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;
});
// Block class with gravity and simple physics
var Block = 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;
// 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) {
self.vy += self.gravity;
self.x += self.vx;
self.y += self.vy;
self.vx *= self.friction;
self.vy *= self.friction;
// 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 && Math.abs(self.vy) < 0.5) {
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;
}
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;
};
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 ---
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 Block();
blockTop.width = boxWidth;
blockTop.height = blockThickness;
blockTop.x = centerX;
blockTop.y = topY;
game.addChild(blockTop);
blocks.push(blockTop);
// Bottom horizontal block
var blockBottom = new Block();
blockBottom.width = boxWidth;
blockBottom.height = blockThickness;
blockBottom.x = centerX;
blockBottom.y = topY + boxHeight;
game.addChild(blockBottom);
blocks.push(blockBottom);
// Left vertical block
var blockLeft = new Block();
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
var blockRight = new Block();
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());
}
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
@@ -128,8 +128,69 @@
return dist < self.radius + other.radius;
};
return self;
});
+// Block class with gravity and simple physics
+var Block = 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;
+ // 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) {
+ self.vy += self.gravity;
+ self.x += self.vx;
+ self.y += self.vy;
+ self.vx *= self.friction;
+ self.vy *= self.friction;
+ // 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 && Math.abs(self.vy) < 0.5) {
+ 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;
+ }
+ 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;
+ };
+ return self;
+});
// Pig class
var Pig = Container.expand(function () {
var self = Container.call(this);
// Attach a green ellipse as the pig
@@ -394,45 +455,33 @@
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 = LK.getAsset('block', {
- anchorX: 0.5,
- anchorY: 0.5
- });
+ var blockTop = new Block();
blockTop.width = boxWidth;
blockTop.height = blockThickness;
blockTop.x = centerX;
blockTop.y = topY;
game.addChild(blockTop);
blocks.push(blockTop);
// Bottom horizontal block
- var blockBottom = LK.getAsset('block', {
- anchorX: 0.5,
- anchorY: 0.5
- });
+ var blockBottom = new Block();
blockBottom.width = boxWidth;
blockBottom.height = blockThickness;
blockBottom.x = centerX;
blockBottom.y = topY + boxHeight;
game.addChild(blockBottom);
blocks.push(blockBottom);
// Left vertical block
- var blockLeft = LK.getAsset('block', {
- anchorX: 0.5,
- anchorY: 0.5
- });
+ var blockLeft = new Block();
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
- var blockRight = LK.getAsset('block', {
- anchorX: 0.5,
- anchorY: 0.5
- });
+ var blockRight = new Block();
blockRight.width = blockThickness;
blockRight.height = boxHeight;
blockRight.x = centerX + boxWidth / 2 - blockThickness / 2;
blockRight.y = topY + boxHeight / 2;
@@ -535,8 +584,14 @@
// 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;