/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Obstacle: acid pool (hazard) var Acid = Container.expand(function () { var self = Container.call(this); var acid = self.attachAsset('acid', { anchorX: 0.5, anchorY: 0.5 }); // Acid can move left/right for challenge self.speed = 0; self.direction = 1; self.update = function () { if (self.speed !== 0) { self.x += self.speed * self.direction; if (self.x < 200 || self.x > 2048 - 200) { self.direction *= -1; } } }; return self; }); // Animal base class var Animal = Container.expand(function () { var self = Container.call(this); // These will be set by subclasses self.assetId = ''; self.moveType = 'normal'; // 'normal', 'hop', 'slide', 'float', etc. self.speed = 12; // Default speed self.jumpPower = 0; // For animals that can jump self.gravity = 0; // For animals affected by gravity self.vy = 0; // Vertical velocity // Attach animal asset var animalSprite = self.attachAsset(self.assetId, { anchorX: 0.5, anchorY: 0.5 }); // Used for per-animal movement logic self.update = function () { // Movement logic handled in main game loop }; // Called when switching to this animal self.onSwitchIn = function () { // Flash or animate to show selection tween(animalSprite, { scaleX: 1.2, scaleY: 1.2 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(animalSprite, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.easeIn }); } }); }; // Called when switching away from this animal self.onSwitchOut = function () { // No-op for now }; return self; }); // Snail: very slow, can stick to walls var Snail = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'snail'; self.speed = 4; return self; }); // Polar Bear: slow, immune to acid var PolarBear = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'polarBear'; self.speed = 7; return self; }); // Pig: slow, can push food chunks var Pig = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'pig'; self.speed = 8; return self; }); // Frog: can hop var Frog = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'frog'; self.speed = 10; self.jumpPower = 48; self.gravity = 3.5; self.isJumping = false; return self; }); // Elephant: can push obstacles, slowest var Elephant = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'elephant'; self.speed = 6; return self; }); // Cat: fast, can jump var Cat = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'cat'; self.speed = 16; self.jumpPower = 38; self.gravity = 3.2; self.isJumping = false; return self; }); // Bird: can fly (ignores gravity) var Bird = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'bird'; self.speed = 13; self.moveType = 'fly'; return self; }); // Bee: can float over acid, moves in short bursts var Bee = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'bee'; self.speed = 10; self.moveType = 'float'; return self; }); // Axolotl: can swim in acid, normal speed var Axolotl = Animal.expand(function () { var self = Animal.call(this); self.assetId = 'axolotl'; self.speed = 11; self.moveType = 'swim'; return self; }); // Obstacle: food chunk (movable) var FoodChunk = Container.expand(function () { var self = Container.call(this); var chunk = self.attachAsset('foodChunk', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () {}; return self; }); // Obstacle: stomach wall (static) var StomachWall = Container.expand(function () { var self = Container.call(this); var wall = self.attachAsset('stomachWall', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Touch button for animal switching var SwitchButton = Container.expand(function () { var self = Container.call(this); var btn = self.attachAsset('switchBtn', { anchorX: 0.5, anchorY: 0.5 }); self.icon = null; // Will be set to animal icon return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2d1b0c // Deep brown, snake belly }); /**** * Game Code ****/ // Touch button shapes // Obstacle shapes // Animal shapes (unique color for each animal) // --- Game constants --- var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var PLAY_AREA_TOP = 200; var PLAY_AREA_BOTTOM = GAME_HEIGHT - 200; var PLAY_AREA_LEFT = 100; var PLAY_AREA_RIGHT = GAME_WIDTH - 100; // --- Animal roster and order --- var animalClasses = [Pig, Cat, Bee, Frog, PolarBear, Elephant, Bird, Snail, Axolotl]; var animalNames = ['Pig', 'Cat', 'Bee', 'Frog', 'Polar Bear', 'Elephant', 'Bird', 'Snail', 'Axolotl']; var animalIcons = ['pig', 'cat', 'bee', 'frog', 'polarBear', 'elephant', 'bird', 'snail', 'axolotl']; var animals = []; var currentAnimalIdx = 0; var currentAnimal = null; // --- Obstacles and hazards --- var obstacles = []; var acids = []; var foodChunks = []; // --- UI --- var switchButtons = []; var switchBtnY = GAME_HEIGHT - 180; var switchBtnSpacing = 200; var infoText = null; // --- Dragging --- var dragNode = null; var dragOffsetX = 0; var dragOffsetY = 0; // --- Game state --- var isMovingLeft = false; var isMovingRight = false; var isMovingUp = false; var isMovingDown = false; var isJumping = false; var isSwitching = false; var gameStarted = false; var gameOver = false; var youWin = false; // --- Level layout (simple for MVP) --- function setupLevel() { // Clear previous for (var i = 0; i < obstacles.length; ++i) obstacles[i].destroy(); for (var i = 0; i < acids.length; ++i) acids[i].destroy(); for (var i = 0; i < foodChunks.length; ++i) foodChunks[i].destroy(); obstacles = []; acids = []; foodChunks = []; // Top and bottom stomach walls var wallTop = new StomachWall(); wallTop.x = GAME_WIDTH / 2; wallTop.y = PLAY_AREA_TOP - 40; obstacles.push(wallTop); game.addChild(wallTop); var wallBottom = new StomachWall(); wallBottom.x = GAME_WIDTH / 2; wallBottom.y = PLAY_AREA_BOTTOM + 40; obstacles.push(wallBottom); game.addChild(wallBottom); // Acid pools (hazards) var acid1 = new Acid(); acid1.x = GAME_WIDTH / 2; acid1.y = PLAY_AREA_TOP + 400; acid1.speed = 6; acids.push(acid1); game.addChild(acid1); var acid2 = new Acid(); acid2.x = GAME_WIDTH / 2 + 400; acid2.y = PLAY_AREA_TOP + 900; acid2.speed = 0; acids.push(acid2); game.addChild(acid2); // Food chunks (movable obstacles) var chunk1 = new FoodChunk(); chunk1.x = GAME_WIDTH / 2 - 300; chunk1.y = PLAY_AREA_TOP + 700; foodChunks.push(chunk1); game.addChild(chunk1); var chunk2 = new FoodChunk(); chunk2.x = GAME_WIDTH / 2 + 300; chunk2.y = PLAY_AREA_TOP + 1200; foodChunks.push(chunk2); game.addChild(chunk2); // More obstacles can be added for future levels } // --- Animal setup --- function setupAnimals() { // Remove previous for (var i = 0; i < animals.length; ++i) animals[i].destroy(); animals = []; // Place all animals at start, stacked var startX = GAME_WIDTH / 2; var startY = PLAY_AREA_BOTTOM - 200; for (var i = 0; i < animalClasses.length; ++i) { var animal = new animalClasses[i](); animal.x = startX + (i - 4) * 40; animal.y = startY - i * 40; animal.zIndex = i; animal.visible = false; animals.push(animal); game.addChild(animal); } // Set first animal active currentAnimalIdx = 0; currentAnimal = animals[currentAnimalIdx]; currentAnimal.visible = true; currentAnimal.onSwitchIn(); } // --- UI setup --- function setupUI() { // Remove previous for (var i = 0; i < switchButtons.length; ++i) switchButtons[i].destroy(); switchButtons = []; // Create switch buttons for each animal var btnStartX = GAME_WIDTH / 2 - (animalClasses.length - 1) / 2 * switchBtnSpacing; for (var i = 0; i < animalClasses.length; ++i) { var btn = new SwitchButton(); btn.x = btnStartX + i * switchBtnSpacing; btn.y = switchBtnY; btn.animalIdx = i; // Add animal icon var icon = btn.attachAsset(animalIcons[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); btn.icon = icon; // Highlight current if (i === currentAnimalIdx) { icon.scaleX = icon.scaleY = 0.7; } // Touch event btn.down = function (x, y, obj) { if (isSwitching) return; var idx = this.animalIdx; if (idx !== currentAnimalIdx) { switchAnimal(idx); } }; LK.gui.bottom.addChild(btn); switchButtons.push(btn); } // Info text if (infoText) infoText.destroy(); infoText = new Text2('Help the animals escape!\nTap an animal to switch.\nDrag to move. Avoid acid!', { size: 70, fill: "#fff", align: "center" }); infoText.anchor.set(0.5, 0); LK.gui.top.addChild(infoText); } // --- Animal switching --- function switchAnimal(idx) { if (idx < 0 || idx >= animals.length) return; if (idx === currentAnimalIdx) return; isSwitching = true; // Animate out old currentAnimal.onSwitchOut(); currentAnimal.visible = false; // Animate in new currentAnimalIdx = idx; currentAnimal = animals[currentAnimalIdx]; currentAnimal.visible = true; currentAnimal.onSwitchIn(); // Highlight button for (var i = 0; i < switchButtons.length; ++i) { var icon = switchButtons[i].icon; if (i === currentAnimalIdx) { tween(icon, { scaleX: 0.7, scaleY: 0.7 }, { duration: 120 }); } else { tween(icon, { scaleX: 0.5, scaleY: 0.5 }, { duration: 120 }); } } // Small delay to prevent rapid switching LK.setTimeout(function () { isSwitching = false; }, 200); } // --- Movement controls (touch drag) --- function handleMove(x, y, obj) { if (gameOver || youWin) return; // Only move current animal if (!currentAnimal) return; // Clamp to play area var nx = Math.max(PLAY_AREA_LEFT, Math.min(PLAY_AREA_RIGHT, x)); var ny = Math.max(PLAY_AREA_TOP, Math.min(PLAY_AREA_BOTTOM, y)); // For animals with gravity, only allow horizontal drag if (currentAnimal.gravity > 0) { nx = Math.max(PLAY_AREA_LEFT, Math.min(PLAY_AREA_RIGHT, x)); // y is controlled by gravity/jump } else { currentAnimal.y = ny; } currentAnimal.x = nx; } // --- Touch events --- game.down = function (x, y, obj) { if (gameOver || youWin) return; // Start drag dragNode = currentAnimal; dragOffsetX = x - currentAnimal.x; dragOffsetY = y - currentAnimal.y; handleMove(x, y, obj); }; game.move = function (x, y, obj) { if (gameOver || youWin) return; if (dragNode) { handleMove(x - dragOffsetX, y - dragOffsetY, obj); } }; game.up = function (x, y, obj) { dragNode = null; }; // --- Collision helpers --- function intersectsAny(obj, arr) { for (var i = 0; i < arr.length; ++i) { if (obj.intersects(arr[i])) return true; } return false; } function getIntersecting(obj, arr) { for (var i = 0; i < arr.length; ++i) { if (obj.intersects(arr[i])) return arr[i]; } return null; } // --- Game update loop --- game.update = function () { if (gameOver || youWin) return; // Update obstacles for (var i = 0; i < acids.length; ++i) { if (acids[i].update) acids[i].update(); } for (var i = 0; i < foodChunks.length; ++i) { if (foodChunks[i].update) foodChunks[i].update(); } // Update current animal movement (gravity/jump) if (currentAnimal) { // Gravity/jump for Cat, Frog if (currentAnimal.gravity > 0) { // If not being dragged, apply gravity if (!dragNode) { currentAnimal.vy = (currentAnimal.vy || 0) + currentAnimal.gravity; currentAnimal.y += currentAnimal.vy; // Floor collision if (currentAnimal.y > PLAY_AREA_BOTTOM - 60) { currentAnimal.y = PLAY_AREA_BOTTOM - 60; currentAnimal.vy = 0; currentAnimal.isJumping = false; } // Ceiling collision if (currentAnimal.y < PLAY_AREA_TOP + 60) { currentAnimal.y = PLAY_AREA_TOP + 60; currentAnimal.vy = 0; } } } // TODO: Add jump on double tap or button (future) } // Check for acid collision (hazard) if (currentAnimal) { var acid = getIntersecting(currentAnimal, acids); if (acid) { // Some animals are immune if (currentAnimal.assetId === 'polarBear' || currentAnimal.assetId === 'axolotl' || currentAnimal.assetId === 'bee' || currentAnimal.assetId === 'bird') { // No effect } else { // Game over LK.effects.flashScreen(0x00ffff, 800); LK.showGameOver(); gameOver = true; return; } } } // Check for wall collision (keep inside) if (currentAnimal) { if (intersectsAny(currentAnimal, obstacles)) { // Push back inside if (currentAnimal.y < GAME_HEIGHT / 2) { currentAnimal.y += 20; } else { currentAnimal.y -= 20; } } } // Check for food chunk collision (Pig/Elephant can push) if (currentAnimal) { var chunk = getIntersecting(currentAnimal, foodChunks); if (chunk) { if (currentAnimal.assetId === 'pig' || currentAnimal.assetId === 'elephant') { // Push chunk in direction of movement var dx = chunk.x - currentAnimal.x; var dy = chunk.y - currentAnimal.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { chunk.x += dx / dist * 8; chunk.y += dy / dist * 8; // Clamp chunk inside play area chunk.x = Math.max(PLAY_AREA_LEFT + 60, Math.min(PLAY_AREA_RIGHT - 60, chunk.x)); chunk.y = Math.max(PLAY_AREA_TOP + 60, Math.min(PLAY_AREA_BOTTOM - 60, chunk.y)); } } else { // Block movement if (dragNode) { // Undo last move currentAnimal.x -= (currentAnimal.x - chunk.x) * 0.2; currentAnimal.y -= (currentAnimal.y - chunk.y) * 0.2; } } } } // Win condition: reach top of play area if (currentAnimal && currentAnimal.y < PLAY_AREA_TOP + 80) { // You win! LK.effects.flashScreen(0x00ff00, 1000); LK.showYouWin(); youWin = true; return; } }; // --- Game start --- function startGame() { setupLevel(); setupAnimals(); setupUI(); gameOver = false; youWin = false; } startGame();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,528 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Obstacle: acid pool (hazard)
+var Acid = Container.expand(function () {
+ var self = Container.call(this);
+ var acid = self.attachAsset('acid', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Acid can move left/right for challenge
+ self.speed = 0;
+ self.direction = 1;
+ self.update = function () {
+ if (self.speed !== 0) {
+ self.x += self.speed * self.direction;
+ if (self.x < 200 || self.x > 2048 - 200) {
+ self.direction *= -1;
+ }
+ }
+ };
+ return self;
+});
+// Animal base class
+var Animal = Container.expand(function () {
+ var self = Container.call(this);
+ // These will be set by subclasses
+ self.assetId = '';
+ self.moveType = 'normal'; // 'normal', 'hop', 'slide', 'float', etc.
+ self.speed = 12; // Default speed
+ self.jumpPower = 0; // For animals that can jump
+ self.gravity = 0; // For animals affected by gravity
+ self.vy = 0; // Vertical velocity
+ // Attach animal asset
+ var animalSprite = self.attachAsset(self.assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Used for per-animal movement logic
+ self.update = function () {
+ // Movement logic handled in main game loop
+ };
+ // Called when switching to this animal
+ self.onSwitchIn = function () {
+ // Flash or animate to show selection
+ tween(animalSprite, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 120,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(animalSprite, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 120,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ // Called when switching away from this animal
+ self.onSwitchOut = function () {
+ // No-op for now
+ };
+ return self;
+});
+// Snail: very slow, can stick to walls
+var Snail = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'snail';
+ self.speed = 4;
+ return self;
+});
+// Polar Bear: slow, immune to acid
+var PolarBear = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'polarBear';
+ self.speed = 7;
+ return self;
+});
+// Pig: slow, can push food chunks
+var Pig = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'pig';
+ self.speed = 8;
+ return self;
+});
+// Frog: can hop
+var Frog = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'frog';
+ self.speed = 10;
+ self.jumpPower = 48;
+ self.gravity = 3.5;
+ self.isJumping = false;
+ return self;
+});
+// Elephant: can push obstacles, slowest
+var Elephant = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'elephant';
+ self.speed = 6;
+ return self;
+});
+// Cat: fast, can jump
+var Cat = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'cat';
+ self.speed = 16;
+ self.jumpPower = 38;
+ self.gravity = 3.2;
+ self.isJumping = false;
+ return self;
+});
+// Bird: can fly (ignores gravity)
+var Bird = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'bird';
+ self.speed = 13;
+ self.moveType = 'fly';
+ return self;
+});
+// Bee: can float over acid, moves in short bursts
+var Bee = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'bee';
+ self.speed = 10;
+ self.moveType = 'float';
+ return self;
+});
+// Axolotl: can swim in acid, normal speed
+var Axolotl = Animal.expand(function () {
+ var self = Animal.call(this);
+ self.assetId = 'axolotl';
+ self.speed = 11;
+ self.moveType = 'swim';
+ return self;
+});
+// Obstacle: food chunk (movable)
+var FoodChunk = Container.expand(function () {
+ var self = Container.call(this);
+ var chunk = self.attachAsset('foodChunk', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.update = function () {};
+ return self;
+});
+// Obstacle: stomach wall (static)
+var StomachWall = Container.expand(function () {
+ var self = Container.call(this);
+ var wall = self.attachAsset('stomachWall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Touch button for animal switching
+var SwitchButton = Container.expand(function () {
+ var self = Container.call(this);
+ var btn = self.attachAsset('switchBtn', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.icon = null; // Will be set to animal icon
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2d1b0c // Deep brown, snake belly
+});
+
+/****
+* Game Code
+****/
+// Touch button shapes
+// Obstacle shapes
+// Animal shapes (unique color for each animal)
+// --- Game constants ---
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var PLAY_AREA_TOP = 200;
+var PLAY_AREA_BOTTOM = GAME_HEIGHT - 200;
+var PLAY_AREA_LEFT = 100;
+var PLAY_AREA_RIGHT = GAME_WIDTH - 100;
+// --- Animal roster and order ---
+var animalClasses = [Pig, Cat, Bee, Frog, PolarBear, Elephant, Bird, Snail, Axolotl];
+var animalNames = ['Pig', 'Cat', 'Bee', 'Frog', 'Polar Bear', 'Elephant', 'Bird', 'Snail', 'Axolotl'];
+var animalIcons = ['pig', 'cat', 'bee', 'frog', 'polarBear', 'elephant', 'bird', 'snail', 'axolotl'];
+var animals = [];
+var currentAnimalIdx = 0;
+var currentAnimal = null;
+// --- Obstacles and hazards ---
+var obstacles = [];
+var acids = [];
+var foodChunks = [];
+// --- UI ---
+var switchButtons = [];
+var switchBtnY = GAME_HEIGHT - 180;
+var switchBtnSpacing = 200;
+var infoText = null;
+// --- Dragging ---
+var dragNode = null;
+var dragOffsetX = 0;
+var dragOffsetY = 0;
+// --- Game state ---
+var isMovingLeft = false;
+var isMovingRight = false;
+var isMovingUp = false;
+var isMovingDown = false;
+var isJumping = false;
+var isSwitching = false;
+var gameStarted = false;
+var gameOver = false;
+var youWin = false;
+// --- Level layout (simple for MVP) ---
+function setupLevel() {
+ // Clear previous
+ for (var i = 0; i < obstacles.length; ++i) obstacles[i].destroy();
+ for (var i = 0; i < acids.length; ++i) acids[i].destroy();
+ for (var i = 0; i < foodChunks.length; ++i) foodChunks[i].destroy();
+ obstacles = [];
+ acids = [];
+ foodChunks = [];
+ // Top and bottom stomach walls
+ var wallTop = new StomachWall();
+ wallTop.x = GAME_WIDTH / 2;
+ wallTop.y = PLAY_AREA_TOP - 40;
+ obstacles.push(wallTop);
+ game.addChild(wallTop);
+ var wallBottom = new StomachWall();
+ wallBottom.x = GAME_WIDTH / 2;
+ wallBottom.y = PLAY_AREA_BOTTOM + 40;
+ obstacles.push(wallBottom);
+ game.addChild(wallBottom);
+ // Acid pools (hazards)
+ var acid1 = new Acid();
+ acid1.x = GAME_WIDTH / 2;
+ acid1.y = PLAY_AREA_TOP + 400;
+ acid1.speed = 6;
+ acids.push(acid1);
+ game.addChild(acid1);
+ var acid2 = new Acid();
+ acid2.x = GAME_WIDTH / 2 + 400;
+ acid2.y = PLAY_AREA_TOP + 900;
+ acid2.speed = 0;
+ acids.push(acid2);
+ game.addChild(acid2);
+ // Food chunks (movable obstacles)
+ var chunk1 = new FoodChunk();
+ chunk1.x = GAME_WIDTH / 2 - 300;
+ chunk1.y = PLAY_AREA_TOP + 700;
+ foodChunks.push(chunk1);
+ game.addChild(chunk1);
+ var chunk2 = new FoodChunk();
+ chunk2.x = GAME_WIDTH / 2 + 300;
+ chunk2.y = PLAY_AREA_TOP + 1200;
+ foodChunks.push(chunk2);
+ game.addChild(chunk2);
+ // More obstacles can be added for future levels
+}
+// --- Animal setup ---
+function setupAnimals() {
+ // Remove previous
+ for (var i = 0; i < animals.length; ++i) animals[i].destroy();
+ animals = [];
+ // Place all animals at start, stacked
+ var startX = GAME_WIDTH / 2;
+ var startY = PLAY_AREA_BOTTOM - 200;
+ for (var i = 0; i < animalClasses.length; ++i) {
+ var animal = new animalClasses[i]();
+ animal.x = startX + (i - 4) * 40;
+ animal.y = startY - i * 40;
+ animal.zIndex = i;
+ animal.visible = false;
+ animals.push(animal);
+ game.addChild(animal);
+ }
+ // Set first animal active
+ currentAnimalIdx = 0;
+ currentAnimal = animals[currentAnimalIdx];
+ currentAnimal.visible = true;
+ currentAnimal.onSwitchIn();
+}
+// --- UI setup ---
+function setupUI() {
+ // Remove previous
+ for (var i = 0; i < switchButtons.length; ++i) switchButtons[i].destroy();
+ switchButtons = [];
+ // Create switch buttons for each animal
+ var btnStartX = GAME_WIDTH / 2 - (animalClasses.length - 1) / 2 * switchBtnSpacing;
+ for (var i = 0; i < animalClasses.length; ++i) {
+ var btn = new SwitchButton();
+ btn.x = btnStartX + i * switchBtnSpacing;
+ btn.y = switchBtnY;
+ btn.animalIdx = i;
+ // Add animal icon
+ var icon = btn.attachAsset(animalIcons[i], {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.5,
+ scaleY: 0.5
+ });
+ btn.icon = icon;
+ // Highlight current
+ if (i === currentAnimalIdx) {
+ icon.scaleX = icon.scaleY = 0.7;
+ }
+ // Touch event
+ btn.down = function (x, y, obj) {
+ if (isSwitching) return;
+ var idx = this.animalIdx;
+ if (idx !== currentAnimalIdx) {
+ switchAnimal(idx);
+ }
+ };
+ LK.gui.bottom.addChild(btn);
+ switchButtons.push(btn);
+ }
+ // Info text
+ if (infoText) infoText.destroy();
+ infoText = new Text2('Help the animals escape!\nTap an animal to switch.\nDrag to move. Avoid acid!', {
+ size: 70,
+ fill: "#fff",
+ align: "center"
+ });
+ infoText.anchor.set(0.5, 0);
+ LK.gui.top.addChild(infoText);
+}
+// --- Animal switching ---
+function switchAnimal(idx) {
+ if (idx < 0 || idx >= animals.length) return;
+ if (idx === currentAnimalIdx) return;
+ isSwitching = true;
+ // Animate out old
+ currentAnimal.onSwitchOut();
+ currentAnimal.visible = false;
+ // Animate in new
+ currentAnimalIdx = idx;
+ currentAnimal = animals[currentAnimalIdx];
+ currentAnimal.visible = true;
+ currentAnimal.onSwitchIn();
+ // Highlight button
+ for (var i = 0; i < switchButtons.length; ++i) {
+ var icon = switchButtons[i].icon;
+ if (i === currentAnimalIdx) {
+ tween(icon, {
+ scaleX: 0.7,
+ scaleY: 0.7
+ }, {
+ duration: 120
+ });
+ } else {
+ tween(icon, {
+ scaleX: 0.5,
+ scaleY: 0.5
+ }, {
+ duration: 120
+ });
+ }
+ }
+ // Small delay to prevent rapid switching
+ LK.setTimeout(function () {
+ isSwitching = false;
+ }, 200);
+}
+// --- Movement controls (touch drag) ---
+function handleMove(x, y, obj) {
+ if (gameOver || youWin) return;
+ // Only move current animal
+ if (!currentAnimal) return;
+ // Clamp to play area
+ var nx = Math.max(PLAY_AREA_LEFT, Math.min(PLAY_AREA_RIGHT, x));
+ var ny = Math.max(PLAY_AREA_TOP, Math.min(PLAY_AREA_BOTTOM, y));
+ // For animals with gravity, only allow horizontal drag
+ if (currentAnimal.gravity > 0) {
+ nx = Math.max(PLAY_AREA_LEFT, Math.min(PLAY_AREA_RIGHT, x));
+ // y is controlled by gravity/jump
+ } else {
+ currentAnimal.y = ny;
+ }
+ currentAnimal.x = nx;
+}
+// --- Touch events ---
+game.down = function (x, y, obj) {
+ if (gameOver || youWin) return;
+ // Start drag
+ dragNode = currentAnimal;
+ dragOffsetX = x - currentAnimal.x;
+ dragOffsetY = y - currentAnimal.y;
+ handleMove(x, y, obj);
+};
+game.move = function (x, y, obj) {
+ if (gameOver || youWin) return;
+ if (dragNode) {
+ handleMove(x - dragOffsetX, y - dragOffsetY, obj);
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// --- Collision helpers ---
+function intersectsAny(obj, arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (obj.intersects(arr[i])) return true;
+ }
+ return false;
+}
+function getIntersecting(obj, arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (obj.intersects(arr[i])) return arr[i];
+ }
+ return null;
+}
+// --- Game update loop ---
+game.update = function () {
+ if (gameOver || youWin) return;
+ // Update obstacles
+ for (var i = 0; i < acids.length; ++i) {
+ if (acids[i].update) acids[i].update();
+ }
+ for (var i = 0; i < foodChunks.length; ++i) {
+ if (foodChunks[i].update) foodChunks[i].update();
+ }
+ // Update current animal movement (gravity/jump)
+ if (currentAnimal) {
+ // Gravity/jump for Cat, Frog
+ if (currentAnimal.gravity > 0) {
+ // If not being dragged, apply gravity
+ if (!dragNode) {
+ currentAnimal.vy = (currentAnimal.vy || 0) + currentAnimal.gravity;
+ currentAnimal.y += currentAnimal.vy;
+ // Floor collision
+ if (currentAnimal.y > PLAY_AREA_BOTTOM - 60) {
+ currentAnimal.y = PLAY_AREA_BOTTOM - 60;
+ currentAnimal.vy = 0;
+ currentAnimal.isJumping = false;
+ }
+ // Ceiling collision
+ if (currentAnimal.y < PLAY_AREA_TOP + 60) {
+ currentAnimal.y = PLAY_AREA_TOP + 60;
+ currentAnimal.vy = 0;
+ }
+ }
+ }
+ // TODO: Add jump on double tap or button (future)
+ }
+ // Check for acid collision (hazard)
+ if (currentAnimal) {
+ var acid = getIntersecting(currentAnimal, acids);
+ if (acid) {
+ // Some animals are immune
+ if (currentAnimal.assetId === 'polarBear' || currentAnimal.assetId === 'axolotl' || currentAnimal.assetId === 'bee' || currentAnimal.assetId === 'bird') {
+ // No effect
+ } else {
+ // Game over
+ LK.effects.flashScreen(0x00ffff, 800);
+ LK.showGameOver();
+ gameOver = true;
+ return;
+ }
+ }
+ }
+ // Check for wall collision (keep inside)
+ if (currentAnimal) {
+ if (intersectsAny(currentAnimal, obstacles)) {
+ // Push back inside
+ if (currentAnimal.y < GAME_HEIGHT / 2) {
+ currentAnimal.y += 20;
+ } else {
+ currentAnimal.y -= 20;
+ }
+ }
+ }
+ // Check for food chunk collision (Pig/Elephant can push)
+ if (currentAnimal) {
+ var chunk = getIntersecting(currentAnimal, foodChunks);
+ if (chunk) {
+ if (currentAnimal.assetId === 'pig' || currentAnimal.assetId === 'elephant') {
+ // Push chunk in direction of movement
+ var dx = chunk.x - currentAnimal.x;
+ var dy = chunk.y - currentAnimal.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ chunk.x += dx / dist * 8;
+ chunk.y += dy / dist * 8;
+ // Clamp chunk inside play area
+ chunk.x = Math.max(PLAY_AREA_LEFT + 60, Math.min(PLAY_AREA_RIGHT - 60, chunk.x));
+ chunk.y = Math.max(PLAY_AREA_TOP + 60, Math.min(PLAY_AREA_BOTTOM - 60, chunk.y));
+ }
+ } else {
+ // Block movement
+ if (dragNode) {
+ // Undo last move
+ currentAnimal.x -= (currentAnimal.x - chunk.x) * 0.2;
+ currentAnimal.y -= (currentAnimal.y - chunk.y) * 0.2;
+ }
+ }
+ }
+ }
+ // Win condition: reach top of play area
+ if (currentAnimal && currentAnimal.y < PLAY_AREA_TOP + 80) {
+ // You win!
+ LK.effects.flashScreen(0x00ff00, 1000);
+ LK.showYouWin();
+ youWin = true;
+ return;
+ }
+};
+// --- Game start ---
+function startGame() {
+ setupLevel();
+ setupAnimals();
+ setupUI();
+ gameOver = false;
+ youWin = false;
+}
+startGame();
\ No newline at end of file