User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var i = 0; i < animalButtons.length; i++) {' Line Number: 385
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var i = 0; i < animalButtons.length; i++) {' Line Number: 385
Code edit (1 edits merged)
Please save this source code
User prompt
Pig Cat Bee Frog: Snake Tummy Struggle
Initial prompt
Pig Cat Bee And Frog Is Struggle In The Snake Tummy With Keyboard
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Digestive hazard (acid pool) var Acid = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('acid', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'hazard'; return self; }); // Animal base class var Animal = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.jumpPower = 0; self.gravity = 0.7; self.vx = 0; self.vy = 0; self.isOnGround = false; self.isActive = false; self.asset = null; self.type = 'animal'; self.name = ''; self.moveDir = 0; // -1 left, 1 right, 0 none // Called every tick self.update = function () { // Only update if active if (!self.isActive) return; // Movement self.x += self.vx; self.y += self.vy; // Gravity self.vy += self.gravity; // Clamp to game area if (self.x < 90) self.x = 90; if (self.x > 2048 - 90) self.x = 2048 - 90; if (self.y > 2732 - 90) { self.y = 2732 - 90; self.vy = 0; self.isOnGround = true; } // If moving left/right if (self.moveDir !== 0) { self.vx = self.moveDir * self.speed; } else { self.vx = 0; } }; // Called when jump button pressed self.jump = function () { if (self.isOnGround) { self.vy = -self.jumpPower; self.isOnGround = false; } }; // Called when switching to this animal self.activate = function () { self.isActive = true; if (self.asset) self.asset.alpha = 1; }; // Called when switching away self.deactivate = function () { self.isActive = false; if (self.asset) self.asset.alpha = 0.5; self.moveDir = 0; self.vx = 0; }; return self; }); // Pig: slow, can push blocks var Pig = Animal.expand(function () { var self = Animal.call(this); self.asset = self.attachAsset('pig', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.jumpPower = 32; self.name = 'Pig'; return self; }); // Frog: can double jump var Frog = Animal.expand(function () { var self = Animal.call(this); self.asset = self.attachAsset('frog', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 13; self.jumpPower = 38; self.name = 'Frog'; self.jumpsLeft = 2; // Override update for double jump self.update = function () { if (!self.isActive) return; self.x += self.vx; self.y += self.vy; self.vy += self.gravity; if (self.x < 90) self.x = 90; if (self.x > 2048 - 90) self.x = 2048 - 90; if (self.y > 2732 - 90) { self.y = 2732 - 90; self.vy = 0; self.isOnGround = true; self.jumpsLeft = 2; } if (self.isOnGround && self.vy !== 0) { self.isOnGround = false; } }; self.jump = function () { if (self.jumpsLeft > 0) { self.vy = -self.jumpPower; self.jumpsLeft--; self.isOnGround = false; } }; // Reset jumps on ground self.activate = function () { self.isActive = true; if (self.asset) self.asset.alpha = 1; if (self.y >= 2732 - 90) self.jumpsLeft = 2; }; return self; }); // Cat: fast, high jump var Cat = Animal.expand(function () { var self = Animal.call(this); self.asset = self.attachAsset('cat', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 18; self.jumpPower = 48; self.name = 'Cat'; return self; }); // Bee: can fly (no gravity) var Bee = Animal.expand(function () { var self = Animal.call(this); self.asset = self.attachAsset('bee', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 14; self.jumpPower = 0; self.name = 'Bee'; self.gravity = 0; // No gravity // Override update for flying self.update = function () { if (!self.isActive) return; self.x += self.vx; self.y += self.vy; // Clamp if (self.x < 90) self.x = 90; if (self.x > 2048 - 90) self.x = 2048 - 90; if (self.y < 90) self.y = 90; if (self.y > 2732 - 90) self.y = 2732 - 90; }; // Bee "jump" is fly up self.jump = function () { self.vy = -16; }; return self; }); // Puzzle block (static) var Block = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('block', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'block'; return self; }); // Button UI var UIButton = Container.expand(function () { var self = Container.call(this); self.bg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); self.txt = new Text2('', { size: 60, fill: "#fff" }); self.txt.anchor.set(0.5, 0.5); self.addChild(self.txt); self.action = null; self.isActive = false; self.setText = function (str) { self.txt.setText(str); }; self.setActive = function (active) { self.isActive = active; self.bg.tint = active ? 0x77cc77 : 0x333333; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2e1e1e }); /**** * Game Code ****/ // Button shapes // Puzzle block // Digestive hazard // Snake belly background // Animal shapes (distinct color for each) // Add snake belly background var bg = LK.getAsset('snakeBelly', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(bg); // Level layout (minimal MVP: platforms, hazards, exit) var blocks = []; var acids = []; var exitZone = { x: 2048 - 200, y: 200, w: 200, h: 200 }; // Top right corner // Create platforms function createBlock(x, y) { var b = new Block(); b.x = x; b.y = y; blocks.push(b); game.addChild(b); } createBlock(400, 2200); createBlock(800, 1800); createBlock(1200, 1400); createBlock(1600, 1000); createBlock(1800, 600); // Create acid hazards function createAcid(x, y) { var a = new Acid(); a.x = x; a.y = y; acids.push(a); game.addChild(a); } createAcid(600, 2300); createAcid(1400, 1600); createAcid(1700, 800); // Create exit zone (invisible, just a rectangle) var exitRect = new Rectangle(exitZone.x, exitZone.y, exitZone.w, exitZone.h); // Animals var animals = []; var pig = new Pig(); pig.x = 400; pig.y = 2100; animals.push(pig); game.addChild(pig); var cat = new Cat(); cat.x = 800; cat.y = 1700; animals.push(cat); game.addChild(cat); var bee = new Bee(); bee.x = 1200; bee.y = 1300; animals.push(bee); game.addChild(bee); var frog = new Frog(); frog.x = 1600; frog.y = 900; animals.push(frog); game.addChild(frog); // Set initial active animal var activeAnimalIndex = 0; function setActiveAnimal(idx) { for (var i = 0; i < animals.length; i++) { if (i === idx) animals[i].activate();else animals[i].deactivate(); } activeAnimalIndex = idx; updateAnimalButtons(); } setActiveAnimal(0); // UI: On-screen controls var btnLeft = new UIButton(); btnLeft.setText('←'); btnLeft.x = 300; btnLeft.y = 2732 - 200; LK.gui.bottomLeft.addChild(btnLeft); var btnRight = new UIButton(); btnRight.setText('→'); btnRight.x = 600; btnRight.y = 2732 - 200; LK.gui.bottomLeft.addChild(btnRight); var btnJump = new UIButton(); btnJump.setText('⤒'); btnJump.x = 2048 - 600; btnJump.y = 2732 - 200; LK.gui.bottomRight.addChild(btnJump); // Animal switch buttons var btnPig = new UIButton(); btnPig.setText('Pig'); btnPig.x = 400; btnPig.y = 200; LK.gui.top.addChild(btnPig); var btnCat = new UIButton(); btnCat.setText('Cat'); btnCat.x = 800; btnCat.y = 200; LK.gui.top.addChild(btnCat); var btnBee = new UIButton(); btnBee.setText('Bee'); btnBee.x = 1200; btnBee.y = 200; LK.gui.top.addChild(btnBee); var btnFrog = new UIButton(); btnFrog.setText('Frog'); btnFrog.x = 1600; btnFrog.y = 200; LK.gui.top.addChild(btnFrog); var animalButtons = [btnPig, btnCat, btnBee, btnFrog]; function updateAnimalButtons() { if (typeof animalButtons === "undefined" || !animalButtons) animalButtons = []; for (var i = 0; i < animalButtons.length; i++) { animalButtons[i].setActive(i === activeAnimalIndex); } } // Score: animals escaped var scoreTxt = new Text2('Escaped: 0/4', { size: 90, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Touch handling for buttons var leftPressed = false, rightPressed = false, jumpPressed = false; // Button event helpers function isInsideBtn(btn, x, y) { var bx = btn.x, by = btn.y; var w = btn.bg.width, h = btn.bg.height; return x >= bx - w / 2 && x <= bx + w / 2 && y >= by - h / 2 && y <= by + h / 2; } // GUI event: move LK.gui.move = function (x, y, obj) { // Only handle move for button press/release // (No drag for MVP) }; // GUI event: down LK.gui.down = function (x, y, obj) { // Convert to GUI coordinates for each button // Left if (isInsideBtn(btnLeft, x, y)) { leftPressed = true; btnLeft.setActive(true); animals[activeAnimalIndex].moveDir = -1; } // Right if (isInsideBtn(btnRight, x, y)) { rightPressed = true; btnRight.setActive(true); animals[activeAnimalIndex].moveDir = 1; } // Jump if (isInsideBtn(btnJump, x, y)) { jumpPressed = true; btnJump.setActive(true); animals[activeAnimalIndex].jump(); } // Animal switch if (typeof animalButtons !== "undefined" && animalButtons && animalButtons.length) { for (var i = 0; i < animalButtons.length; i++) { if (isInsideBtn(animalButtons[i], x, y)) { setActiveAnimal(i); } } } }; // GUI event: up LK.gui.up = function (x, y, obj) { // Left if (leftPressed) { leftPressed = false; btnLeft.setActive(false); if (animals[activeAnimalIndex].moveDir === -1) animals[activeAnimalIndex].moveDir = 0; } // Right if (rightPressed) { rightPressed = false; btnRight.setActive(false); if (animals[activeAnimalIndex].moveDir === 1) animals[activeAnimalIndex].moveDir = 0; } // Jump if (jumpPressed) { jumpPressed = false; btnJump.setActive(false); } }; // Collision helpers function rectsIntersect(ax, ay, aw, ah, bx, by, bw, bh) { return !(bx > ax + aw || bx + bw < ax || by > ay + ah || by + bh < ay); } // Check collision with blocks function animalBlockCollision(animal) { for (var i = 0; i < blocks.length; i++) { var b = blocks[i]; var aw = animal.asset.width, ah = animal.asset.height; var bw = b.asset.width, bh = b.asset.height; // Simple AABB if (rectsIntersect(animal.x - aw / 2, animal.y - ah / 2, aw, ah, b.x - bw / 2, b.y - bh / 2, bw, bh)) { // Land on top if (animal.y < b.y && animal.vy > 0) { animal.y = b.y - bh / 2 - ah / 2; animal.vy = 0; animal.isOnGround = true; if (animal.name === 'Frog') animal.jumpsLeft = 2; } // Push block (only Pig) if (animal.name === 'Pig' && Math.abs(animal.x - b.x) < (aw + bw) / 2 && Math.abs(animal.y - b.y) < (ah + bh) / 2) { b.x += animal.vx * 0.5; // Clamp block if (b.x < bw / 2) b.x = bw / 2; if (b.x > 2048 - bw / 2) b.x = 2048 - bw / 2; } } } } // Check collision with acid function animalAcidCollision(animal) { for (var i = 0; i < acids.length; i++) { var a = acids[i]; var aw = animal.asset.width, ah = animal.asset.height; var aw2 = aw / 2, ah2 = ah / 2; var ax = animal.x - aw2, ay = animal.y - ah2; var bw = a.asset.width, bh = a.asset.height; var bx = a.x - bw / 2, by = a.y - bh / 2; if (rectsIntersect(ax, ay, aw, ah, bx, by, bw, bh)) { // Flash and game over LK.effects.flashScreen(0x00ffff, 800); LK.showGameOver(); return true; } } return false; } // Check if animal reached exit function animalAtExit(animal) { var aw = animal.asset.width, ah = animal.asset.height; var ax = animal.x - aw / 2, ay = animal.y - ah / 2; return rectsIntersect(ax, ay, aw, ah, exitRect.x, exitRect.y, exitRect.width, exitRect.height); } // Track which animals have escaped var escaped = [false, false, false, false]; // Main game update game.update = function () { // Update all animals for (var i = 0; i < animals.length; i++) { animals[i].update(); animalBlockCollision(animals[i]); if (animalAcidCollision(animals[i])) return; // Check exit if (!escaped[i] && animalAtExit(animals[i])) { escaped[i] = true; animals[i].visible = false; // Flash green LK.effects.flashScreen(0x00ff00, 400); // Update score var count = 0; for (var j = 0; j < escaped.length; j++) if (escaped[j]) count++; scoreTxt.setText('Escaped: ' + count + '/4'); // If all escaped, win! if (count === 4) { LK.showYouWin(); } else { // Switch to next available animal for (var k = 0; k < animals.length; k++) { if (!escaped[k]) { setActiveAnimal(k); break; } } } } } // If active animal is escaped, switch if (escaped[activeAnimalIndex]) { for (var k = 0; k < animals.length; k++) { if (!escaped[k]) { setActiveAnimal(k); break; } } } }; // Draw exit zone (for MVP, invisible, but could add a visual hint if desired) // var exitHint = LK.getAsset('centerCircle', {anchorX:0.5, anchorY:0.5, x:exitZone.x+exitZone.w/2, y:exitZone.y+exitZone.h/2, scaleX:1.2, scaleY:1.2, tint:0x00ff00, alpha:0.2}); // game.addChild(exitHint);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Digestive hazard (acid pool)
var Acid = Container.expand(function () {
var self = Container.call(this);
self.asset = self.attachAsset('acid', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'hazard';
return self;
});
// Animal base class
var Animal = Container.expand(function () {
var self = Container.call(this);
self.speed = 0;
self.jumpPower = 0;
self.gravity = 0.7;
self.vx = 0;
self.vy = 0;
self.isOnGround = false;
self.isActive = false;
self.asset = null;
self.type = 'animal';
self.name = '';
self.moveDir = 0; // -1 left, 1 right, 0 none
// Called every tick
self.update = function () {
// Only update if active
if (!self.isActive) return;
// Movement
self.x += self.vx;
self.y += self.vy;
// Gravity
self.vy += self.gravity;
// Clamp to game area
if (self.x < 90) self.x = 90;
if (self.x > 2048 - 90) self.x = 2048 - 90;
if (self.y > 2732 - 90) {
self.y = 2732 - 90;
self.vy = 0;
self.isOnGround = true;
}
// If moving left/right
if (self.moveDir !== 0) {
self.vx = self.moveDir * self.speed;
} else {
self.vx = 0;
}
};
// Called when jump button pressed
self.jump = function () {
if (self.isOnGround) {
self.vy = -self.jumpPower;
self.isOnGround = false;
}
};
// Called when switching to this animal
self.activate = function () {
self.isActive = true;
if (self.asset) self.asset.alpha = 1;
};
// Called when switching away
self.deactivate = function () {
self.isActive = false;
if (self.asset) self.asset.alpha = 0.5;
self.moveDir = 0;
self.vx = 0;
};
return self;
});
// Pig: slow, can push blocks
var Pig = Animal.expand(function () {
var self = Animal.call(this);
self.asset = self.attachAsset('pig', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.jumpPower = 32;
self.name = 'Pig';
return self;
});
// Frog: can double jump
var Frog = Animal.expand(function () {
var self = Animal.call(this);
self.asset = self.attachAsset('frog', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 13;
self.jumpPower = 38;
self.name = 'Frog';
self.jumpsLeft = 2;
// Override update for double jump
self.update = function () {
if (!self.isActive) return;
self.x += self.vx;
self.y += self.vy;
self.vy += self.gravity;
if (self.x < 90) self.x = 90;
if (self.x > 2048 - 90) self.x = 2048 - 90;
if (self.y > 2732 - 90) {
self.y = 2732 - 90;
self.vy = 0;
self.isOnGround = true;
self.jumpsLeft = 2;
}
if (self.isOnGround && self.vy !== 0) {
self.isOnGround = false;
}
};
self.jump = function () {
if (self.jumpsLeft > 0) {
self.vy = -self.jumpPower;
self.jumpsLeft--;
self.isOnGround = false;
}
};
// Reset jumps on ground
self.activate = function () {
self.isActive = true;
if (self.asset) self.asset.alpha = 1;
if (self.y >= 2732 - 90) self.jumpsLeft = 2;
};
return self;
});
// Cat: fast, high jump
var Cat = Animal.expand(function () {
var self = Animal.call(this);
self.asset = self.attachAsset('cat', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 18;
self.jumpPower = 48;
self.name = 'Cat';
return self;
});
// Bee: can fly (no gravity)
var Bee = Animal.expand(function () {
var self = Animal.call(this);
self.asset = self.attachAsset('bee', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 14;
self.jumpPower = 0;
self.name = 'Bee';
self.gravity = 0; // No gravity
// Override update for flying
self.update = function () {
if (!self.isActive) return;
self.x += self.vx;
self.y += self.vy;
// Clamp
if (self.x < 90) self.x = 90;
if (self.x > 2048 - 90) self.x = 2048 - 90;
if (self.y < 90) self.y = 90;
if (self.y > 2732 - 90) self.y = 2732 - 90;
};
// Bee "jump" is fly up
self.jump = function () {
self.vy = -16;
};
return self;
});
// Puzzle block (static)
var Block = Container.expand(function () {
var self = Container.call(this);
self.asset = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'block';
return self;
});
// Button UI
var UIButton = Container.expand(function () {
var self = Container.call(this);
self.bg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.txt = new Text2('', {
size: 60,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
self.action = null;
self.isActive = false;
self.setText = function (str) {
self.txt.setText(str);
};
self.setActive = function (active) {
self.isActive = active;
self.bg.tint = active ? 0x77cc77 : 0x333333;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2e1e1e
});
/****
* Game Code
****/
// Button shapes
// Puzzle block
// Digestive hazard
// Snake belly background
// Animal shapes (distinct color for each)
// Add snake belly background
var bg = LK.getAsset('snakeBelly', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(bg);
// Level layout (minimal MVP: platforms, hazards, exit)
var blocks = [];
var acids = [];
var exitZone = {
x: 2048 - 200,
y: 200,
w: 200,
h: 200
}; // Top right corner
// Create platforms
function createBlock(x, y) {
var b = new Block();
b.x = x;
b.y = y;
blocks.push(b);
game.addChild(b);
}
createBlock(400, 2200);
createBlock(800, 1800);
createBlock(1200, 1400);
createBlock(1600, 1000);
createBlock(1800, 600);
// Create acid hazards
function createAcid(x, y) {
var a = new Acid();
a.x = x;
a.y = y;
acids.push(a);
game.addChild(a);
}
createAcid(600, 2300);
createAcid(1400, 1600);
createAcid(1700, 800);
// Create exit zone (invisible, just a rectangle)
var exitRect = new Rectangle(exitZone.x, exitZone.y, exitZone.w, exitZone.h);
// Animals
var animals = [];
var pig = new Pig();
pig.x = 400;
pig.y = 2100;
animals.push(pig);
game.addChild(pig);
var cat = new Cat();
cat.x = 800;
cat.y = 1700;
animals.push(cat);
game.addChild(cat);
var bee = new Bee();
bee.x = 1200;
bee.y = 1300;
animals.push(bee);
game.addChild(bee);
var frog = new Frog();
frog.x = 1600;
frog.y = 900;
animals.push(frog);
game.addChild(frog);
// Set initial active animal
var activeAnimalIndex = 0;
function setActiveAnimal(idx) {
for (var i = 0; i < animals.length; i++) {
if (i === idx) animals[i].activate();else animals[i].deactivate();
}
activeAnimalIndex = idx;
updateAnimalButtons();
}
setActiveAnimal(0);
// UI: On-screen controls
var btnLeft = new UIButton();
btnLeft.setText('←');
btnLeft.x = 300;
btnLeft.y = 2732 - 200;
LK.gui.bottomLeft.addChild(btnLeft);
var btnRight = new UIButton();
btnRight.setText('→');
btnRight.x = 600;
btnRight.y = 2732 - 200;
LK.gui.bottomLeft.addChild(btnRight);
var btnJump = new UIButton();
btnJump.setText('⤒');
btnJump.x = 2048 - 600;
btnJump.y = 2732 - 200;
LK.gui.bottomRight.addChild(btnJump);
// Animal switch buttons
var btnPig = new UIButton();
btnPig.setText('Pig');
btnPig.x = 400;
btnPig.y = 200;
LK.gui.top.addChild(btnPig);
var btnCat = new UIButton();
btnCat.setText('Cat');
btnCat.x = 800;
btnCat.y = 200;
LK.gui.top.addChild(btnCat);
var btnBee = new UIButton();
btnBee.setText('Bee');
btnBee.x = 1200;
btnBee.y = 200;
LK.gui.top.addChild(btnBee);
var btnFrog = new UIButton();
btnFrog.setText('Frog');
btnFrog.x = 1600;
btnFrog.y = 200;
LK.gui.top.addChild(btnFrog);
var animalButtons = [btnPig, btnCat, btnBee, btnFrog];
function updateAnimalButtons() {
if (typeof animalButtons === "undefined" || !animalButtons) animalButtons = [];
for (var i = 0; i < animalButtons.length; i++) {
animalButtons[i].setActive(i === activeAnimalIndex);
}
}
// Score: animals escaped
var scoreTxt = new Text2('Escaped: 0/4', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Touch handling for buttons
var leftPressed = false,
rightPressed = false,
jumpPressed = false;
// Button event helpers
function isInsideBtn(btn, x, y) {
var bx = btn.x,
by = btn.y;
var w = btn.bg.width,
h = btn.bg.height;
return x >= bx - w / 2 && x <= bx + w / 2 && y >= by - h / 2 && y <= by + h / 2;
}
// GUI event: move
LK.gui.move = function (x, y, obj) {
// Only handle move for button press/release
// (No drag for MVP)
};
// GUI event: down
LK.gui.down = function (x, y, obj) {
// Convert to GUI coordinates for each button
// Left
if (isInsideBtn(btnLeft, x, y)) {
leftPressed = true;
btnLeft.setActive(true);
animals[activeAnimalIndex].moveDir = -1;
}
// Right
if (isInsideBtn(btnRight, x, y)) {
rightPressed = true;
btnRight.setActive(true);
animals[activeAnimalIndex].moveDir = 1;
}
// Jump
if (isInsideBtn(btnJump, x, y)) {
jumpPressed = true;
btnJump.setActive(true);
animals[activeAnimalIndex].jump();
}
// Animal switch
if (typeof animalButtons !== "undefined" && animalButtons && animalButtons.length) {
for (var i = 0; i < animalButtons.length; i++) {
if (isInsideBtn(animalButtons[i], x, y)) {
setActiveAnimal(i);
}
}
}
};
// GUI event: up
LK.gui.up = function (x, y, obj) {
// Left
if (leftPressed) {
leftPressed = false;
btnLeft.setActive(false);
if (animals[activeAnimalIndex].moveDir === -1) animals[activeAnimalIndex].moveDir = 0;
}
// Right
if (rightPressed) {
rightPressed = false;
btnRight.setActive(false);
if (animals[activeAnimalIndex].moveDir === 1) animals[activeAnimalIndex].moveDir = 0;
}
// Jump
if (jumpPressed) {
jumpPressed = false;
btnJump.setActive(false);
}
};
// Collision helpers
function rectsIntersect(ax, ay, aw, ah, bx, by, bw, bh) {
return !(bx > ax + aw || bx + bw < ax || by > ay + ah || by + bh < ay);
}
// Check collision with blocks
function animalBlockCollision(animal) {
for (var i = 0; i < blocks.length; i++) {
var b = blocks[i];
var aw = animal.asset.width,
ah = animal.asset.height;
var bw = b.asset.width,
bh = b.asset.height;
// Simple AABB
if (rectsIntersect(animal.x - aw / 2, animal.y - ah / 2, aw, ah, b.x - bw / 2, b.y - bh / 2, bw, bh)) {
// Land on top
if (animal.y < b.y && animal.vy > 0) {
animal.y = b.y - bh / 2 - ah / 2;
animal.vy = 0;
animal.isOnGround = true;
if (animal.name === 'Frog') animal.jumpsLeft = 2;
}
// Push block (only Pig)
if (animal.name === 'Pig' && Math.abs(animal.x - b.x) < (aw + bw) / 2 && Math.abs(animal.y - b.y) < (ah + bh) / 2) {
b.x += animal.vx * 0.5;
// Clamp block
if (b.x < bw / 2) b.x = bw / 2;
if (b.x > 2048 - bw / 2) b.x = 2048 - bw / 2;
}
}
}
}
// Check collision with acid
function animalAcidCollision(animal) {
for (var i = 0; i < acids.length; i++) {
var a = acids[i];
var aw = animal.asset.width,
ah = animal.asset.height;
var aw2 = aw / 2,
ah2 = ah / 2;
var ax = animal.x - aw2,
ay = animal.y - ah2;
var bw = a.asset.width,
bh = a.asset.height;
var bx = a.x - bw / 2,
by = a.y - bh / 2;
if (rectsIntersect(ax, ay, aw, ah, bx, by, bw, bh)) {
// Flash and game over
LK.effects.flashScreen(0x00ffff, 800);
LK.showGameOver();
return true;
}
}
return false;
}
// Check if animal reached exit
function animalAtExit(animal) {
var aw = animal.asset.width,
ah = animal.asset.height;
var ax = animal.x - aw / 2,
ay = animal.y - ah / 2;
return rectsIntersect(ax, ay, aw, ah, exitRect.x, exitRect.y, exitRect.width, exitRect.height);
}
// Track which animals have escaped
var escaped = [false, false, false, false];
// Main game update
game.update = function () {
// Update all animals
for (var i = 0; i < animals.length; i++) {
animals[i].update();
animalBlockCollision(animals[i]);
if (animalAcidCollision(animals[i])) return;
// Check exit
if (!escaped[i] && animalAtExit(animals[i])) {
escaped[i] = true;
animals[i].visible = false;
// Flash green
LK.effects.flashScreen(0x00ff00, 400);
// Update score
var count = 0;
for (var j = 0; j < escaped.length; j++) if (escaped[j]) count++;
scoreTxt.setText('Escaped: ' + count + '/4');
// If all escaped, win!
if (count === 4) {
LK.showYouWin();
} else {
// Switch to next available animal
for (var k = 0; k < animals.length; k++) {
if (!escaped[k]) {
setActiveAnimal(k);
break;
}
}
}
}
}
// If active animal is escaped, switch
if (escaped[activeAnimalIndex]) {
for (var k = 0; k < animals.length; k++) {
if (!escaped[k]) {
setActiveAnimal(k);
break;
}
}
}
};
// Draw exit zone (for MVP, invisible, but could add a visual hint if desired)
// var exitHint = LK.getAsset('centerCircle', {anchorX:0.5, anchorY:0.5, x:exitZone.x+exitZone.w/2, y:exitZone.y+exitZone.h/2, scaleX:1.2, scaleY:1.2, tint:0x00ff00, alpha:0.2});
// game.addChild(exitHint);