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); ===================================================================
--- original.js
+++ change.js
@@ -334,8 +334,9 @@
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);
}
}