/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
level: 1
});
/****
* Classes
****/
// Classe pour les abeilles adversaires
var EnemyBee = Container.expand(function () {
var self = Container.call(this);
// Couleur différente selon l'index
var colorId = self.colorId || 1;
var assetId = 'bee_enemy' + colorId;
var bee = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bee.width;
self.height = bee.height;
self.lane = 0;
self.speed = 0;
self.avoidCooldown = 0;
self.update = function () {
// Avance automatiquement
self.x += self.speed;
// Petite oscillation pour donner vie
bee.y = Math.sin(LK.ticks / 20 + self.lane) * 10;
};
// Pour éviter un obstacle, saute sur le côté (change de voie)
self.tryAvoid = function (obstacles) {
if (self.avoidCooldown > 0) {
self.avoidCooldown--;
return;
}
// Si un obstacle est proche devant, tente d'éviter
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
if (obs.lane === self.lane && obs.x > self.x && obs.x - self.x < 180) {
// Tente de changer de voie (aléatoire)
var dirs = [];
if (self.lane > 0) dirs.push(-1);
if (self.lane < 4) dirs.push(1);
if (dirs.length > 0) {
var dir = dirs[Math.floor(Math.random() * dirs.length)];
self.lane += dir;
self.y = laneY(self.lane);
self.avoidCooldown = 30 + Math.floor(Math.random() * 20);
}
break;
}
}
};
return self;
});
// Classe pour l'abeille du joueur
var PlayerBee = Container.expand(function () {
var self = Container.call(this);
var bee = self.attachAsset('bee_player', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bee.width;
self.height = bee.height;
self.lane = 2; // Par défaut, voie centrale (0-4)
self.isJumping = false;
self.jumpStartY = 0;
self.jumpStartX = 0;
self.jumpTargetY = 0;
self.jumpTargetX = 0;
self.jumpProgress = 0;
self.jumpDuration = 10; // frames, bond plus court
self.targetLane = self.lane;
self.targetX = 0;
self.update = function () {
// Synchronise la vitesse de déplacement avec les abeilles adversaires
// On prend la vitesse moyenne des ennemis pour la course actuelle
var avgSpeed = 0;
if (typeof enemyBees !== "undefined" && enemyBees.length > 0) {
var total = 0;
for (var i = 0; i < enemyBees.length; i++) {
total += enemyBees[i].speed;
}
avgSpeed = total / enemyBees.length;
} else {
avgSpeed = 7 + level * 1.5; // fallback
}
// Gestion du bond (court et latéral)
if (self.isJumping) {
self.jumpProgress++;
var t = self.jumpProgress / self.jumpDuration;
// Interpolation linéaire pour X et Y
self.x = self.jumpStartX + (self.jumpTargetX - self.jumpStartX) * t;
self.y = self.jumpStartY + (self.jumpTargetY - self.jumpStartY) * t - Math.sin(Math.PI * t) * 40;
if (self.jumpProgress >= self.jumpDuration) {
self.isJumping = false;
self.x = self.jumpTargetX;
self.y = self.jumpTargetY;
self.lane = self.targetLane;
}
} else {
// Si pas en saut, avance automatiquement à la même vitesse que les ennemis
self.x += avgSpeed;
}
};
// Prépare un bond court vers la position cible (tap ou drag)
self.prepareJump = function () {
if (self.isJumping) return;
// Bond court : distance max 120 px par bond
var dx = self.targetX - self.x;
var maxDist = 120;
if (Math.abs(dx) > maxDist) {
self.jumpTargetX = self.x + (dx > 0 ? maxDist : -maxDist);
} else {
self.jumpTargetX = self.targetX;
}
// Cible Y = voie choisie
self.jumpStartY = self.y;
self.jumpStartX = self.x;
self.jumpTargetY = laneY(self.targetLane);
self.jumpProgress = 0;
self.isJumping = true;
};
// Pour compatibilité avec l'ancien code (tap simple)
self.jump = function () {
if (self.isJumping) return;
self.targetLane = self.lane;
self.targetX = self.x + 80; // bond court vers la droite
self.prepareJump();
};
return self;
});
// Classe pour les obstacles (arbres)
var TreeObstacle = Container.expand(function () {
var self = Container.call(this);
var tree = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1
});
self.width = tree.width;
self.height = tree.height;
self.lane = 0;
self.update = function () {
// Les obstacles ne bougent pas, mais pourraient bouger à haut niveau
if (level >= 4) {
// Oscillation horizontale
self.x += Math.sin(LK.ticks / 40 + self.lane) * 0.7;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2e3c1c
});
/****
* Game Code
****/
// Ajout de l'asset image de fond personnalisé (remplacez l'id par celui de votre image)
// --- Variables globales ---
// Abeille du joueur
// Abeilles adversaires (4 couleurs différentes)
// Obstacles (arbres)
// Ligne d'arrivée
var level = storage.level || 1;
var lanes = [0, 1, 2, 3, 4]; // 5 voies horizontales
var laneSpacing = 350;
var startX = 200;
var finishX = 2048 - 200;
var playerBee;
var enemyBees = [];
var obstacles = [];
var finishLine;
var scoreTxt;
var levelTxt;
var dragNode = null;
var gameOver = false;
// --- Fonctions utilitaires ---
function laneY(lane) {
// Espace verticalement les voies
return 500 + lane * laneSpacing;
}
// --- Initialisation du jeu ---
function setupGame() {
// Nettoyage
game.removeChildren();
enemyBees = [];
obstacles = [];
gameOver = false;
// Ajout de l'image de fond personnalisé (doit être le premier enfant pour être en fond)
var bg = LK.getAsset('forest_bg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(bg);
// Ligne d'arrivée
finishLine = LK.getAsset('finish_line', {
anchorX: 0,
anchorY: 0
});
finishLine.x = 0;
finishLine.y = 350;
game.addChild(finishLine);
// Score (niveau)
if (!scoreTxt) {
scoreTxt = new Text2('Niveau: ' + level, {
size: 90,
fill: '#ff69b4' //{1f} // Rose
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
}
scoreTxt.setText('Niveau: ' + level);
// Affichage du niveau (en haut à droite)
if (!levelTxt) {
levelTxt = new Text2('', {
size: 60,
fill: '#ff69b4' //{1i} // Rose
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
}
levelTxt.setText('Course des abeilles');
// Joueur
playerBee = new PlayerBee();
playerBee.lane = 2;
playerBee.x = startX;
playerBee.y = laneY(playerBee.lane);
game.addChild(playerBee);
// Abeilles adversaires
for (var i = 0; i < 4; i++) {
var bee = new EnemyBee();
bee.colorId = i + 1;
bee.lane = i < 2 ? i : i + 1; // Sauter la voie centrale pour le joueur
bee.x = startX;
bee.y = laneY(bee.lane);
bee.speed = 7 + level * 1.5 + Math.random() * 2;
game.addChild(bee);
enemyBees.push(bee);
}
// Obstacles
var nbObstacles = 3 + Math.floor(level * 0.7);
for (var i = 0; i < nbObstacles; i++) {
var obs = new TreeObstacle();
obs.lane = Math.floor(Math.random() * 5);
obs.x = 600 + Math.random() * (finishX - 800);
obs.y = laneY(obs.lane) + 60;
game.addChild(obs);
obstacles.push(obs);
}
// Ligne d'arrivée (visuelle)
finishLine.y = laneY(0) - 80;
finishLine.height = laneSpacing * 5 + 60;
}
// --- Contrôles joueur ---
// Permet de déplacer l'abeille du joueur vers la position touchée (tap ou drag), avec un bond court à chaque appui
game.down = function (x, y, obj) {
if (gameOver) return;
// On convertit la position touchée en coordonnées de jeu
var local = game.toLocal({
x: x,
y: y
});
// On cherche la voie la plus proche de la position touchée
var minDist = Infinity;
var bestLane = playerBee.lane;
for (var i = 0; i < lanes.length; i++) {
var ly = laneY(lanes[i]);
var dist = Math.abs(local.y - ly);
if (dist < minDist) {
minDist = dist;
bestLane = lanes[i];
}
}
// On déplace l'abeille sur la voie la plus proche et on prépare le bond
playerBee.targetLane = bestLane;
playerBee.targetX = Math.min(local.x, finishX); // Ne pas dépasser la ligne d'arrivée
playerBee.prepareJump();
};
game.move = function (x, y, obj) {
if (gameOver) return;
// Permet de déplacer l'abeille en glissant le doigt (drag)
var local = game.toLocal({
x: x,
y: y
});
var minDist = Infinity;
var bestLane = playerBee.lane;
for (var i = 0; i < lanes.length; i++) {
var ly = laneY(lanes[i]);
var dist = Math.abs(local.y - ly);
if (dist < minDist) {
minDist = dist;
bestLane = lanes[i];
}
}
playerBee.targetLane = bestLane;
playerBee.targetX = Math.min(local.x, finishX);
playerBee.prepareJump();
};
game.up = function (x, y, obj) {
// Rien à faire ici
};
// --- Boucle principale ---
game.update = function () {
if (gameOver) return;
// Update player
playerBee.update();
// Update ennemis
for (var i = 0; i < enemyBees.length; i++) {
var bee = enemyBees[i];
bee.update();
bee.tryAvoid(obstacles);
}
// Update obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
// --- Collisions joueur/obstacles ---
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
// Collision si même voie et x proche
if (playerBee.lane === obs.lane && Math.abs(playerBee.x - obs.x) < 70) {
// Perdu !
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
storage.level = 1;
LK.setTimeout(function () {
LK.showGameOver();
}, 700);
return;
}
}
// --- Collisions ennemis/obstacles (ils évitent, mais si collision, ralentissent) ---
for (var i = 0; i < enemyBees.length; i++) {
var bee = enemyBees[i];
for (var j = 0; j < obstacles.length; j++) {
var obs = obstacles[j];
if (bee.lane === obs.lane && Math.abs(bee.x - obs.x) < 70) {
bee.speed *= 0.7;
}
}
}
// --- Arrivée joueur ---
if (playerBee.x >= finishX) {
// Gagné !
LK.effects.flashScreen(0xffff00, 800);
gameOver = true;
storage.level = level + 1;
LK.setTimeout(function () {
LK.showYouWin();
}, 700);
return;
}
// --- Arrivée ennemis ---
for (var i = 0; i < enemyBees.length; i++) {
if (enemyBees[i].x >= finishX) {
// Perdu !
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
storage.level = 1;
LK.setTimeout(function () {
LK.showGameOver();
}, 700);
return;
}
}
};
// --- Démarrage ---
setupGame();
LK.playMusic('bee_race_music');
// --- Gestion du reset automatique par LK ---
LK.on('reset', function () {
level = storage.level || 1;
setupGame();
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
level: 1
});
/****
* Classes
****/
// Classe pour les abeilles adversaires
var EnemyBee = Container.expand(function () {
var self = Container.call(this);
// Couleur différente selon l'index
var colorId = self.colorId || 1;
var assetId = 'bee_enemy' + colorId;
var bee = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bee.width;
self.height = bee.height;
self.lane = 0;
self.speed = 0;
self.avoidCooldown = 0;
self.update = function () {
// Avance automatiquement
self.x += self.speed;
// Petite oscillation pour donner vie
bee.y = Math.sin(LK.ticks / 20 + self.lane) * 10;
};
// Pour éviter un obstacle, saute sur le côté (change de voie)
self.tryAvoid = function (obstacles) {
if (self.avoidCooldown > 0) {
self.avoidCooldown--;
return;
}
// Si un obstacle est proche devant, tente d'éviter
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
if (obs.lane === self.lane && obs.x > self.x && obs.x - self.x < 180) {
// Tente de changer de voie (aléatoire)
var dirs = [];
if (self.lane > 0) dirs.push(-1);
if (self.lane < 4) dirs.push(1);
if (dirs.length > 0) {
var dir = dirs[Math.floor(Math.random() * dirs.length)];
self.lane += dir;
self.y = laneY(self.lane);
self.avoidCooldown = 30 + Math.floor(Math.random() * 20);
}
break;
}
}
};
return self;
});
// Classe pour l'abeille du joueur
var PlayerBee = Container.expand(function () {
var self = Container.call(this);
var bee = self.attachAsset('bee_player', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bee.width;
self.height = bee.height;
self.lane = 2; // Par défaut, voie centrale (0-4)
self.isJumping = false;
self.jumpStartY = 0;
self.jumpStartX = 0;
self.jumpTargetY = 0;
self.jumpTargetX = 0;
self.jumpProgress = 0;
self.jumpDuration = 10; // frames, bond plus court
self.targetLane = self.lane;
self.targetX = 0;
self.update = function () {
// Synchronise la vitesse de déplacement avec les abeilles adversaires
// On prend la vitesse moyenne des ennemis pour la course actuelle
var avgSpeed = 0;
if (typeof enemyBees !== "undefined" && enemyBees.length > 0) {
var total = 0;
for (var i = 0; i < enemyBees.length; i++) {
total += enemyBees[i].speed;
}
avgSpeed = total / enemyBees.length;
} else {
avgSpeed = 7 + level * 1.5; // fallback
}
// Gestion du bond (court et latéral)
if (self.isJumping) {
self.jumpProgress++;
var t = self.jumpProgress / self.jumpDuration;
// Interpolation linéaire pour X et Y
self.x = self.jumpStartX + (self.jumpTargetX - self.jumpStartX) * t;
self.y = self.jumpStartY + (self.jumpTargetY - self.jumpStartY) * t - Math.sin(Math.PI * t) * 40;
if (self.jumpProgress >= self.jumpDuration) {
self.isJumping = false;
self.x = self.jumpTargetX;
self.y = self.jumpTargetY;
self.lane = self.targetLane;
}
} else {
// Si pas en saut, avance automatiquement à la même vitesse que les ennemis
self.x += avgSpeed;
}
};
// Prépare un bond court vers la position cible (tap ou drag)
self.prepareJump = function () {
if (self.isJumping) return;
// Bond court : distance max 120 px par bond
var dx = self.targetX - self.x;
var maxDist = 120;
if (Math.abs(dx) > maxDist) {
self.jumpTargetX = self.x + (dx > 0 ? maxDist : -maxDist);
} else {
self.jumpTargetX = self.targetX;
}
// Cible Y = voie choisie
self.jumpStartY = self.y;
self.jumpStartX = self.x;
self.jumpTargetY = laneY(self.targetLane);
self.jumpProgress = 0;
self.isJumping = true;
};
// Pour compatibilité avec l'ancien code (tap simple)
self.jump = function () {
if (self.isJumping) return;
self.targetLane = self.lane;
self.targetX = self.x + 80; // bond court vers la droite
self.prepareJump();
};
return self;
});
// Classe pour les obstacles (arbres)
var TreeObstacle = Container.expand(function () {
var self = Container.call(this);
var tree = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1
});
self.width = tree.width;
self.height = tree.height;
self.lane = 0;
self.update = function () {
// Les obstacles ne bougent pas, mais pourraient bouger à haut niveau
if (level >= 4) {
// Oscillation horizontale
self.x += Math.sin(LK.ticks / 40 + self.lane) * 0.7;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2e3c1c
});
/****
* Game Code
****/
// Ajout de l'asset image de fond personnalisé (remplacez l'id par celui de votre image)
// --- Variables globales ---
// Abeille du joueur
// Abeilles adversaires (4 couleurs différentes)
// Obstacles (arbres)
// Ligne d'arrivée
var level = storage.level || 1;
var lanes = [0, 1, 2, 3, 4]; // 5 voies horizontales
var laneSpacing = 350;
var startX = 200;
var finishX = 2048 - 200;
var playerBee;
var enemyBees = [];
var obstacles = [];
var finishLine;
var scoreTxt;
var levelTxt;
var dragNode = null;
var gameOver = false;
// --- Fonctions utilitaires ---
function laneY(lane) {
// Espace verticalement les voies
return 500 + lane * laneSpacing;
}
// --- Initialisation du jeu ---
function setupGame() {
// Nettoyage
game.removeChildren();
enemyBees = [];
obstacles = [];
gameOver = false;
// Ajout de l'image de fond personnalisé (doit être le premier enfant pour être en fond)
var bg = LK.getAsset('forest_bg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(bg);
// Ligne d'arrivée
finishLine = LK.getAsset('finish_line', {
anchorX: 0,
anchorY: 0
});
finishLine.x = 0;
finishLine.y = 350;
game.addChild(finishLine);
// Score (niveau)
if (!scoreTxt) {
scoreTxt = new Text2('Niveau: ' + level, {
size: 90,
fill: '#ff69b4' //{1f} // Rose
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
}
scoreTxt.setText('Niveau: ' + level);
// Affichage du niveau (en haut à droite)
if (!levelTxt) {
levelTxt = new Text2('', {
size: 60,
fill: '#ff69b4' //{1i} // Rose
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
}
levelTxt.setText('Course des abeilles');
// Joueur
playerBee = new PlayerBee();
playerBee.lane = 2;
playerBee.x = startX;
playerBee.y = laneY(playerBee.lane);
game.addChild(playerBee);
// Abeilles adversaires
for (var i = 0; i < 4; i++) {
var bee = new EnemyBee();
bee.colorId = i + 1;
bee.lane = i < 2 ? i : i + 1; // Sauter la voie centrale pour le joueur
bee.x = startX;
bee.y = laneY(bee.lane);
bee.speed = 7 + level * 1.5 + Math.random() * 2;
game.addChild(bee);
enemyBees.push(bee);
}
// Obstacles
var nbObstacles = 3 + Math.floor(level * 0.7);
for (var i = 0; i < nbObstacles; i++) {
var obs = new TreeObstacle();
obs.lane = Math.floor(Math.random() * 5);
obs.x = 600 + Math.random() * (finishX - 800);
obs.y = laneY(obs.lane) + 60;
game.addChild(obs);
obstacles.push(obs);
}
// Ligne d'arrivée (visuelle)
finishLine.y = laneY(0) - 80;
finishLine.height = laneSpacing * 5 + 60;
}
// --- Contrôles joueur ---
// Permet de déplacer l'abeille du joueur vers la position touchée (tap ou drag), avec un bond court à chaque appui
game.down = function (x, y, obj) {
if (gameOver) return;
// On convertit la position touchée en coordonnées de jeu
var local = game.toLocal({
x: x,
y: y
});
// On cherche la voie la plus proche de la position touchée
var minDist = Infinity;
var bestLane = playerBee.lane;
for (var i = 0; i < lanes.length; i++) {
var ly = laneY(lanes[i]);
var dist = Math.abs(local.y - ly);
if (dist < minDist) {
minDist = dist;
bestLane = lanes[i];
}
}
// On déplace l'abeille sur la voie la plus proche et on prépare le bond
playerBee.targetLane = bestLane;
playerBee.targetX = Math.min(local.x, finishX); // Ne pas dépasser la ligne d'arrivée
playerBee.prepareJump();
};
game.move = function (x, y, obj) {
if (gameOver) return;
// Permet de déplacer l'abeille en glissant le doigt (drag)
var local = game.toLocal({
x: x,
y: y
});
var minDist = Infinity;
var bestLane = playerBee.lane;
for (var i = 0; i < lanes.length; i++) {
var ly = laneY(lanes[i]);
var dist = Math.abs(local.y - ly);
if (dist < minDist) {
minDist = dist;
bestLane = lanes[i];
}
}
playerBee.targetLane = bestLane;
playerBee.targetX = Math.min(local.x, finishX);
playerBee.prepareJump();
};
game.up = function (x, y, obj) {
// Rien à faire ici
};
// --- Boucle principale ---
game.update = function () {
if (gameOver) return;
// Update player
playerBee.update();
// Update ennemis
for (var i = 0; i < enemyBees.length; i++) {
var bee = enemyBees[i];
bee.update();
bee.tryAvoid(obstacles);
}
// Update obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
// --- Collisions joueur/obstacles ---
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
// Collision si même voie et x proche
if (playerBee.lane === obs.lane && Math.abs(playerBee.x - obs.x) < 70) {
// Perdu !
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
storage.level = 1;
LK.setTimeout(function () {
LK.showGameOver();
}, 700);
return;
}
}
// --- Collisions ennemis/obstacles (ils évitent, mais si collision, ralentissent) ---
for (var i = 0; i < enemyBees.length; i++) {
var bee = enemyBees[i];
for (var j = 0; j < obstacles.length; j++) {
var obs = obstacles[j];
if (bee.lane === obs.lane && Math.abs(bee.x - obs.x) < 70) {
bee.speed *= 0.7;
}
}
}
// --- Arrivée joueur ---
if (playerBee.x >= finishX) {
// Gagné !
LK.effects.flashScreen(0xffff00, 800);
gameOver = true;
storage.level = level + 1;
LK.setTimeout(function () {
LK.showYouWin();
}, 700);
return;
}
// --- Arrivée ennemis ---
for (var i = 0; i < enemyBees.length; i++) {
if (enemyBees[i].x >= finishX) {
// Perdu !
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
storage.level = 1;
LK.setTimeout(function () {
LK.showGameOver();
}, 700);
return;
}
}
};
// --- Démarrage ---
setupGame();
LK.playMusic('bee_race_music');
// --- Gestion du reset automatique par LK ---
LK.on('reset', function () {
level = storage.level || 1;
setupGame();
});
Arbre. In-Game asset. 2d. High contrast. No shadows
Abeille rouge. In-Game asset. 2d. High contrast. No shadows
Abeille bleu. In-Game asset. 2d. High contrast. No shadows
Abeille verte. In-Game asset. 2d. High contrast. No shadows
Abeille orange. In-Game asset. 2d. High contrast. No shadows
Abeille jaune. In-Game asset. 2d. High contrast. No shadows
Fond d'écran forêt. In-Game asset. 2d. High contrast. No shadows