/****
* 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