/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Dragon class var Dragon = Container.expand(function () { var self = Container.call(this); // Properties self.type = null; // 'wind', 'fire', 'plant', 'bee', 'earth' self.asset = null; self.happy = false; self.waitTime = 0; // ms self.timerText = null; // Set dragon type and visuals self.setType = function (type) { self.type = type; var assetId = 'dragon_' + type; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; // Show impatience timer self.showTimer = function (duration) { if (self.timerText) { self.timerText.destroy(); self.timerText = null; } self.timerText = new Text2('', { size: 60, fill: "#fff" }); self.timerText.anchor.set(0.5, 1); self.timerText.x = 0; self.timerText.y = self.asset.height / 2 + 10; self.addChild(self.timerText); self.waitTime = duration; }; // Update impatience timer self.updateTimer = function (remaining) { if (self.timerText) { var sec = Math.ceil(remaining / 1000); self.timerText.setText(sec); } }; // Remove timer self.removeTimer = function () { if (self.timerText) { self.timerText.destroy(); self.timerText = null; } }; return self; }); // Food class var Food = Container.expand(function () { var self = Container.call(this); self.type = null; // 'soup', 'meat', 'fruit', 'honey', 'insect' self.asset = null; self.dragging = false; self.setType = function (type) { self.type = type; var assetId = 'food_' + type; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222233 }); /**** * Game Code ****/ // Add custom background var backgroundImage = game.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); // --- Game Data --- /* We need: - 5 dragon types (Wind, Fire, Plant, Bee, Earth), each with a unique color/shape. - 5 food types (Soup, Meat, Fruit, Honey, Insect), each with a unique color/shape. - Use simple shapes for MVP. */ // Dragons // Foods // SFX // Music var dragonTypes = [{ type: 'wind', food: 'soup', label: 'Vent', foodLabel: 'Soupe' }, { type: 'fire', food: 'meat', label: 'Feu', foodLabel: 'Viande' }, { type: 'plant', food: 'fruit', label: 'Végétal', foodLabel: 'Fruits' }, { type: 'bee', food: 'honey', label: 'Abeille', foodLabel: 'Miel' }, { type: 'earth', food: 'insect', label: 'Terre', foodLabel: 'Insectes' }]; var foodTypes = [{ s: 'soup', label: 'Soupe' }, { s: 'meat', label: 'Viande' }, { s: 'fruit', label: 'Fruits' }, { s: 'honey', label: 'Miel' }, { s: 'insect', label: 'Insectes' }]; // --- Game State --- var currentDragon = null; var foodTray = []; var dragFood = null; var dragOffsetX = 0; var dragOffsetY = 0; var dragonTimeout = null; var dragonArriveTime = 0; var impatienceDuration = 4000; // ms, decrease with level var score = 0; var level = 1; var dragonsFed = 0; var bonheurs = 0; var bonheurNextLevel = 10; var scoreTxt = null; var levelTxt = null; var bonheurTxt = null; var feedbackTxt = null; // --- UI Setup --- // Score display scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Level display levelTxt = new Text2('Niveau 1', { size: 60, fill: "#fff" }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); levelTxt.y = 120; // Bonheur display bonheurTxt = new Text2('Bonheurs : 0 / 10', { size: 60, fill: 0xFFE066 }); bonheurTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bonheurTxt); bonheurTxt.y = 200; // Feedback text (centered, for "Bravo!", "Mauvais plat!", etc) feedbackTxt = new Text2('', { size: 120, fill: "#fff" }); feedbackTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(feedbackTxt); // --- Helper Functions --- function pickRandomDragon() { var idx = Math.floor(Math.random() * dragonTypes.length); return dragonTypes[idx]; } function spawnDragon() { // Remove previous dragon if (currentDragon) { currentDragon.destroy(); currentDragon = null; } // Pick random dragon var d = pickRandomDragon(); var dragon = new Dragon(); dragon.setType(d.type); // Center dragon dragon.x = 2048 / 2; dragon.y = 900; game.addChild(dragon); // Show impatience timer dragon.showTimer(impatienceDuration); // Add label var label = new Text2(d.label, { size: 70, fill: "#fff" }); label.anchor.set(0.5, 0); label.y = dragon.asset.height / 2 + 60; dragon.addChild(label); currentDragon = dragon; currentDragon.dragonData = d; dragonsFed = dragonsFed; // Play appear sound LK.getSound('appear').play(); // Start impatience timer dragonArriveTime = Date.now(); if (dragonTimeout) LK.clearTimeout(dragonTimeout); dragonTimeout = LK.setTimeout(onDragonTimeout, impatienceDuration); } function setupFoodTray() { // Remove old food for (var i = 0; i < foodTray.length; ++i) { foodTray[i].destroy(); } foodTray = []; // Place foods at bottom, spaced evenly var margin = 180; var total = foodTypes.length; var trayY = 2732 - 250; var trayW = 2048 - margin * 2; for (var i = 0; i < total; ++i) { var f = new Food(); f.setType(foodTypes[i].s); f.x = margin + trayW / (total - 1) * i; f.y = trayY; f.foodData = foodTypes[i]; game.addChild(f); foodTray.push(f); // Add label var t = new Text2(foodTypes[i].label, { size: 48, fill: "#fff" }); t.anchor.set(0.5, 0); t.y = f.asset.height / 2 + 10; f.addChild(t); } } // --- Game Logic --- function onDragonTimeout() { // Dragon got impatient! showFeedback("Trop lent !", 0xff4444); LK.effects.flashScreen(0xff4444, 600); // End game LK.showGameOver(); } function showFeedback(msg, color) { feedbackTxt.setText(msg); feedbackTxt.setStyle({ fill: color ? "#" + color.toString(16).padStart(6, '0') : "#fff" }); feedbackTxt.alpha = 1; tween(feedbackTxt, { alpha: 0 }, { duration: 1200, easing: tween.linear }); } function feedDragon(food) { if (!currentDragon) return; var correct = food.type === currentDragon.dragonData.food; if (correct) { LK.getSound('feed').play(); score += 1; scoreTxt.setText(score); showFeedback("Bravo !", 0x44ff44); dragonsFed += 1; bonheurs += 1; // Met à jour l'affichage des bonheurs bonheurTxt.setText('Bonheurs : ' + bonheurs + ' / ' + bonheurNextLevel); // Système de progression de niveau basé sur les bonheurs if (bonheurs >= bonheurNextLevel) { level += 1; bonheurs = 0; bonheurNextLevel = bonheurNextLevel * 2; levelTxt.setText("Niveau " + level); bonheurTxt.setText('Bonheurs : ' + bonheurs + ' / ' + bonheurNextLevel); impatienceDuration = Math.max(1800, impatienceDuration - 400); showFeedback("Niveau " + level + " !", 0x44aaff); } // Next dragon after short delay if (dragonTimeout) LK.clearTimeout(dragonTimeout); LK.setTimeout(spawnDragon, 700); } else { LK.getSound('wrong').play(); showFeedback("Mauvais plat !", 0xff4444); LK.effects.flashObject(currentDragon, 0xff0000, 600); // End game if (dragonTimeout) LK.clearTimeout(dragonTimeout); LK.setTimeout(function () { LK.showGameOver(); }, 700); } // Remove dragon currentDragon.removeTimer(); currentDragon.happy = true; } // --- Drag & Drop --- function getFoodAt(x, y) { for (var i = 0; i < foodTray.length; ++i) { var f = foodTray[i]; var dx = x - f.x; var dy = y - f.y; var r = f.asset.width / 2 + 30; if (dx * dx + dy * dy < r * r) return f; } return null; } function isOverDragon(food) { if (!currentDragon) return false; // Check intersection return food.intersects(currentDragon); } // --- Event Handlers --- game.down = function (x, y, obj) { // Start drag if on food var f = getFoodAt(x, y); if (f) { dragFood = f; dragFood.dragging = true; dragOffsetX = x - f.x; dragOffsetY = y - f.y; // Bring to front game.removeChild(f); game.addChild(f); } }; game.move = function (x, y, obj) { if (dragFood && dragFood.dragging) { dragFood.x = x - dragOffsetX; dragFood.y = y - dragOffsetY; } }; game.up = function (x, y, obj) { if (dragFood && dragFood.dragging) { // Check if over dragon if (isOverDragon(dragFood)) { feedDragon(dragFood); } // Return food to tray var idx = foodTray.indexOf(dragFood); if (idx !== -1) { // Animate back var targetX = 180 + (2048 - 360) / (foodTray.length - 1) * idx; var targetY = 2732 - 250; tween(dragFood, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut }); } dragFood.dragging = false; dragFood = null; } }; // --- Game Update --- game.update = function () { // Update impatience timer if (currentDragon && !currentDragon.happy) { var now = Date.now(); var elapsed = now - dragonArriveTime; var remain = Math.max(0, impatienceDuration - elapsed); currentDragon.updateTimer(remain); } }; // --- Game Start --- // Play music LK.playMusic('bgmusic', { loop: true }); // Setup food tray setupFoodTray(); // Reset state score = 0; level = 1; dragonsFed = 0; bonheurs = 0; bonheurNextLevel = 10; impatienceDuration = 4000; scoreTxt.setText(score); levelTxt.setText("Niveau 1"); if (bonheurTxt) bonheurTxt.setText('Bonheurs : 0 / 10'); feedbackTxt.setText(''); // Spawn first dragon spawnDragon(); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Dragon class
var Dragon = Container.expand(function () {
var self = Container.call(this);
// Properties
self.type = null; // 'wind', 'fire', 'plant', 'bee', 'earth'
self.asset = null;
self.happy = false;
self.waitTime = 0; // ms
self.timerText = null;
// Set dragon type and visuals
self.setType = function (type) {
self.type = type;
var assetId = 'dragon_' + type;
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
// Show impatience timer
self.showTimer = function (duration) {
if (self.timerText) {
self.timerText.destroy();
self.timerText = null;
}
self.timerText = new Text2('', {
size: 60,
fill: "#fff"
});
self.timerText.anchor.set(0.5, 1);
self.timerText.x = 0;
self.timerText.y = self.asset.height / 2 + 10;
self.addChild(self.timerText);
self.waitTime = duration;
};
// Update impatience timer
self.updateTimer = function (remaining) {
if (self.timerText) {
var sec = Math.ceil(remaining / 1000);
self.timerText.setText(sec);
}
};
// Remove timer
self.removeTimer = function () {
if (self.timerText) {
self.timerText.destroy();
self.timerText = null;
}
};
return self;
});
// Food class
var Food = Container.expand(function () {
var self = Container.call(this);
self.type = null; // 'soup', 'meat', 'fruit', 'honey', 'insect'
self.asset = null;
self.dragging = false;
self.setType = function (type) {
self.type = type;
var assetId = 'food_' + type;
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222233
});
/****
* Game Code
****/
// Add custom background
var backgroundImage = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// --- Game Data ---
/*
We need:
- 5 dragon types (Wind, Fire, Plant, Bee, Earth), each with a unique color/shape.
- 5 food types (Soup, Meat, Fruit, Honey, Insect), each with a unique color/shape.
- Use simple shapes for MVP.
*/
// Dragons
// Foods
// SFX
// Music
var dragonTypes = [{
type: 'wind',
food: 'soup',
label: 'Vent',
foodLabel: 'Soupe'
}, {
type: 'fire',
food: 'meat',
label: 'Feu',
foodLabel: 'Viande'
}, {
type: 'plant',
food: 'fruit',
label: 'Végétal',
foodLabel: 'Fruits'
}, {
type: 'bee',
food: 'honey',
label: 'Abeille',
foodLabel: 'Miel'
}, {
type: 'earth',
food: 'insect',
label: 'Terre',
foodLabel: 'Insectes'
}];
var foodTypes = [{
s: 'soup',
label: 'Soupe'
}, {
s: 'meat',
label: 'Viande'
}, {
s: 'fruit',
label: 'Fruits'
}, {
s: 'honey',
label: 'Miel'
}, {
s: 'insect',
label: 'Insectes'
}];
// --- Game State ---
var currentDragon = null;
var foodTray = [];
var dragFood = null;
var dragOffsetX = 0;
var dragOffsetY = 0;
var dragonTimeout = null;
var dragonArriveTime = 0;
var impatienceDuration = 4000; // ms, decrease with level
var score = 0;
var level = 1;
var dragonsFed = 0;
var bonheurs = 0;
var bonheurNextLevel = 10;
var scoreTxt = null;
var levelTxt = null;
var bonheurTxt = null;
var feedbackTxt = null;
// --- UI Setup ---
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Level display
levelTxt = new Text2('Niveau 1', {
size: 60,
fill: "#fff"
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 120;
// Bonheur display
bonheurTxt = new Text2('Bonheurs : 0 / 10', {
size: 60,
fill: 0xFFE066
});
bonheurTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(bonheurTxt);
bonheurTxt.y = 200;
// Feedback text (centered, for "Bravo!", "Mauvais plat!", etc)
feedbackTxt = new Text2('', {
size: 120,
fill: "#fff"
});
feedbackTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(feedbackTxt);
// --- Helper Functions ---
function pickRandomDragon() {
var idx = Math.floor(Math.random() * dragonTypes.length);
return dragonTypes[idx];
}
function spawnDragon() {
// Remove previous dragon
if (currentDragon) {
currentDragon.destroy();
currentDragon = null;
}
// Pick random dragon
var d = pickRandomDragon();
var dragon = new Dragon();
dragon.setType(d.type);
// Center dragon
dragon.x = 2048 / 2;
dragon.y = 900;
game.addChild(dragon);
// Show impatience timer
dragon.showTimer(impatienceDuration);
// Add label
var label = new Text2(d.label, {
size: 70,
fill: "#fff"
});
label.anchor.set(0.5, 0);
label.y = dragon.asset.height / 2 + 60;
dragon.addChild(label);
currentDragon = dragon;
currentDragon.dragonData = d;
dragonsFed = dragonsFed;
// Play appear sound
LK.getSound('appear').play();
// Start impatience timer
dragonArriveTime = Date.now();
if (dragonTimeout) LK.clearTimeout(dragonTimeout);
dragonTimeout = LK.setTimeout(onDragonTimeout, impatienceDuration);
}
function setupFoodTray() {
// Remove old food
for (var i = 0; i < foodTray.length; ++i) {
foodTray[i].destroy();
}
foodTray = [];
// Place foods at bottom, spaced evenly
var margin = 180;
var total = foodTypes.length;
var trayY = 2732 - 250;
var trayW = 2048 - margin * 2;
for (var i = 0; i < total; ++i) {
var f = new Food();
f.setType(foodTypes[i].s);
f.x = margin + trayW / (total - 1) * i;
f.y = trayY;
f.foodData = foodTypes[i];
game.addChild(f);
foodTray.push(f);
// Add label
var t = new Text2(foodTypes[i].label, {
size: 48,
fill: "#fff"
});
t.anchor.set(0.5, 0);
t.y = f.asset.height / 2 + 10;
f.addChild(t);
}
}
// --- Game Logic ---
function onDragonTimeout() {
// Dragon got impatient!
showFeedback("Trop lent !", 0xff4444);
LK.effects.flashScreen(0xff4444, 600);
// End game
LK.showGameOver();
}
function showFeedback(msg, color) {
feedbackTxt.setText(msg);
feedbackTxt.setStyle({
fill: color ? "#" + color.toString(16).padStart(6, '0') : "#fff"
});
feedbackTxt.alpha = 1;
tween(feedbackTxt, {
alpha: 0
}, {
duration: 1200,
easing: tween.linear
});
}
function feedDragon(food) {
if (!currentDragon) return;
var correct = food.type === currentDragon.dragonData.food;
if (correct) {
LK.getSound('feed').play();
score += 1;
scoreTxt.setText(score);
showFeedback("Bravo !", 0x44ff44);
dragonsFed += 1;
bonheurs += 1;
// Met à jour l'affichage des bonheurs
bonheurTxt.setText('Bonheurs : ' + bonheurs + ' / ' + bonheurNextLevel);
// Système de progression de niveau basé sur les bonheurs
if (bonheurs >= bonheurNextLevel) {
level += 1;
bonheurs = 0;
bonheurNextLevel = bonheurNextLevel * 2;
levelTxt.setText("Niveau " + level);
bonheurTxt.setText('Bonheurs : ' + bonheurs + ' / ' + bonheurNextLevel);
impatienceDuration = Math.max(1800, impatienceDuration - 400);
showFeedback("Niveau " + level + " !", 0x44aaff);
}
// Next dragon after short delay
if (dragonTimeout) LK.clearTimeout(dragonTimeout);
LK.setTimeout(spawnDragon, 700);
} else {
LK.getSound('wrong').play();
showFeedback("Mauvais plat !", 0xff4444);
LK.effects.flashObject(currentDragon, 0xff0000, 600);
// End game
if (dragonTimeout) LK.clearTimeout(dragonTimeout);
LK.setTimeout(function () {
LK.showGameOver();
}, 700);
}
// Remove dragon
currentDragon.removeTimer();
currentDragon.happy = true;
}
// --- Drag & Drop ---
function getFoodAt(x, y) {
for (var i = 0; i < foodTray.length; ++i) {
var f = foodTray[i];
var dx = x - f.x;
var dy = y - f.y;
var r = f.asset.width / 2 + 30;
if (dx * dx + dy * dy < r * r) return f;
}
return null;
}
function isOverDragon(food) {
if (!currentDragon) return false;
// Check intersection
return food.intersects(currentDragon);
}
// --- Event Handlers ---
game.down = function (x, y, obj) {
// Start drag if on food
var f = getFoodAt(x, y);
if (f) {
dragFood = f;
dragFood.dragging = true;
dragOffsetX = x - f.x;
dragOffsetY = y - f.y;
// Bring to front
game.removeChild(f);
game.addChild(f);
}
};
game.move = function (x, y, obj) {
if (dragFood && dragFood.dragging) {
dragFood.x = x - dragOffsetX;
dragFood.y = y - dragOffsetY;
}
};
game.up = function (x, y, obj) {
if (dragFood && dragFood.dragging) {
// Check if over dragon
if (isOverDragon(dragFood)) {
feedDragon(dragFood);
}
// Return food to tray
var idx = foodTray.indexOf(dragFood);
if (idx !== -1) {
// Animate back
var targetX = 180 + (2048 - 360) / (foodTray.length - 1) * idx;
var targetY = 2732 - 250;
tween(dragFood, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut
});
}
dragFood.dragging = false;
dragFood = null;
}
};
// --- Game Update ---
game.update = function () {
// Update impatience timer
if (currentDragon && !currentDragon.happy) {
var now = Date.now();
var elapsed = now - dragonArriveTime;
var remain = Math.max(0, impatienceDuration - elapsed);
currentDragon.updateTimer(remain);
}
};
// --- Game Start ---
// Play music
LK.playMusic('bgmusic', {
loop: true
});
// Setup food tray
setupFoodTray();
// Reset state
score = 0;
level = 1;
dragonsFed = 0;
bonheurs = 0;
bonheurNextLevel = 10;
impatienceDuration = 4000;
scoreTxt.setText(score);
levelTxt.setText("Niveau 1");
if (bonheurTxt) bonheurTxt.setText('Bonheurs : 0 / 10');
feedbackTxt.setText('');
// Spawn first dragon
spawnDragon();
;
Dragon abeille. In-Game asset. 2d. High contrast. No shadows
Dragon feu. In-Game asset. 2d. High contrast. No shadows
Dragon terre. In-Game asset. 2d. High contrast. No shadows
Dragon vent. In-Game asset. 2d. High contrast. No shadows
Soupe. In-Game asset. 2d. High contrast. No shadows
Miel. In-Game asset. 2d. High contrast. No shadows
Viande. In-Game asset. 2d. High contrast. No shadows
Dragon végétal. In-Game asset. 2d. High contrast. No shadows
Fruit. In-Game asset. 2d. High contrast. No shadows
Insecte. In-Game asset. 2d. High contrast. No shadows
Fond d'écran tanière de dragons. In-Game asset. 2d. High contrast. No shadows