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: 417
User prompt
fix bugs
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: 417
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: 436
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: 429
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: 417
User prompt
make the sun bird throwlable if want
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: 417
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: 417
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: 417
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: 417
User prompt
detailed birds
User prompt
add trees
User prompt
add bottom woods under pig
User prompt
add support woods for the box because roof is falling
User prompt
make woods shaped big box
User prompt
extra two birds
User prompt
sun
User prompt
trees and blue air
User prompt
add back ground
User prompt
add something you want it game
User prompt
deletele second pig
/**** * 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; // Add a yellow triangle for the beak var beak = self.attachAsset('beakTriangle', { anchorX: 0.1, anchorY: 0.5 }); beak.width = birdBody.width * 0.48; beak.height = birdBody.height * 0.36; beak.x = birdBody.width * 0.56; beak.y = 0; beak.rotation = Math.PI / 8; // 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 { 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 (self.y && _typeof(self.y) === "object") { // Defensive: if self.y is an object, check if it's a Promise (has .then) if (typeof self.y.then === "function") { // If it's a Promise, set lastY to 0 to avoid .then errors self.lastY = 0; } else if (typeof self.y.valueOf === "function" && !isNaN(self.y.valueOf())) { self.lastY = Number(self.y.valueOf()); } else { self.lastY = 0; } } else { 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; }); // Block class (rectangular, can be horizontal or vertical) var Block = Container.expand(function () { var self = Container.call(this); // Attach a brown box as the block var blockAsset = self.attachAsset('block', { anchorX: 0.5, anchorY: 0.5 }); self.width = blockAsset.width; self.height = blockAsset.height; self.vx = 0; self.vy = 0; self.gravity = 0.7; self.friction = 0.98; self.bounce = 0.3; self.stopped = false; // Add health property for wood blocks self.health = 100; // 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.stopped) { // Apply gravity to wood blocks self.vy += self.gravity; self.x += self.vx; self.y += self.vy; self.vx *= self.friction; self.vy *= self.friction; // --- Ragdoll effect: angular physics --- if (typeof self.angularVelocity === "undefined") self.angularVelocity = 0; if (typeof self.angle === "undefined") self.angle = self.rotation || 0; // Apply angular velocity to rotation self.angle += self.angularVelocity; self.rotation = self.angle; // Dampen angular velocity (simulate friction) self.angularVelocity *= 0.97; // Block-on-block collision (stand or crash) for (var i = 0; i < blocks.length; i++) { var other = blocks[i]; if (other === self) continue; // Axis-aligned bounding box collision var selfLeft = self.x - self.width / 2; var selfRight = self.x + self.width / 2; var selfBottom = self.y + self.height / 2; var selfTop = self.y - self.height / 2; 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; // Check if horizontally overlapping and self is falling onto other if (selfRight > otherLeft && selfLeft < otherRight && selfBottom > otherTop && selfTop < otherTop && self.vy > 0 && self.y < other.y) { // Land on top of the other block self.y = otherTop - self.height / 2; // If falling fast, bounce/crash 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; // --- Ragdoll: add angular velocity based on impact --- var impact = self.vx * 0.1 + self.vy * 0.1; if (typeof self.angularVelocity === "undefined") self.angularVelocity = 0; self.angularVelocity += impact * (Math.random() - 0.5) * 0.2; if (typeof other.angularVelocity === "undefined") other.angularVelocity = 0; other.angularVelocity += impact * (Math.random() - 0.5) * 0.2; // Reduce health for both blocks based on impact var damage = Math.min(30, Math.max(5, Math.floor(Math.abs(self.vy) * 2))); self.health -= damage; other.health -= Math.floor(damage / 2); // Destroy self if health <= 0 if (self.health <= 0) { self.destroy(); return; } // Destroy other if health <= 0 if (other.health <= 0) { other.destroy(); } // Bird-block collision damage is handled in game.update } else { self.vy = 0; self.vx *= 0.8; if (Math.abs(self.vx) < 1) { self.stopped = true; } } } // Also allow side-to-side collision (prevent overlap horizontally) if (selfBottom > otherTop && selfTop < otherBottom) { // Check if self is moving right into other's left side if (selfRight > otherLeft && selfLeft < otherLeft && self.vx > 0) { self.x = otherLeft - self.width / 2; self.vx = -self.vx * self.bounce; // Transfer some force to the other block (right hit) other.vx += self.vx * 0.2; // --- Ragdoll: add angular velocity based on side impact --- var impact = self.vx * 0.1; if (typeof self.angularVelocity === "undefined") self.angularVelocity = 0; self.angularVelocity += impact * 0.1; if (typeof other.angularVelocity === "undefined") other.angularVelocity = 0; other.angularVelocity -= impact * 0.1; } // Check if self is moving left into other's right side if (selfLeft < otherRight && selfRight > otherRight && self.vx < 0) { self.x = otherRight + self.width / 2; self.vx = -self.vx * self.bounce; // Transfer some force to the other block (left hit) other.vx += self.vx * 0.2; // --- Ragdoll: add angular velocity based on side impact --- var impact = self.vx * 0.1; if (typeof self.angularVelocity === "undefined") self.angularVelocity = 0; self.angularVelocity -= impact * 0.1; if (typeof other.angularVelocity === "undefined") other.angularVelocity = 0; other.angularVelocity += impact * 0.1; } } } // 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; } else { self.vy = 0; self.vx *= 0.8; if (Math.abs(self.vx) < 1) { self.stopped = true; } } } // Wall collision if (self.x - self.width / 2 < 0) { self.x = self.width / 2; self.vx = -self.vx * self.bounce; } if (self.x + self.width / 2 > 2048) { self.x = 2048 - self.width / 2; self.vx = -self.vx * self.bounce; } } // Update lastX and lastY after movement self.lastX = self.x; self.lastY = self.y; }; // Simple rectangle collision with circle (bird) self.intersectsCircle = function (circle) { var cx = circle.x; var cy = circle.y; var rx = self.x; var ry = self.y; var hw = self.width / 2; var hh = self.height / 2; // Closest point on rectangle to circle center var closestX = Math.max(rx - hw, Math.min(cx, rx + hw)); var closestY = Math.max(ry - hh, Math.min(cy, ry + hh)); var dx = cx - closestX; var dy = cy - closestY; return dx * dx + dy * dy < circle.radius * circle.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; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // Sky blue }); /**** * Game Code ****/ // --- Asset Initialization (shapes) --- // --- Add Background Image --- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 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); // --- Add Sun to the Sky (throwable bonus bird) --- var sun = LK.getAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); sun.width = 320; sun.height = 320; sun.tint = 0xfff700; // bright yellow sun.x = 350; sun.y = 350; game.addChild(sun); // Sun bird as a bonus bird (throwable if tapped/dragged) var sunBird = null; var sunBirdActive = false; // Helper: create a Bird at sun's position, but golden and big function launchSunBird() { if (sunBirdActive) return; sun.visible = false; sunBirdActive = true; sunBird = new Bird(); sunBird.x = sun.x; sunBird.y = sun.y; sunBird.radius = sun.width / 2; // Make it look like the sun (bigger, yellow) sunBird.children[0].tint = 0xfff700; // main body sunBird.children[0].width = sun.width; sunBird.children[0].height = sun.height; // Belly, eyes, beak: scale up for (var i = 1; i < sunBird.children.length; i++) { sunBird.children[i].width *= 3.5; sunBird.children[i].height *= 3.5; sunBird.children[i].x *= 3.5; sunBird.children[i].y *= 3.5; } sunBird.gravity = 0.35; sunBird.friction = 0.998; sunBird.bounce = 0.5; sunBird.stopped = false; sunBird.launched = false; birds.push(sunBird); game.addChild(sunBird); currentBird = sunBird; birdIndex = birds.length - 1; updateBirdsLeft(); launching = false; } // Allow dragging/launching the sun if the player taps it sun.interactive = true; sun.hitArea = { x: -sun.width / 2, y: -sun.height / 2, width: sun.width, height: sun.height }; game.down = function (origDown) { return function (x, y, obj) { // If sun is tapped and not yet used, allow to launch it if (!sunBirdActive && sun.visible) { var dx = x - sun.x; var dy = y - sun.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < sun.width / 2) { launchSunBird(); // Now allow drag as normal isDragging = true; dragStart.x = x; dragStart.y = y; return; } } // Otherwise, normal bird drag if (typeof origDown === "function") origDown(x, y, obj); }; }(game.down); game.move = function (origMove) { return function (x, y, obj) { if (isDragging && currentBird && !currentBird.launched) { // Limit drag distance from slingshot or sun start var originX = sunBirdActive ? sun.x : slingshotX; var originY = sunBirdActive ? sun.y : slingshotY; var dx = x - originX; var dy = y - originY; var dist = getDistance(x, y, originX, originY); var maxLen = sunBirdActive ? 320 : slingshotBandLength; if (dist > maxLen) { var angle = getAngle(originX, originY, x, y); dx = Math.cos(angle) * maxLen; dy = Math.sin(angle) * maxLen; } currentBird.x = originX + dx; currentBird.y = originY + dy; dragEnd.x = currentBird.x; dragEnd.y = currentBird.y; } if (typeof origMove === "function") origMove(x, y, obj); }; }(game.move); game.up = function (origUp) { return function (x, y, obj) { if (isDragging && currentBird && !currentBird.launched) { isDragging = false; // Calculate launch velocity var originX = sunBirdActive ? sun.x : slingshotX; var originY = sunBirdActive ? sun.y : slingshotY; var dx = originX - currentBird.x; var dy = originY - currentBird.y; var power = sunBirdActive ? 0.12 : 0.18; currentBird.vx = dx * power; currentBird.vy = dy * power; currentBird.launched = true; launching = true; // Animate back tween(currentBird, { x: currentBird.x, y: currentBird.y }, { duration: 80 }); } if (typeof origUp === "function") origUp(x, y, obj); }; }(game.up); // When sun bird stops, remove it from play and restore sun if not used game.update = function (origUpdate) { return function () { if (sunBirdActive && sunBird && sunBird.launched && sunBird.stopped) { // Remove sun bird from birds array var idx = birds.indexOf(sunBird); if (idx !== -1) birds.splice(idx, 1); sunBird.destroy(); sunBird = null; sunBirdActive = false; // Don't restore sun (one use only) // Optionally: sun.visible = true; // Move to next bird if any if (birdIndex < birds.length) { currentBird = birds[birdIndex]; } } if (typeof origUpdate === "function") origUpdate(); }; }(game.update); // --- 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 = 180; 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; // Place birds 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]; // Place blocks to form a house shape var houseCenterX = 1500; var houseBottomY = groundY - 100; var wallW = 180; var wallH = 40; var wallHeight = 4; // number of vertical wall blocks var roofW = 180; var roofH = 40; // --- House base: two vertical walls (left/right), 4 blocks high --- for (var i = 0; i < wallHeight; i++) { // Left wall var leftWall = new Block(); leftWall.x = houseCenterX - wallW / 2 + wallH / 2; leftWall.y = houseBottomY - i * wallW; leftWall.rotation = Math.PI / 2; blocks.push(leftWall); game.addChild(leftWall); // Right wall var rightWall = new Block(); rightWall.x = houseCenterX + wallW / 2 - wallH / 2; rightWall.y = houseBottomY - i * wallW; rightWall.rotation = Math.PI / 2; blocks.push(rightWall); game.addChild(rightWall); } // --- House base: bottom block (floor) --- var houseFloor = new Block(); houseFloor.x = houseCenterX; houseFloor.y = houseBottomY + wallH / 2; blocks.push(houseFloor); game.addChild(houseFloor); // --- House base: top block (ceiling) --- var houseCeiling = new Block(); houseCeiling.x = houseCenterX; houseCeiling.y = houseBottomY - (wallHeight - 1) * wallW - wallH / 2; blocks.push(houseCeiling); game.addChild(houseCeiling); // --- House roof: two diagonal blocks (left/right) --- var roofLeft = new Block(); roofLeft.x = houseCenterX - wallW / 2 + wallH / 2 + 30; roofLeft.y = houseCeiling.y - wallW / 2 + 10; roofLeft.rotation = Math.PI / 4; // 45 degrees blocks.push(roofLeft); game.addChild(roofLeft); var roofRight = new Block(); roofRight.x = houseCenterX + wallW / 2 - wallH / 2 - 30; roofRight.y = houseCeiling.y - wallW / 2 + 10; roofRight.rotation = -Math.PI / 4; // -45 degrees blocks.push(roofRight); game.addChild(roofRight); // --- House roof: top horizontal block (roof ridge) --- var roofRidge = new Block(); roofRidge.x = houseCenterX; roofRidge.y = houseCeiling.y - wallW / 2 - roofH / 2 + 10; blocks.push(roofRidge); game.addChild(roofRidge); // Place pig on the house ceiling var pig1 = new Pig(); pig1.x = houseCeiling.x; pig1.y = houseCeiling.y - houseCeiling.height / 2 - pig1.radius - 50; pigs.push(pig1); game.addChild(pig1); // (Second pig inside the house removed) // --- Ensure blocks and pigs are not hanging in the air --- for (var i = 0; i < blocks.length; i++) { var block = blocks[i]; // Check if block is supported by ground or another block var supported = false; // Supported by ground if (Math.abs(block.y + block.height / 2 - groundY) < 2) { supported = true; } // Supported by another block below for (var j = 0; j < blocks.length; j++) { if (i === j) continue; var other = blocks[j]; var blockBottom = block.y + block.height / 2; var otherTop = other.y - other.height / 2; var horizontalOverlap = block.x + block.width / 2 > other.x - other.width / 2 && block.x - block.width / 2 < other.x + other.width / 2; if (horizontalOverlap && Math.abs(blockBottom - otherTop) < 2) { supported = true; break; } } block.stopped = !supported ? false : block.stopped; } for (var i = 0; i < pigs.length; i++) { var pig = pigs[i]; // Check if pig is supported by ground or a block var supported = false; // Supported by ground if (Math.abs(pig.y + pig.radius - groundY) < 2) { supported = true; } // Supported by a block below for (var j = 0; j < blocks.length; j++) { var block = blocks[j]; var pigBottom = pig.y + pig.radius; var blockTop = block.y - block.height / 2; var horizontalOverlap = pig.x + pig.radius > block.x - block.width / 2 && pig.x - pig.radius < block.x + block.width / 2; if (horizontalOverlap && Math.abs(pigBottom - blockTop) < 2) { supported = true; break; } } 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 for (var i = 0; i < blocks.length; i++) { blocks[i].update(); } // --- Check support for each block: if not supported, set stopped = false so it falls --- for (var i = 0; i < blocks.length; i++) { var block = blocks[i]; // Check if block is supported by ground or another block var supported = false; // Supported by ground if (Math.abs(block.y + block.height / 2 - groundY) < 2) { supported = true; } // Supported by another block below for (var j = 0; j < blocks.length; j++) { if (i === j) continue; var other = blocks[j]; var blockBottom = block.y + block.height / 2; var otherTop = other.y - other.height / 2; var horizontalOverlap = block.x + block.width / 2 > other.x - other.width / 2 && block.x - block.width / 2 < other.x + other.width / 2; if (horizontalOverlap && Math.abs(blockBottom - otherTop) < 2) { supported = true; break; } } // If not supported, set stopped = false so it will fall if (!supported) { block.stopped = false; } } // Bird-block collision for (var i = 0; i < birds.length; i++) { var bird = birds[i]; if (!bird.launched) continue; if (bird.stopped) continue; // Collide with blocks for (var j = 0; j < blocks.length; j++) { var block = blocks[j]; // Remove block.stopped check so birds can always touch wood if (block.intersectsCircle(bird)) { // Calculate collision angle and force var angle = getAngle(bird.x, bird.y, block.x, block.y); var force = Math.sqrt(bird.vx * bird.vx + bird.vy * bird.vy) * 0.5; // Apply force to block block.vx += Math.cos(angle) * force * 0.7; block.vy += Math.sin(angle) * force * 0.7; // --- Ragdoll: add angular velocity to block based on bird impact --- var impact = force * 0.2; if (typeof block.angularVelocity === "undefined") block.angularVelocity = 0; block.angularVelocity += impact * (Math.random() - 0.5); // Apply bounce to bird bird.vx = -bird.vx * 0.4; bird.vy = -bird.vy * 0.4; // Move bird out of block to prevent sticking var overlap = bird.radius + Math.max(block.width, block.height) / 2 - getDistance(bird.x, bird.y, block.x, block.y); if (overlap > 0) { bird.x += Math.cos(angle) * overlap * 0.5; bird.y += Math.sin(angle) * overlap * 0.5; } // Optionally, mark block as not stopped to allow it to move if hit hard block.stopped = false; // Birds deal damage to woods on collision var birdDamage = Math.min(40, Math.max(5, Math.floor(force * 2))); block.health -= birdDamage; if (block.health <= 0) { block.destroy(); blocks.splice(j, 1); j--; // Adjust index since we removed a block continue; } } } } // 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()); } 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()); } } } // Block-pig collision (falling blocks can kill pigs) for (var i = 0; i < blocks.length; i++) { var block = blocks[i]; if (block.stopped) continue; for (var j = 0; j < pigs.length; j++) { var pig = pigs[j]; if (!pig.alive) continue; // Treat pig as circle, block as rectangle if (block.intersectsCircle(pig)) { // Only kill pig if block is moving fast enough (e.g. falling hard) var blockSpeed = Math.sqrt(block.vx * block.vx + block.vy * block.vy); if (blockSpeed > 8) { 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; } // Supported by a block below for (var j = 0; j < blocks.length; j++) { var block = blocks[j]; var pigBottom = pig.y + pig.radius; var blockTop = block.y - block.height / 2; var horizontalOverlap = pig.x + pig.radius > block.x - block.width / 2 && pig.x - pig.radius < block.x + block.width / 2; if (horizontalOverlap && Math.abs(pigBottom - blockTop) < 2) { supported = true; break; } } 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
@@ -117,11 +117,14 @@
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 (self.y && _typeof(self.y) === "object" && typeof self.y.then !== "function") {
- // Defensive: if self.y is an object but not a Promise, try to extract a numeric value
- if (typeof self.y.valueOf === "function" && !isNaN(self.y.valueOf())) {
+ } else if (self.y && _typeof(self.y) === "object") {
+ // Defensive: if self.y is an object, check if it's a Promise (has .then)
+ if (typeof self.y.then === "function") {
+ // If it's a Promise, set lastY to 0 to avoid .then errors
+ self.lastY = 0;
+ } else if (typeof self.y.valueOf === "function" && !isNaN(self.y.valueOf())) {
self.lastY = Number(self.y.valueOf());
} else {
self.lastY = 0;
}