User prompt
woods can fall
User prompt
birds can push down the blocks
User prompt
add gravity for all blocsk
User prompt
side boxes have gravty too
User prompt
add ragdoll for boxes
User prompt
birds can touch boxes
User prompt
boxes can fall
User prompt
add box gravity
User prompt
make boxes can touch other boxes
User prompt
add gravity for boxes
User prompt
another box top
User prompt
add two big boxes top top
User prompt
bigger box.
User prompt
make them a box
User prompt
put the woods shaped two box
User prompt
add on the game two box made of wood
User prompt
create two box mode of wood
User prompt
Add a Block class named wood
User prompt
remove bird nosses
User prompt
Please fix the bug: 'TypeError: birds[i].update is not a function' in or related to this line: 'birds[i].update();' Line Number: 378
User prompt
deletele bird dteails
User prompt
detele block
User prompt
Please fix the bug: 's.apply(...).then is not a function' in or related to this line: 'self.lastY = self.y;' Line Number: 433
User prompt
deletele the wood blocks from save and game
User prompt
deletele sun
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bird class var Bird = Container.expand(function () { var self = Container.call(this); // Attach a red ellipse as the main bird body var birdBody = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); birdBody.width = 90; birdBody.height = 90; // Add a white ellipse for the belly var belly = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); belly.width = birdBody.width * 0.7; belly.height = birdBody.height * 0.5; belly.x = 0; belly.y = birdBody.height * 0.18; belly.tint = 0xffffff; // Add a black ellipse for the left eye var leftEye = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); leftEye.width = birdBody.width * 0.18; leftEye.height = birdBody.height * 0.18; leftEye.x = -birdBody.width * 0.18; leftEye.y = -birdBody.height * 0.18; leftEye.tint = 0x000000; // Add a black ellipse for the right eye var rightEye = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); rightEye.width = birdBody.width * 0.18; rightEye.height = birdBody.height * 0.18; rightEye.x = birdBody.width * 0.08; rightEye.y = -birdBody.height * 0.18; rightEye.tint = 0x000000; // Physics properties self.vx = 0; self.vy = 0; self.launched = false; self.radius = birdBody.width / 2; self.gravity = 0.35; self.friction = 0.998; self.bounce = 0.5; self.stopped = false; // Called every tick self.update = function () { // Track lastX and lastY for physics events if (typeof self.lastX === "undefined") self.lastX = self.x; if (typeof self.lastY === "undefined") self.lastY = self.y; if (self.launched && !self.stopped) { // Standard projectile physics, no tracking or homing self.vy += self.gravity; self.x += self.vx; self.y += self.vy; // Friction self.vx *= self.friction; self.vy *= self.friction; // Floor collision if (self.y + self.radius > groundY) { self.y = groundY - self.radius; if (Math.abs(self.vy) > 2) { self.vy = -self.vy * self.bounce; self.vx *= 0.8; self.stopped = false; // Don't stop if still bouncing } else { self.vy = 0; self.vx *= 0.8; // Only stop if both vx and vy are very small and bird is on ground if (Math.abs(self.vx) < 1 && Math.abs(self.vy) < 0.5) { self.stopped = true; } else { self.stopped = false; } } } // Wall collision if (self.x - self.radius < 0) { self.x = self.radius; self.vx = -self.vx * self.bounce; } if (self.x + self.radius > 2048) { self.x = 2048 - self.radius; self.vx = -self.vx * self.bounce; } } // Update lastX and lastY after movement if (typeof self.x === "number" && !isNaN(self.x)) { self.lastX = self.x; } else if (typeof self.x === "string" && !isNaN(parseFloat(self.x))) { self.lastX = parseFloat(self.x); } else if (typeof self.lastX === "number" && !isNaN(self.lastX)) { // keep previous } else { self.lastX = 0; } if (typeof self.y === "number" && !isNaN(self.y)) { self.lastY = self.y; } else if (typeof self.y === "string" && !isNaN(parseFloat(self.y))) { self.lastY = parseFloat(self.y); } else if (typeof self.lastY === "number" && !isNaN(self.lastY)) { // keep previous } else { self.lastY = 0; } // Defensive: always ensure lastY is a number if (typeof self.lastY !== "number" || isNaN(self.lastY)) { self.lastY = 0; } }; // Simple circle collision self.intersectsCircle = function (other) { var dx = self.x - other.x; var dy = self.y - other.y; var dist = Math.sqrt(dx * dx + dy * dy); return dist < self.radius + other.radius; }; return self; }); // Pig class var Pig = Container.expand(function () { var self = Container.call(this); // Attach a green ellipse as the pig var pigAsset = self.attachAsset('pig', { anchorX: 0.5, anchorY: 0.5 }); self.radius = pigAsset.width / 2; self.alive = true; // Physics properties for pigs self.vx = 0; self.vy = 0; self.gravity = 0.7; self.friction = 0.98; self.bounce = 0.3; self.stopped = false; // Called every tick self.update = function () { if (!self.alive) return; // Track lastX and lastY for physics events if (typeof self.lastX === "undefined") self.lastX = self.x; if (typeof self.lastY === "undefined") self.lastY = self.y; if (!self.stopped) { self.vy += self.gravity; self.x += self.vx; self.y += self.vy; self.vx *= self.friction; self.vy *= self.friction; // Pig-on-block collision: prevent pig from going inside the wood blocks for (var i = 0; i < blocks.length; i++) { var block = blocks[i]; // Axis-aligned bounding box for block var blockLeft = block.x - block.width / 2; var blockRight = block.x + block.width / 2; var blockTop = block.y - block.height / 2; var blockBottom = block.y + block.height / 2; // Only check if pig is above block and falling if (self.y < block.y && self.vy > 0) { // Check horizontal overlap if (self.x + self.radius > blockLeft && self.x - self.radius < blockRight) { // Check if pig's bottom is entering block's top if (self.y + self.radius > blockTop && self.y - self.radius < blockBottom) { // Place pig on top of block self.y = blockTop - self.radius; if (Math.abs(self.vy) > 2) { self.vy = -self.vy * self.bounce; self.vx *= 0.8; // Transfer some force to the block below (crash effect) block.vx += self.vx * 0.2; block.vy += self.vy * 0.2; } else { self.vy = 0; self.vx *= 0.8; if (Math.abs(self.vx) < 1) { self.stopped = true; } } } } } } // Floor collision if (self.y + self.radius > groundY) { self.y = groundY - self.radius; if (Math.abs(self.vy) > 2) { self.vy = -self.vy * self.bounce; self.vx *= 0.8; } else { self.vy = 0; self.vx *= 0.8; if (Math.abs(self.vx) < 1) { self.stopped = true; } } } // Wall collision if (self.x - self.radius < 0) { self.x = self.radius; self.vx = -self.vx * self.bounce; } if (self.x + self.radius > 2048) { self.x = 2048 - self.radius; self.vx = -self.vx * self.bounce; } } // Update lastX and lastY after movement self.lastX = self.x; self.lastY = self.y; }; return self; }); // RagdollBlock class with rotation and angular physics var RagdollBlock = Container.expand(function () { var self = Container.call(this); // Attach block asset var blockAsset = self.attachAsset('block', { anchorX: 0.5, anchorY: 0.5 }); // Set width/height after attach self.width = blockAsset.width; self.height = blockAsset.height; // Physics properties self.vx = 0; self.vy = 0; self.gravity = 0.7; self.friction = 0.98; self.bounce = 0.2; self.stopped = false; // Ragdoll/rotation properties self.angle = 0; self.angularVelocity = 0; self.angularFriction = 0.97; self.maxAngular = 0.25; // Called every tick self.update = function () { // Track lastX and lastY for physics events if (typeof self.lastX === "undefined") self.lastX = self.x; if (typeof self.lastY === "undefined") self.lastY = self.y; if (typeof self.lastAngle === "undefined") self.lastAngle = self.angle; if (!self.stopped) { self.vy += self.gravity; self.x += self.vx; self.y += self.vy; self.vx *= self.friction; self.vy *= self.friction; self.angle += self.angularVelocity; self.angularVelocity *= self.angularFriction; // Clamp angular velocity if (self.angularVelocity > self.maxAngular) self.angularVelocity = self.maxAngular; if (self.angularVelocity < -self.maxAngular) self.angularVelocity = -self.maxAngular; // Block-on-block collision (stacking/landing) for (var i = 0; i < blocks.length; i++) { var other = blocks[i]; if (other === self) continue; // Axis-aligned bounding box for other block var otherLeft = other.x - other.width / 2; var otherRight = other.x + other.width / 2; var otherTop = other.y - other.height / 2; var otherBottom = other.y + other.height / 2; // Only check if self is above other and falling if (self.y < other.y && self.vy > 0) { // Check horizontal overlap if (self.x + self.width / 2 > otherLeft && self.x - self.width / 2 < otherRight) { // Check if self's bottom is entering other's top if (self.y + self.height / 2 > otherTop && self.y - self.height / 2 < otherBottom) { // Place self on top of other self.y = otherTop - self.height / 2; if (Math.abs(self.vy) > 2) { self.vy = -self.vy * self.bounce; self.vx *= 0.8; // Transfer some force to the block below (crash effect) other.vx += self.vx * 0.2; other.vy += self.vy * 0.2; // Add angular velocity for ragdoll effect self.angularVelocity += (self.vx - other.vx) * 0.01 + (Math.random() - 0.5) * 0.05; other.angularVelocity += (self.vx - other.vx) * 0.005 + (Math.random() - 0.5) * 0.03; } else { self.vy = 0; self.vx *= 0.8; if (Math.abs(self.vx) < 1 && Math.abs(self.vy) < 0.5 && Math.abs(self.angularVelocity) < 0.01) { self.stopped = true; } else { self.stopped = false; } } } } } } // Floor collision if (self.y + self.height / 2 > groundY) { self.y = groundY - self.height / 2; if (Math.abs(self.vy) > 2) { self.vy = -self.vy * self.bounce; self.vx *= 0.8; // Add angular velocity for ragdoll effect self.angularVelocity += self.vx * 0.01 + (Math.random() - 0.5) * 0.05; } else { self.vy = 0; self.vx *= 0.8; if (Math.abs(self.vx) < 1 && Math.abs(self.vy) < 0.5 && Math.abs(self.angularVelocity) < 0.01) { self.stopped = true; } else { self.stopped = false; } } } // Wall collision if (self.x - self.width / 2 < 0) { self.x = self.width / 2; self.vx = -self.vx * self.bounce; self.angularVelocity += (Math.random() - 0.5) * 0.1; } if (self.x + self.width / 2 > 2048) { self.x = 2048 - self.width / 2; self.vx = -self.vx * self.bounce; self.angularVelocity += (Math.random() - 0.5) * 0.1; } } // Update lastX, lastY, lastAngle after movement self.lastX = self.x; self.lastY = self.y; self.lastAngle = self.angle; // Apply rotation to asset blockAsset.rotation = self.angle; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // Sky blue }); /**** * Game Code ****/ // --- Asset Initialization (shapes) --- // --- Add Background Image --- var background = LK.getAsset('block', { anchorX: 0, anchorY: 0 }); background.width = 2048; background.height = 2732; background.tint = 0x87ceeb; // Sky blue tint for now background.x = 0; background.y = 0; game.addChild(background); // (Sun removed) // --- Add Trees for Scenery --- var treeTrunkColor = 0x8b5a2b; var treeLeafColor = 0x228b22; var treeCount = 4; var treeSpacing = 2048 / (treeCount + 1); for (var i = 0; i < treeCount; i++) { // Trunk var trunk = LK.getAsset('block', { anchorX: 0.5, anchorY: 1 }); trunk.width = 40; trunk.height = 220; trunk.tint = treeTrunkColor; trunk.x = treeSpacing * (i + 1); trunk.y = groundY + 10; game.addChild(trunk); // Leaves (ellipse) var leaves = LK.getAsset('bird', { anchorX: 0.5, anchorY: 1 }); leaves.width = 180; leaves.height = 160; leaves.tint = treeLeafColor; leaves.x = trunk.x; leaves.y = trunk.y - trunk.height + 10; game.addChild(leaves); } // --- Game Variables --- var birds = []; var pigs = []; var blocks = []; var currentBird = null; var birdIndex = 0; var isDragging = false; var dragStart = { x: 0, y: 0 }; var dragEnd = { x: 0, y: 0 }; var slingshotX = 260; // Moved more right from 60 var slingshotY = 2000; // Raised slingshot higher (was 2450) var slingshotBandLength = 180; var maxBirds = 5; var groundY = 2650; var level = 1; var launching = false; var score = 0; // --- GUI --- var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var birdsLeftTxt = new Text2('', { size: 80, fill: 0xFFFFFF }); birdsLeftTxt.anchor.set(0.5, 0); LK.gui.topRight.addChild(birdsLeftTxt); // --- Draw Ground --- var ground = LK.getAsset('ground', { anchorX: 0, anchorY: 0 }); ground.x = 0; ground.y = groundY; game.addChild(ground); // --- Draw Little Mountain below the slingshot --- var mountainWidth = 400; var mountainHeight = 120; var mountain = LK.getAsset('block', { anchorX: 0.5, anchorY: 1 }); mountain.width = mountainWidth; mountain.height = mountainHeight; mountain.x = slingshotX; mountain.y = groundY + 10; // Slightly below ground for overlap mountain.tint = 0x8b7765; // Optional: make it look more like a mountain game.addChild(mountain); // --- Draw Slingshot --- var slingshot = LK.getAsset('slingshot', { anchorX: 0.5, anchorY: 1 }); slingshot.x = slingshotX; slingshot.y = slingshotY + 90; game.addChild(slingshot); // --- Level Setup --- function setupLevel() { // Add a golden star collectible above the house for bonus points if (typeof star === "undefined") { star = LK.getAsset('block', { anchorX: 0.5, anchorY: 0.5 }); star.width = 80; star.height = 80; star.tint = 0xffd700; // gold color star.isStar = true; } star.x = 1500; star.y = groundY - 600; star.collected = false; star.visible = true; game.addChild(star); // Clear previous for (var i = 0; i < birds.length; i++) birds[i].destroy(); for (var i = 0; i < pigs.length; i++) pigs[i].destroy(); for (var i = 0; i < blocks.length; i++) blocks[i].destroy(); birds = []; pigs = []; blocks = []; birdIndex = 0; score = 0; LK.setScore(0); scoreTxt.setText('0'); launching = false; for (var i = 0; i < maxBirds; i++) { var bird = new Bird(); bird.x = slingshotX - 120 - i * 80; bird.y = slingshotY + 40; birds.push(bird); game.addChild(bird); } currentBird = birds[birdIndex]; var pig1 = new Pig(); pig1.x = 1500; pig1.y = groundY - 400; pigs.push(pig1); game.addChild(pig1); // (Second pig inside the house removed) // --- Add two big wood block boxes stacked on top of each other --- // Box parameters var boxWidth = 320; var boxHeight = 220; var blockThickness = 40; var box1CenterX = 1500; var box1TopY = groundY - 300; var box2CenterX = 1500; var box2TopY = box1TopY - boxHeight - 80; // 80px gap between boxes // Helper to add a box at (centerX, topY) function addBox(centerX, topY) { // Top horizontal block var blockTop = new RagdollBlock(); blockTop.width = boxWidth; blockTop.height = blockThickness; blockTop.x = centerX; blockTop.y = topY; game.addChild(blockTop); blocks.push(blockTop); // Bottom horizontal block var blockBottom = new RagdollBlock(); blockBottom.width = boxWidth; blockBottom.height = blockThickness; blockBottom.x = centerX; blockBottom.y = topY + boxHeight; game.addChild(blockBottom); blocks.push(blockBottom); // Left vertical block (now uses RagdollBlock for gravity/physics) var blockLeft = new RagdollBlock(); blockLeft.width = blockThickness; blockLeft.height = boxHeight; blockLeft.x = centerX - boxWidth / 2 + blockThickness / 2; blockLeft.y = topY + boxHeight / 2; game.addChild(blockLeft); blocks.push(blockLeft); // Right vertical block (now uses RagdollBlock for gravity/physics) var blockRight = new RagdollBlock(); blockRight.width = blockThickness; blockRight.height = boxHeight; blockRight.x = centerX + boxWidth / 2 - blockThickness / 2; blockRight.y = topY + boxHeight / 2; game.addChild(blockRight); blocks.push(blockRight); } // First (bottom) box addBox(box1CenterX, box1TopY); // Second (top) box addBox(box2CenterX, box2TopY); // Third (topmost) box var box3CenterX = 1500; var box3TopY = box2TopY - boxHeight - 80; // 80px gap between boxes addBox(box3CenterX, box3TopY); // --- Ensure blocks and pigs are not hanging in the air --- for (var i = 0; i < pigs.length; i++) { var pig = pigs[i]; // Check if pig is supported by ground var supported = false; // Supported by ground if (Math.abs(pig.y + pig.radius - groundY) < 2) { supported = true; } pig.stopped = !supported ? false : pig.stopped; } updateBirdsLeft(); // Reset star collectible if it exists if (typeof star !== "undefined") { star.collected = false; star.visible = true; } } // --- Update birds left text --- function updateBirdsLeft() { birdsLeftTxt.setText('Birds: ' + (maxBirds - birdIndex)); } // --- Drag and Launch Logic --- function getDistance(x1, y1, x2, y2) { var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx * dx + dy * dy); } function getAngle(x1, y1, x2, y2) { return Math.atan2(y2 - y1, x2 - x1); } // Only allow drag if not launched game.down = function (x, y, obj) { if (launching) return; if (!currentBird || currentBird.launched) return; // Only allow drag if touch is near the bird var dist = getDistance(x, y, currentBird.x, currentBird.y); if (dist < currentBird.radius * 1.5) { isDragging = true; dragStart.x = x; dragStart.y = y; } }; game.move = function (x, y, obj) { if (isDragging && currentBird && !currentBird.launched) { // Limit drag distance var dx = x - slingshotX; var dy = y - slingshotY; var dist = getDistance(x, y, slingshotX, slingshotY); if (dist > slingshotBandLength) { var angle = getAngle(slingshotX, slingshotY, x, y); dx = Math.cos(angle) * slingshotBandLength; dy = Math.sin(angle) * slingshotBandLength; } currentBird.x = slingshotX + dx; currentBird.y = slingshotY + dy; dragEnd.x = currentBird.x; dragEnd.y = currentBird.y; } }; game.up = function (x, y, obj) { if (isDragging && currentBird && !currentBird.launched) { isDragging = false; // Calculate launch velocity var dx = slingshotX - currentBird.x; var dy = slingshotY - currentBird.y; currentBird.vx = dx * 0.18; currentBird.vy = dy * 0.18; currentBird.launched = true; launching = true; // Animate slingshot back tween(currentBird, { x: currentBird.x, y: currentBird.y }, { duration: 80 }); } }; // --- Main Game Loop --- game.update = function () { // Update all birds for (var i = 0; i < birds.length; i++) { birds[i].update(); } // Update all pigs for (var i = 0; i < pigs.length; i++) { pigs[i].update(); } // Update all blocks (gravity/physics) for (var i = 0; i < blocks.length; i++) { if (typeof blocks[i].update === "function") { blocks[i].update(); } } // Bird-pig collision for (var i = 0; i < birds.length; i++) { var bird = birds[i]; if (!bird.launched) continue; if (bird.stopped) continue; // Bird-star collision if (typeof star !== "undefined" && star.visible && !star.collected && bird.intersectsCircle({ x: star.x, y: star.y, radius: star.width / 2 })) { star.collected = true; star.visible = false; LK.setScore(LK.getScore() + 5000); scoreTxt.setText(LK.getScore()); } // Bird-block collision (circle-rectangle) for (var b = 0; b < blocks.length; b++) { var block = blocks[b]; // Find closest point on block to bird center var closestX = Math.max(block.x - block.width / 2, Math.min(bird.x, block.x + block.width / 2)); var closestY = Math.max(block.y - block.height / 2, Math.min(bird.y, block.y + block.height / 2)); var dx = bird.x - closestX; var dy = bird.y - closestY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < bird.radius) { // Simple bounce: reflect bird's velocity based on collision normal var nx = dx / (dist || 1); var ny = dy / (dist || 1); // Only bounce if moving toward the block var dot = bird.vx * nx + bird.vy * ny; if (dot < 0) { // Move bird out of block bird.x = closestX + nx * (bird.radius + 0.5); bird.y = closestY + ny * (bird.radius + 0.5); // Bounce var bounce = 0.5; var friction = 0.7; // Reflect velocity var vDotN = bird.vx * nx + bird.vy * ny; bird.vx = (bird.vx - 2 * vDotN * nx) * bounce; bird.vy = (bird.vy - 2 * vDotN * ny) * bounce; // Transfer some force to the block block.vx += bird.vx * 0.15; block.vy += bird.vy * 0.15; // Friction on block block.vx *= friction; block.vy *= friction; } } } for (var j = 0; j < pigs.length; j++) { var pig = pigs[j]; if (!pig.alive) continue; if (bird.intersectsCircle(pig)) { pig.alive = false; pig.visible = false; LK.setScore(LK.getScore() + 1000); scoreTxt.setText(LK.getScore()); } } } // --- Check support for each pig: if not supported, set stopped = false so it falls --- for (var i = 0; i < pigs.length; i++) { var pig = pigs[i]; if (!pig.alive) continue; var supported = false; // Supported by ground if (Math.abs(pig.y + pig.radius - groundY) < 2) { supported = true; } if (!supported) { pig.stopped = false; } } // Remove dead pigs var allPigsDead = true; for (var i = 0; i < pigs.length; i++) { if (pigs[i].alive) { allPigsDead = false; break; } } // If all pigs dead, win (only if there was at least one pig) if (pigs.length > 0 && allPigsDead) { LK.showYouWin(); return; } // If current bird stopped, move to next bird if (currentBird && currentBird.launched && currentBird.stopped && !isDragging && launching) { birdIndex++; updateBirdsLeft(); if (birdIndex < birds.length) { currentBird = birds[birdIndex]; // Move next bird to slingshot tween(currentBird, { x: slingshotX, y: slingshotY }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { launching = false; } }); } else { // Out of birds, game over LK.showGameOver(); return; } launching = false; } }; // --- Start Game --- setupLevel();
===================================================================
--- original.js
+++ change.js