/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bird class var Bird = Container.expand(function () { var self = Container.call(this); self.type = 'red'; // 'red', 'blue', 'yellow' self.radius = 60; self.launched = false; self.vx = 0; self.vy = 0; self.gravity = 1.2; self.trailTimer = 0; self.trailInterval = 3; // frames self.trail = []; self.powerUsed = false; self.alive = true; // Attach asset based on type self.setType = function (type) { self.type = type; if (self.birdAsset) self.removeChild(self.birdAsset); var assetId = 'birdRed'; if (type === 'blue') assetId = 'birdBlue'; if (type === 'yellow') assetId = 'birdYellow'; self.birdAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.radius = self.birdAsset.width / 2; }; self.setType('red'); // Launch bird with velocity self.launch = function (vx, vy) { self.vx = vx; self.vy = vy; self.launched = true; self.trailTimer = 0; self.powerUsed = false; self.alive = true; }; // Bird special power (tap in air) self.usePower = function () { if (self.powerUsed || !self.launched) return; self.powerUsed = true; if (self.type === 'blue') { // Split into 3 birds game.spawnSplitBirds(self); } else if (self.type === 'yellow') { // Speed boost self.vx *= 1.7; self.vy *= 1.1; LK.effects.flashObject(self, 0xffff00, 300); } else if (self.type === 'red') { // Red: screen shake game.cameraShake(20, 300); } }; // Update per frame self.update = function () { if (!self.launched || !self.alive) return; self.vy += self.gravity; self.x += self.vx; self.y += self.vy; // --- Vomit dot trail effect --- if (!self.vomitTrail) self.vomitTrail = []; if (!self.lastVomitX) self.lastVomitX = self.x; if (!self.lastVomitY) self.lastVomitY = self.y; // Only spawn a vomit dot if the bird is moving fast enough and in the air if (self.launched && Math.abs(self.vx) + Math.abs(self.vy) > 6) { // Place a dot every 40px of movement var dx = self.x - self.lastVomitX; var dy = self.y - self.lastVomitY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 40) { var vomitDot = LK.getAsset('trailDot', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, alpha: 0.7, scaleX: 1.1, scaleY: 0.7, tint: 0xB8FF5A // light green/yellow for 'vomit' }); game.addChild(vomitDot); self.vomitTrail.push(vomitDot); tween(vomitDot, { alpha: 0, scaleX: 0.3, scaleY: 0.2 }, { duration: 900, easing: tween.linear, onFinish: function onFinish() { vomitDot.destroy(); } }); if (self.vomitTrail.length > 20) { var oldVomit = self.vomitTrail.shift(); if (oldVomit) oldVomit.destroy(); } self.lastVomitX = self.x; self.lastVomitY = self.y; } } // Trail effect self.trailTimer++; if (self.trailTimer >= self.trailInterval) { self.trailTimer = 0; var dot = LK.getAsset('trailDot', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, alpha: 0.5, scaleX: 0.7, scaleY: 0.7 }); game.addChild(dot); self.trail.push(dot); tween(dot, { alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 600, easing: tween.linear, onFinish: function onFinish() { dot.destroy(); } }); if (self.trail.length > 12) { var old = self.trail.shift(); if (old) old.destroy(); } } // Out of bounds if (self.x < -200 || self.x > 2248 || self.y > 3000) { self.alive = false; self.destroy(); } }; return self; }); // Block class var Block = Container.expand(function () { var self = Container.call(this); self.type = 'wood'; // 'wood', 'stone', 'glass' self.hp = 3; self.width = 200; self.height = 60; self.blockAsset = null; self.broken = false; self.setType = function (type) { self.type = type; if (self.blockAsset) self.removeChild(self.blockAsset); var assetId = 'blockWood'; if (type === 'stone') assetId = 'blockStone'; if (type === 'glass') assetId = 'blockGlass'; self.blockAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.width = self.blockAsset.width; self.height = self.blockAsset.height; if (type === 'glass') self.hp = 1;else if (type === 'wood') self.hp = 2;else if (type === 'stone') self.hp = 4; }; self.setType('wood'); self.hit = function (force) { self.hp -= force; LK.getSound('break').play(); LK.effects.flashObject(self, 0xffffff, 120); if (self.hp <= 0 && !self.broken) { self.broken = true; game.spawnDebris(self.x, self.y, self.type); self.destroy(); } }; return self; }); // Particle (for debris/explosion) var Particle = Container.expand(function () { var self = Container.call(this); self.vx = 0; self.vy = 0; self.life = 30; self.asset = null; self.init = function (type, color) { var assetId = 'debris'; if (type === 'explosion') assetId = 'explosion'; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5, tint: color }); }; self.update = function () { self.x += self.vx; self.y += self.vy; self.vy += 0.7; self.life--; self.asset.alpha = self.life / 30; if (self.life <= 0) { self.destroy(); } }; return self; }); // Pig class var Pig = Container.expand(function () { var self = Container.call(this); self.radius = 60; self.alive = true; self.pigAsset = self.attachAsset('pig', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 2; self.hit = function (force) { self.hp -= force; LK.getSound('pigOink').play(); LK.effects.flashObject(self, 0xffffff, 200); if (self.hp <= 0) { self.die(); } }; self.die = function () { self.alive = false; game.spawnExplosion(self.x, self.y, 0x7ed957); self.destroy(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // Sky blue }); /**** * Game Code ****/ // Camera shake variables // Bird types // Pig // Block types // Slingshot base // Trail particle // Debris particle // Explosion particle // Sound effects // Music var cameraShakeTime = 0; var cameraShakeStrength = 0; // Game state var birds = []; var pigs = []; var blocks = []; var particles = []; var currentBird = null; var slingshotBase = null; var slingshotPos = { x: 400, y: 2000 }; var slingshotRadius = 180; var dragStart = null; var dragging = false; var launchLine = null; var birdsQueue = []; var levelCleared = false; var score = 0; var scoreTxt = null; var shotsTxt = null; var shots = 0; var slowmo = false; var slowmoTimer = 0; // GUI scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); shotsTxt = new Text2('Shots: 0', { size: 70, fill: "#fff" }); shotsTxt.anchor.set(0.5, 0); LK.gui.topRight.addChild(shotsTxt); // Combo system variables var comboCount = 0; var comboTimer = 0; var comboTimerMax = 90; // 1.5 seconds at 60fps var comboTxt = new Text2('', { size: 110, fill: 0xFF4081, stroke: "#fff", strokeThickness: 8 }); comboTxt.anchor.set(0.5, 0); // Place combo text below the score, with good spacing for visibility comboTxt.x = 2048 / 2; comboTxt.y = scoreTxt.height + 60; LK.gui.top.addChild(comboTxt); // Level indicator var levelTxtGui = new Text2('Level 1', { size: 80, fill: 0xFFEB3B, stroke: "#333", strokeThickness: 8 }); levelTxtGui.anchor.set(0.5, 0); LK.gui.bottom.addChild(levelTxtGui); // Update level indicator on level start var oldSetupLevel = setupLevel; setupLevel = function setupLevel() { levelTxtGui.setText('Level ' + (currentLevel + 1)); oldSetupLevel(); }; // Add slingshot base slingshotBase = LK.getAsset('slingshotBase', { anchorX: 0.5, anchorY: 1, x: slingshotPos.x, y: slingshotPos.y + 100 }); game.addChild(slingshotBase); // Level definitions var levels = [{ birds: ['red', 'blue', 'yellow'], pigs: [{ x: 1500, y: 2100 }, { x: 1700, y: 1900 }], blocks: [{ type: 'wood', x: 1500, y: 2200 }, { type: 'stone', x: 1700, y: 2000 }, { type: 'glass', x: 1600, y: 2100 }] }, { birds: ['red', 'red', 'blue', 'yellow'], pigs: [{ x: 1550, y: 2100 }, { x: 1700, y: 1900 }, { x: 1800, y: 2200 }], blocks: [{ type: 'wood', x: 1500, y: 2200 }, { type: 'wood', x: 1500, y: 2140 }, { type: 'stone', x: 1700, y: 2000 }, { type: 'glass', x: 1600, y: 2100 }, { type: 'stone', x: 1800, y: 2200 }] }, { birds: ['yellow', 'yellow', 'blue', 'red'], pigs: [{ x: 1600, y: 2100 }, { x: 1750, y: 2000 }, { x: 1850, y: 2200 }, { x: 1700, y: 2300 }], blocks: [{ type: 'glass', x: 1600, y: 2100 }, { type: 'glass', x: 1600, y: 2160 }, { type: 'wood', x: 1750, y: 2000 }, { type: 'stone', x: 1850, y: 2200 }, { type: 'wood', x: 1700, y: 2300 }, { type: 'stone', x: 1700, y: 2240 }] }, { birds: ['blue', 'blue', 'yellow', 'red', 'red'], pigs: [{ x: 1500, y: 2100 }, { x: 1700, y: 1900 }, { x: 1800, y: 2200 }, { x: 1600, y: 2000 }, { x: 1750, y: 2200 }], blocks: [{ type: 'wood', x: 1500, y: 2200 }, { type: 'wood', x: 1500, y: 2140 }, { type: 'stone', x: 1700, y: 2000 }, { type: 'glass', x: 1600, y: 2100 }, { type: 'stone', x: 1800, y: 2200 }, { type: 'glass', x: 1600, y: 2160 }, { type: 'wood', x: 1750, y: 2200 }] }, // Level 5: Tall tower, more blocks, more pigs { birds: ['yellow', 'red', 'blue', 'yellow', 'red'], pigs: [{ x: 1700, y: 1800 }, { x: 1700, y: 2000 }, { x: 1700, y: 2200 }], blocks: [{ type: 'stone', x: 1700, y: 1850 }, { type: 'wood', x: 1700, y: 1950 }, { type: 'glass', x: 1700, y: 2050 }, { type: 'wood', x: 1700, y: 2150 }, { type: 'stone', x: 1700, y: 2250 }] }, // Level 6: Wide fortress, more fun { birds: ['blue', 'blue', 'yellow', 'red', 'yellow'], pigs: [{ x: 1500, y: 2100 }, { x: 1800, y: 2100 }, { x: 1650, y: 2000 }], blocks: [{ type: 'wood', x: 1500, y: 2200 }, { type: 'wood', x: 1800, y: 2200 }, { type: 'stone', x: 1650, y: 2100 }, { type: 'glass', x: 1575, y: 2150 }, { type: 'glass', x: 1725, y: 2150 }, { type: 'stone', x: 1650, y: 2000 }] }, // Level 7: Pyramid { birds: ['red', 'yellow', 'blue', 'red', 'yellow'], pigs: [{ x: 1650, y: 2200 }, { x: 1700, y: 2100 }, { x: 1750, y: 2200 }], blocks: [{ type: 'stone', x: 1700, y: 2250 }, { type: 'wood', x: 1650, y: 2250 }, { type: 'wood', x: 1750, y: 2250 }, { type: 'glass', x: 1700, y: 2200 }, { type: 'glass', x: 1675, y: 2225 }, { type: 'glass', x: 1725, y: 2225 }] }, // Level 8: Pig bunker { birds: ['yellow', 'yellow', 'blue', 'red', 'blue'], pigs: [{ x: 1600, y: 2100 }, { x: 1800, y: 2100 }], blocks: [{ type: 'stone', x: 1600, y: 2150 }, { type: 'stone', x: 1800, y: 2150 }, { type: 'wood', x: 1700, y: 2200 }, { type: 'glass', x: 1700, y: 2100 }, { type: 'wood', x: 1700, y: 2150 }] }, // Level 9: Chaos fun { birds: ['blue', 'yellow', 'red', 'yellow', 'blue', 'red'], pigs: [{ x: 1500, y: 2100 }, { x: 1700, y: 1900 }, { x: 1800, y: 2200 }, { x: 1600, y: 2000 }, { x: 1750, y: 2200 }], blocks: [{ type: 'wood', x: 1500, y: 2200 }, { type: 'wood', x: 1500, y: 2140 }, { type: 'stone', x: 1700, y: 2000 }, { type: 'glass', x: 1600, y: 2100 }, { type: 'stone', x: 1800, y: 2200 }, { type: 'glass', x: 1600, y: 2160 }, { type: 'wood', x: 1750, y: 2200 }, { type: 'glass', x: 1700, y: 2100 }] }, // Level 10: The Grand Finale { birds: ['red', 'yellow', 'blue', 'yellow', 'red', 'blue'], pigs: [{ x: 1600, y: 2100 }, { x: 1700, y: 2000 }, { x: 1800, y: 2100 }, { x: 1700, y: 2200 }, { x: 1750, y: 2300 }], blocks: [{ type: 'stone', x: 1700, y: 1950 }, { type: 'wood', x: 1600, y: 2150 }, { type: 'wood', x: 1800, y: 2150 }, { type: 'glass', x: 1700, y: 2100 }, { type: 'glass', x: 1650, y: 2200 }, { type: 'glass', x: 1750, y: 2200 }, { type: 'stone', x: 1700, y: 2250 }, { type: 'wood', x: 1700, y: 2300 }] }]; var currentLevel = 0; // Level setup function setupLevel() { // Clear arrays 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(); for (var i = 0; i < particles.length; i++) particles[i].destroy(); birds = []; pigs = []; blocks = []; particles = []; birdsQueue = []; levelCleared = false; score = 0; shots = 0; scoreTxt.setText('0'); shotsTxt.setText('Shots: 0'); slowmo = false; slowmoTimer = 0; comboCount = 0; comboTimer = 0; comboTxt.setText(''); // Clamp currentLevel to available levels if (currentLevel < 0) currentLevel = 0; if (currentLevel >= levels.length) currentLevel = levels.length - 1; var level = levels[currentLevel]; // Birds queue for (var i = 0; i < level.birds.length; i++) { birdsQueue.push(level.birds[i]); } // Spawn first bird spawnNextBird(); // Pigs for (var i = 0; i < level.pigs.length; i++) { var pig = new Pig(); pig.x = level.pigs[i].x; pig.y = level.pigs[i].y; game.addChild(pig); pigs.push(pig); } // Blocks for (var i = 0; i < level.blocks.length; i++) { var block = new Block(); block.setType(level.blocks[i].type); block.x = level.blocks[i].x; block.y = level.blocks[i].y; game.addChild(block); blocks.push(block); } } function spawnNextBird() { if (birdsQueue.length === 0) { // No more birds, check for loss LK.setTimeout(function () { if (!levelCleared) LK.showGameOver(); }, 1200); return; } var type = birdsQueue.shift(); var bird = new Bird(); bird.setType(type); bird.x = slingshotPos.x; bird.y = slingshotPos.y; game.addChild(bird); birds.push(bird); currentBird = bird; dragging = false; dragStart = null; } // Camera shake game.cameraShake = function (strength, duration) { cameraShakeStrength = strength; cameraShakeTime = duration; }; // Debris game.spawnDebris = function (x, y, type) { for (var i = 0; i < 8; i++) { var p = new Particle(); p.init('debris', type === 'wood' ? 0xc2b280 : type === 'stone' ? 0xaaaaaa : 0x99e6ff); p.x = x; p.y = y; var angle = Math.random() * Math.PI * 2; var speed = 8 + Math.random() * 8; p.vx = Math.cos(angle) * speed; p.vy = Math.sin(angle) * speed - 4; game.addChild(p); particles.push(p); } }; // Explosion game.spawnExplosion = function (x, y, color) { LK.getSound('explosionSfx').play(); for (var i = 0; i < 12; i++) { var p = new Particle(); p.init('explosion', color); p.x = x; p.y = y; var angle = Math.random() * Math.PI * 2; var speed = 10 + Math.random() * 10; p.vx = Math.cos(angle) * speed; p.vy = Math.sin(angle) * speed - 6; game.addChild(p); particles.push(p); } LK.effects.flashScreen(0xffff99, 200); game.cameraShake(30, 400); }; // Bird split (blue) game.spawnSplitBirds = function (parentBird) { for (var i = -1; i <= 1; i += 2) { var bird = new Bird(); bird.setType('blue'); bird.x = parentBird.x; bird.y = parentBird.y; bird.launched = true; bird.vx = parentBird.vx + i * 7; bird.vy = parentBird.vy - 2; bird.powerUsed = true; game.addChild(bird); birds.push(bird); } }; // SLOWMO function triggerSlowmo() { slowmo = true; slowmoTimer = 40; } // Touch controls game.down = function (x, y, obj) { if (levelCleared) return; if (!currentBird || currentBird.launched) return; // Only allow drag if touch is near bird var dx = x - currentBird.x, dy = y - currentBird.y; if (dx * dx + dy * dy < 180 * 180) { dragging = true; dragStart = { x: x, y: y }; } }; game.move = function (x, y, obj) { if (dragging && currentBird && !currentBird.launched) { // Limit drag distance var dx = x - slingshotPos.x, dy = y - slingshotPos.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > slingshotRadius) { dx *= slingshotRadius / dist; dy *= slingshotRadius / dist; } currentBird.x = slingshotPos.x + dx; currentBird.y = slingshotPos.y + dy; } }; game.up = function (x, y, obj) { if (dragging && currentBird && !currentBird.launched) { // Launch var dx = currentBird.x - slingshotPos.x, dy = currentBird.y - slingshotPos.y; currentBird.launch(-dx * 0.25, -dy * 0.25); LK.getSound('launch').play(); shots++; shotsTxt.setText('Shots: ' + shots); dragging = false; dragStart = null; } }; // Tap for bird power game.on('down', function (x, y, obj) { if (currentBird && currentBird.launched && !currentBird.powerUsed) { currentBird.usePower(); } }); // Main update game.update = function () { // Camera shake if (cameraShakeTime > 0) { cameraShakeTime -= 16; var shakeX = (Math.random() - 0.5) * cameraShakeStrength; var shakeY = (Math.random() - 0.5) * cameraShakeStrength; game.x = shakeX; game.y = shakeY; } else { game.x = 0; game.y = 0; } // SLOWMO var slowmoFactor = 1; if (slowmo) { slowmoFactor = 0.3; slowmoTimer--; if (slowmoTimer <= 0) slowmo = false; } // Update birds for (var i = birds.length - 1; i >= 0; i--) { var bird = birds[i]; if (bird.launched && bird.alive) { // Slowmo if (slowmo) { bird.x += bird.vx * slowmoFactor; bird.y += bird.vy * slowmoFactor; bird.vy += bird.gravity * slowmoFactor; } else { bird.update(); } // Collisions with blocks for (var j = blocks.length - 1; j >= 0; j--) { var block = blocks[j]; if (!block.broken && rectCircleCollide(block, bird)) { block.hit(1); LK.getSound('hit').play(); // Cartoonish bounce and squash effect tween(block, { scaleY: 0.7, scaleX: 1.2 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(block, { scaleY: 1, scaleX: 1 }, { duration: 120, easing: tween.easeOut }); } }); LK.effects.flashObject(block, 0xff0000, 100); // Exaggerated camera shake game.cameraShake(18, 320); // Add a burst of debris for extra cartoon effect for (var d = 0; d < 3; d++) { var p = new Particle(); p.init('debris', block.type === 'wood' ? 0xc2b280 : block.type === 'stone' ? 0xaaaaaa : 0x99e6ff); p.x = block.x + (Math.random() - 0.5) * block.width * 0.7; p.y = block.y + (Math.random() - 0.5) * block.height * 0.7; var angle = Math.random() * Math.PI * 2; var speed = 10 + Math.random() * 8; p.vx = Math.cos(angle) * speed; p.vy = Math.sin(angle) * speed - 4; game.addChild(p); particles.push(p); } triggerSlowmo(); bird.vx *= 0.6; bird.vy *= 0.6; } } // Collisions with pigs for (var j = pigs.length - 1; j >= 0; j--) { var pig = pigs[j]; if (pig.alive && circleCircleCollide(bird, pig)) { pig.hit(2); LK.getSound('hit').play(); // Pig bounce and color flash tween(pig, { scaleY: 0.6, scaleX: 1.3 }, { duration: 90, easing: tween.easeOut, onFinish: function onFinish() { tween(pig, { scaleY: 1, scaleX: 1 }, { duration: 140, easing: tween.easeOut }); } }); LK.effects.flashObject(pig, 0x00ff00, 180); // Big camera shake and a burst of confetti-like debris game.cameraShake(28, 400); for (var d = 0; d < 6; d++) { var p = new Particle(); p.init('debris', 0x7ed957); p.x = pig.x + (Math.random() - 0.5) * pig.radius * 1.2; p.y = pig.y + (Math.random() - 0.5) * pig.radius * 1.2; var angle = Math.random() * Math.PI * 2; var speed = 12 + Math.random() * 10; p.vx = Math.cos(angle) * speed; p.vy = Math.sin(angle) * speed - 6; game.addChild(p); particles.push(p); } triggerSlowmo(); bird.vx *= 0.7; bird.vy *= 0.7; score += 500; scoreTxt.setText(score); } } } // Remove dead birds if (!bird.alive) { birds.splice(i, 1); if (bird === currentBird) { LK.setTimeout(function () { spawnNextBird(); }, 700); } } } // Update pigs for (var i = pigs.length - 1; i >= 0; i--) { var pig = pigs[i]; if (!pig.alive) { pigs.splice(i, 1); score += 1000; scoreTxt.setText(score); // Combo system: pig destroyed triggers combo comboCount++; comboTimer = comboTimerMax; comboTxt.setText('Combo x' + comboCount + '!'); comboTxt.alpha = 1; tween(comboTxt, { scaleX: 1.25, scaleY: 1.25, alpha: 1 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.easeOut }); } }); } } // Update blocks for (var i = blocks.length - 1; i >= 0; i--) { var block = blocks[i]; if (block.broken) { blocks.splice(i, 1); score += 200; scoreTxt.setText(score); // Combo system: block destroyed triggers combo comboCount++; comboTimer = comboTimerMax; comboTxt.setText('Combo x' + comboCount + '!'); comboTxt.alpha = 1; tween(comboTxt, { scaleX: 1.18, scaleY: 1.18, alpha: 1 }, { duration: 90, easing: tween.easeOut, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 90, easing: tween.easeOut }); } }); } } // Update particles for (var i = particles.length - 1; i >= 0; i--) { var p = particles[i]; p.update(); if (p.life <= 0) { particles.splice(i, 1); } } // Combo timer logic if (comboCount > 0) { comboTimer--; if (comboTimer <= 0) { // Combo ended, award bonus if comboCount > 1 if (comboCount > 1) { var bonus = comboCount * 300; score += bonus; scoreTxt.setText(score); comboTxt.setText('Combo Bonus +' + bonus + '!'); comboTxt.alpha = 1; tween(comboTxt, { scaleX: 1.3, scaleY: 1.3, alpha: 1 }, { duration: 180, easing: tween.easeOut, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1, alpha: 0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { comboTxt.setText(''); } }); } }); LK.effects.flashScreen(0xFF4081, 300); game.cameraShake(18, 300); } else { comboTxt.setText(''); } comboCount = 0; comboTimer = 0; } } // Win condition if (!levelCleared && pigs.length === 0) { levelCleared = true; // Fun effects: screen flash, camera shake, confetti, sound, and more! LK.effects.flashScreen(0x00ff00, 800); LK.effects.flashScreen(0xff4081, 600); LK.effects.flashScreen(0xffff00, 400); game.cameraShake(60, 900); LK.getSound('explosionSfx').play(); LK.getSound('break').play(); LK.getSound('hit').play(); LK.getSound('pigOink').play(); // Massive confetti burst (lots of colored particles) for (var i = 0; i < 64; i++) { var confetti = new Particle(); confetti.init('debris', [0xFFEB3B, 0xFF4081, 0x7ed957, 0x00bcd4, 0xffffff][Math.floor(Math.random() * 5)]); confetti.x = 2048 / 2 + (Math.random() - 0.5) * 600; confetti.y = 2732 / 2 + (Math.random() - 0.5) * 400; var angle = Math.random() * Math.PI * 2; var speed = 24 + Math.random() * 18; confetti.vx = Math.cos(angle) * speed; confetti.vy = Math.sin(angle) * speed - 12; game.addChild(confetti); particles.push(confetti); } // Multiple explosions across the screen for (var e = 0; e < 8; e++) { var ex = 400 + Math.random() * 1200; var ey = 1200 + Math.random() * 1000; game.spawnExplosion(ex, ey, [0xFFEB3B, 0xFF4081, 0x7ed957, 0x00bcd4, 0xffffff][Math.floor(Math.random() * 5)]); } // Show fun level complete text var levelTxt = new Text2('Level ' + (currentLevel + 1) + ' Complete!', { size: 180, fill: 0xFFEB3B, stroke: "#333", strokeThickness: 10 }); levelTxt.anchor.set(0.5, 0.5); levelTxt.x = 2048 / 2; levelTxt.y = 2732 / 2; game.addChild(levelTxt); // Animate text: pop and fade out levelTxt.scale.set(0.7, 0.7); tween(levelTxt, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(levelTxt, { scaleX: 1, scaleY: 1, alpha: 0 }, { duration: 800, delay: 800, onFinish: function onFinish() { levelTxt.destroy(); } }); } }); // Level progression and end logic LK.setTimeout(function () { currentLevel++; if (currentLevel >= levels.length) { // After level 10, show you win LK.showYouWin(); } else { // For levels 1-9, show "Level X Complete!" and proceed to next level // (already handled by levelTxt and setupLevel) setupLevel(); } }, 1800); } }; // Helper: rectangle-circle collision function rectCircleCollide(rect, circ) { var rx = rect.x, ry = rect.y, rw = rect.width, rh = rect.height; var cx = circ.x, cy = circ.y, cr = circ.radius; var testX = cx, testY = cy; if (cx < rx - rw / 2) testX = rx - rw / 2;else if (cx > rx + rw / 2) testX = rx + rw / 2; if (cy < ry - rh / 2) testY = ry - rh / 2;else if (cy > ry + rh / 2) testY = ry + rh / 2; var distX = cx - testX; var distY = cy - testY; return distX * distX + distY * distY <= cr * cr; } // Helper: circle-circle collision function circleCircleCollide(a, b) { var dx = a.x - b.x, dy = a.y - b.y; var r = a.radius + b.radius; return dx * dx + dy * dy <= r * r; } // Start music LK.playMusic('bgmusic', { fade: { start: 0, end: 1, duration: 1000 } }); // Start level setupLevel();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bird class
var Bird = Container.expand(function () {
var self = Container.call(this);
self.type = 'red'; // 'red', 'blue', 'yellow'
self.radius = 60;
self.launched = false;
self.vx = 0;
self.vy = 0;
self.gravity = 1.2;
self.trailTimer = 0;
self.trailInterval = 3; // frames
self.trail = [];
self.powerUsed = false;
self.alive = true;
// Attach asset based on type
self.setType = function (type) {
self.type = type;
if (self.birdAsset) self.removeChild(self.birdAsset);
var assetId = 'birdRed';
if (type === 'blue') assetId = 'birdBlue';
if (type === 'yellow') assetId = 'birdYellow';
self.birdAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = self.birdAsset.width / 2;
};
self.setType('red');
// Launch bird with velocity
self.launch = function (vx, vy) {
self.vx = vx;
self.vy = vy;
self.launched = true;
self.trailTimer = 0;
self.powerUsed = false;
self.alive = true;
};
// Bird special power (tap in air)
self.usePower = function () {
if (self.powerUsed || !self.launched) return;
self.powerUsed = true;
if (self.type === 'blue') {
// Split into 3 birds
game.spawnSplitBirds(self);
} else if (self.type === 'yellow') {
// Speed boost
self.vx *= 1.7;
self.vy *= 1.1;
LK.effects.flashObject(self, 0xffff00, 300);
} else if (self.type === 'red') {
// Red: screen shake
game.cameraShake(20, 300);
}
};
// Update per frame
self.update = function () {
if (!self.launched || !self.alive) return;
self.vy += self.gravity;
self.x += self.vx;
self.y += self.vy;
// --- Vomit dot trail effect ---
if (!self.vomitTrail) self.vomitTrail = [];
if (!self.lastVomitX) self.lastVomitX = self.x;
if (!self.lastVomitY) self.lastVomitY = self.y;
// Only spawn a vomit dot if the bird is moving fast enough and in the air
if (self.launched && Math.abs(self.vx) + Math.abs(self.vy) > 6) {
// Place a dot every 40px of movement
var dx = self.x - self.lastVomitX;
var dy = self.y - self.lastVomitY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 40) {
var vomitDot = LK.getAsset('trailDot', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.7,
scaleX: 1.1,
scaleY: 0.7,
tint: 0xB8FF5A // light green/yellow for 'vomit'
});
game.addChild(vomitDot);
self.vomitTrail.push(vomitDot);
tween(vomitDot, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.2
}, {
duration: 900,
easing: tween.linear,
onFinish: function onFinish() {
vomitDot.destroy();
}
});
if (self.vomitTrail.length > 20) {
var oldVomit = self.vomitTrail.shift();
if (oldVomit) oldVomit.destroy();
}
self.lastVomitX = self.x;
self.lastVomitY = self.y;
}
}
// Trail effect
self.trailTimer++;
if (self.trailTimer >= self.trailInterval) {
self.trailTimer = 0;
var dot = LK.getAsset('trailDot', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
game.addChild(dot);
self.trail.push(dot);
tween(dot, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 600,
easing: tween.linear,
onFinish: function onFinish() {
dot.destroy();
}
});
if (self.trail.length > 12) {
var old = self.trail.shift();
if (old) old.destroy();
}
}
// Out of bounds
if (self.x < -200 || self.x > 2248 || self.y > 3000) {
self.alive = false;
self.destroy();
}
};
return self;
});
// Block class
var Block = Container.expand(function () {
var self = Container.call(this);
self.type = 'wood'; // 'wood', 'stone', 'glass'
self.hp = 3;
self.width = 200;
self.height = 60;
self.blockAsset = null;
self.broken = false;
self.setType = function (type) {
self.type = type;
if (self.blockAsset) self.removeChild(self.blockAsset);
var assetId = 'blockWood';
if (type === 'stone') assetId = 'blockStone';
if (type === 'glass') assetId = 'blockGlass';
self.blockAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.blockAsset.width;
self.height = self.blockAsset.height;
if (type === 'glass') self.hp = 1;else if (type === 'wood') self.hp = 2;else if (type === 'stone') self.hp = 4;
};
self.setType('wood');
self.hit = function (force) {
self.hp -= force;
LK.getSound('break').play();
LK.effects.flashObject(self, 0xffffff, 120);
if (self.hp <= 0 && !self.broken) {
self.broken = true;
game.spawnDebris(self.x, self.y, self.type);
self.destroy();
}
};
return self;
});
// Particle (for debris/explosion)
var Particle = Container.expand(function () {
var self = Container.call(this);
self.vx = 0;
self.vy = 0;
self.life = 30;
self.asset = null;
self.init = function (type, color) {
var assetId = 'debris';
if (type === 'explosion') assetId = 'explosion';
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
};
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.vy += 0.7;
self.life--;
self.asset.alpha = self.life / 30;
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
// Pig class
var Pig = Container.expand(function () {
var self = Container.call(this);
self.radius = 60;
self.alive = true;
self.pigAsset = self.attachAsset('pig', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 2;
self.hit = function (force) {
self.hp -= force;
LK.getSound('pigOink').play();
LK.effects.flashObject(self, 0xffffff, 200);
if (self.hp <= 0) {
self.die();
}
};
self.die = function () {
self.alive = false;
game.spawnExplosion(self.x, self.y, 0x7ed957);
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// Camera shake variables
// Bird types
// Pig
// Block types
// Slingshot base
// Trail particle
// Debris particle
// Explosion particle
// Sound effects
// Music
var cameraShakeTime = 0;
var cameraShakeStrength = 0;
// Game state
var birds = [];
var pigs = [];
var blocks = [];
var particles = [];
var currentBird = null;
var slingshotBase = null;
var slingshotPos = {
x: 400,
y: 2000
};
var slingshotRadius = 180;
var dragStart = null;
var dragging = false;
var launchLine = null;
var birdsQueue = [];
var levelCleared = false;
var score = 0;
var scoreTxt = null;
var shotsTxt = null;
var shots = 0;
var slowmo = false;
var slowmoTimer = 0;
// GUI
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
shotsTxt = new Text2('Shots: 0', {
size: 70,
fill: "#fff"
});
shotsTxt.anchor.set(0.5, 0);
LK.gui.topRight.addChild(shotsTxt);
// Combo system variables
var comboCount = 0;
var comboTimer = 0;
var comboTimerMax = 90; // 1.5 seconds at 60fps
var comboTxt = new Text2('', {
size: 110,
fill: 0xFF4081,
stroke: "#fff",
strokeThickness: 8
});
comboTxt.anchor.set(0.5, 0);
// Place combo text below the score, with good spacing for visibility
comboTxt.x = 2048 / 2;
comboTxt.y = scoreTxt.height + 60;
LK.gui.top.addChild(comboTxt);
// Level indicator
var levelTxtGui = new Text2('Level 1', {
size: 80,
fill: 0xFFEB3B,
stroke: "#333",
strokeThickness: 8
});
levelTxtGui.anchor.set(0.5, 0);
LK.gui.bottom.addChild(levelTxtGui);
// Update level indicator on level start
var oldSetupLevel = setupLevel;
setupLevel = function setupLevel() {
levelTxtGui.setText('Level ' + (currentLevel + 1));
oldSetupLevel();
};
// Add slingshot base
slingshotBase = LK.getAsset('slingshotBase', {
anchorX: 0.5,
anchorY: 1,
x: slingshotPos.x,
y: slingshotPos.y + 100
});
game.addChild(slingshotBase);
// Level definitions
var levels = [{
birds: ['red', 'blue', 'yellow'],
pigs: [{
x: 1500,
y: 2100
}, {
x: 1700,
y: 1900
}],
blocks: [{
type: 'wood',
x: 1500,
y: 2200
}, {
type: 'stone',
x: 1700,
y: 2000
}, {
type: 'glass',
x: 1600,
y: 2100
}]
}, {
birds: ['red', 'red', 'blue', 'yellow'],
pigs: [{
x: 1550,
y: 2100
}, {
x: 1700,
y: 1900
}, {
x: 1800,
y: 2200
}],
blocks: [{
type: 'wood',
x: 1500,
y: 2200
}, {
type: 'wood',
x: 1500,
y: 2140
}, {
type: 'stone',
x: 1700,
y: 2000
}, {
type: 'glass',
x: 1600,
y: 2100
}, {
type: 'stone',
x: 1800,
y: 2200
}]
}, {
birds: ['yellow', 'yellow', 'blue', 'red'],
pigs: [{
x: 1600,
y: 2100
}, {
x: 1750,
y: 2000
}, {
x: 1850,
y: 2200
}, {
x: 1700,
y: 2300
}],
blocks: [{
type: 'glass',
x: 1600,
y: 2100
}, {
type: 'glass',
x: 1600,
y: 2160
}, {
type: 'wood',
x: 1750,
y: 2000
}, {
type: 'stone',
x: 1850,
y: 2200
}, {
type: 'wood',
x: 1700,
y: 2300
}, {
type: 'stone',
x: 1700,
y: 2240
}]
}, {
birds: ['blue', 'blue', 'yellow', 'red', 'red'],
pigs: [{
x: 1500,
y: 2100
}, {
x: 1700,
y: 1900
}, {
x: 1800,
y: 2200
}, {
x: 1600,
y: 2000
}, {
x: 1750,
y: 2200
}],
blocks: [{
type: 'wood',
x: 1500,
y: 2200
}, {
type: 'wood',
x: 1500,
y: 2140
}, {
type: 'stone',
x: 1700,
y: 2000
}, {
type: 'glass',
x: 1600,
y: 2100
}, {
type: 'stone',
x: 1800,
y: 2200
}, {
type: 'glass',
x: 1600,
y: 2160
}, {
type: 'wood',
x: 1750,
y: 2200
}]
},
// Level 5: Tall tower, more blocks, more pigs
{
birds: ['yellow', 'red', 'blue', 'yellow', 'red'],
pigs: [{
x: 1700,
y: 1800
}, {
x: 1700,
y: 2000
}, {
x: 1700,
y: 2200
}],
blocks: [{
type: 'stone',
x: 1700,
y: 1850
}, {
type: 'wood',
x: 1700,
y: 1950
}, {
type: 'glass',
x: 1700,
y: 2050
}, {
type: 'wood',
x: 1700,
y: 2150
}, {
type: 'stone',
x: 1700,
y: 2250
}]
},
// Level 6: Wide fortress, more fun
{
birds: ['blue', 'blue', 'yellow', 'red', 'yellow'],
pigs: [{
x: 1500,
y: 2100
}, {
x: 1800,
y: 2100
}, {
x: 1650,
y: 2000
}],
blocks: [{
type: 'wood',
x: 1500,
y: 2200
}, {
type: 'wood',
x: 1800,
y: 2200
}, {
type: 'stone',
x: 1650,
y: 2100
}, {
type: 'glass',
x: 1575,
y: 2150
}, {
type: 'glass',
x: 1725,
y: 2150
}, {
type: 'stone',
x: 1650,
y: 2000
}]
},
// Level 7: Pyramid
{
birds: ['red', 'yellow', 'blue', 'red', 'yellow'],
pigs: [{
x: 1650,
y: 2200
}, {
x: 1700,
y: 2100
}, {
x: 1750,
y: 2200
}],
blocks: [{
type: 'stone',
x: 1700,
y: 2250
}, {
type: 'wood',
x: 1650,
y: 2250
}, {
type: 'wood',
x: 1750,
y: 2250
}, {
type: 'glass',
x: 1700,
y: 2200
}, {
type: 'glass',
x: 1675,
y: 2225
}, {
type: 'glass',
x: 1725,
y: 2225
}]
},
// Level 8: Pig bunker
{
birds: ['yellow', 'yellow', 'blue', 'red', 'blue'],
pigs: [{
x: 1600,
y: 2100
}, {
x: 1800,
y: 2100
}],
blocks: [{
type: 'stone',
x: 1600,
y: 2150
}, {
type: 'stone',
x: 1800,
y: 2150
}, {
type: 'wood',
x: 1700,
y: 2200
}, {
type: 'glass',
x: 1700,
y: 2100
}, {
type: 'wood',
x: 1700,
y: 2150
}]
},
// Level 9: Chaos fun
{
birds: ['blue', 'yellow', 'red', 'yellow', 'blue', 'red'],
pigs: [{
x: 1500,
y: 2100
}, {
x: 1700,
y: 1900
}, {
x: 1800,
y: 2200
}, {
x: 1600,
y: 2000
}, {
x: 1750,
y: 2200
}],
blocks: [{
type: 'wood',
x: 1500,
y: 2200
}, {
type: 'wood',
x: 1500,
y: 2140
}, {
type: 'stone',
x: 1700,
y: 2000
}, {
type: 'glass',
x: 1600,
y: 2100
}, {
type: 'stone',
x: 1800,
y: 2200
}, {
type: 'glass',
x: 1600,
y: 2160
}, {
type: 'wood',
x: 1750,
y: 2200
}, {
type: 'glass',
x: 1700,
y: 2100
}]
},
// Level 10: The Grand Finale
{
birds: ['red', 'yellow', 'blue', 'yellow', 'red', 'blue'],
pigs: [{
x: 1600,
y: 2100
}, {
x: 1700,
y: 2000
}, {
x: 1800,
y: 2100
}, {
x: 1700,
y: 2200
}, {
x: 1750,
y: 2300
}],
blocks: [{
type: 'stone',
x: 1700,
y: 1950
}, {
type: 'wood',
x: 1600,
y: 2150
}, {
type: 'wood',
x: 1800,
y: 2150
}, {
type: 'glass',
x: 1700,
y: 2100
}, {
type: 'glass',
x: 1650,
y: 2200
}, {
type: 'glass',
x: 1750,
y: 2200
}, {
type: 'stone',
x: 1700,
y: 2250
}, {
type: 'wood',
x: 1700,
y: 2300
}]
}];
var currentLevel = 0;
// Level setup
function setupLevel() {
// Clear arrays
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();
for (var i = 0; i < particles.length; i++) particles[i].destroy();
birds = [];
pigs = [];
blocks = [];
particles = [];
birdsQueue = [];
levelCleared = false;
score = 0;
shots = 0;
scoreTxt.setText('0');
shotsTxt.setText('Shots: 0');
slowmo = false;
slowmoTimer = 0;
comboCount = 0;
comboTimer = 0;
comboTxt.setText('');
// Clamp currentLevel to available levels
if (currentLevel < 0) currentLevel = 0;
if (currentLevel >= levels.length) currentLevel = levels.length - 1;
var level = levels[currentLevel];
// Birds queue
for (var i = 0; i < level.birds.length; i++) {
birdsQueue.push(level.birds[i]);
}
// Spawn first bird
spawnNextBird();
// Pigs
for (var i = 0; i < level.pigs.length; i++) {
var pig = new Pig();
pig.x = level.pigs[i].x;
pig.y = level.pigs[i].y;
game.addChild(pig);
pigs.push(pig);
}
// Blocks
for (var i = 0; i < level.blocks.length; i++) {
var block = new Block();
block.setType(level.blocks[i].type);
block.x = level.blocks[i].x;
block.y = level.blocks[i].y;
game.addChild(block);
blocks.push(block);
}
}
function spawnNextBird() {
if (birdsQueue.length === 0) {
// No more birds, check for loss
LK.setTimeout(function () {
if (!levelCleared) LK.showGameOver();
}, 1200);
return;
}
var type = birdsQueue.shift();
var bird = new Bird();
bird.setType(type);
bird.x = slingshotPos.x;
bird.y = slingshotPos.y;
game.addChild(bird);
birds.push(bird);
currentBird = bird;
dragging = false;
dragStart = null;
}
// Camera shake
game.cameraShake = function (strength, duration) {
cameraShakeStrength = strength;
cameraShakeTime = duration;
};
// Debris
game.spawnDebris = function (x, y, type) {
for (var i = 0; i < 8; i++) {
var p = new Particle();
p.init('debris', type === 'wood' ? 0xc2b280 : type === 'stone' ? 0xaaaaaa : 0x99e6ff);
p.x = x;
p.y = y;
var angle = Math.random() * Math.PI * 2;
var speed = 8 + Math.random() * 8;
p.vx = Math.cos(angle) * speed;
p.vy = Math.sin(angle) * speed - 4;
game.addChild(p);
particles.push(p);
}
};
// Explosion
game.spawnExplosion = function (x, y, color) {
LK.getSound('explosionSfx').play();
for (var i = 0; i < 12; i++) {
var p = new Particle();
p.init('explosion', color);
p.x = x;
p.y = y;
var angle = Math.random() * Math.PI * 2;
var speed = 10 + Math.random() * 10;
p.vx = Math.cos(angle) * speed;
p.vy = Math.sin(angle) * speed - 6;
game.addChild(p);
particles.push(p);
}
LK.effects.flashScreen(0xffff99, 200);
game.cameraShake(30, 400);
};
// Bird split (blue)
game.spawnSplitBirds = function (parentBird) {
for (var i = -1; i <= 1; i += 2) {
var bird = new Bird();
bird.setType('blue');
bird.x = parentBird.x;
bird.y = parentBird.y;
bird.launched = true;
bird.vx = parentBird.vx + i * 7;
bird.vy = parentBird.vy - 2;
bird.powerUsed = true;
game.addChild(bird);
birds.push(bird);
}
};
// SLOWMO
function triggerSlowmo() {
slowmo = true;
slowmoTimer = 40;
}
// Touch controls
game.down = function (x, y, obj) {
if (levelCleared) return;
if (!currentBird || currentBird.launched) return;
// Only allow drag if touch is near bird
var dx = x - currentBird.x,
dy = y - currentBird.y;
if (dx * dx + dy * dy < 180 * 180) {
dragging = true;
dragStart = {
x: x,
y: y
};
}
};
game.move = function (x, y, obj) {
if (dragging && currentBird && !currentBird.launched) {
// Limit drag distance
var dx = x - slingshotPos.x,
dy = y - slingshotPos.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > slingshotRadius) {
dx *= slingshotRadius / dist;
dy *= slingshotRadius / dist;
}
currentBird.x = slingshotPos.x + dx;
currentBird.y = slingshotPos.y + dy;
}
};
game.up = function (x, y, obj) {
if (dragging && currentBird && !currentBird.launched) {
// Launch
var dx = currentBird.x - slingshotPos.x,
dy = currentBird.y - slingshotPos.y;
currentBird.launch(-dx * 0.25, -dy * 0.25);
LK.getSound('launch').play();
shots++;
shotsTxt.setText('Shots: ' + shots);
dragging = false;
dragStart = null;
}
};
// Tap for bird power
game.on('down', function (x, y, obj) {
if (currentBird && currentBird.launched && !currentBird.powerUsed) {
currentBird.usePower();
}
});
// Main update
game.update = function () {
// Camera shake
if (cameraShakeTime > 0) {
cameraShakeTime -= 16;
var shakeX = (Math.random() - 0.5) * cameraShakeStrength;
var shakeY = (Math.random() - 0.5) * cameraShakeStrength;
game.x = shakeX;
game.y = shakeY;
} else {
game.x = 0;
game.y = 0;
}
// SLOWMO
var slowmoFactor = 1;
if (slowmo) {
slowmoFactor = 0.3;
slowmoTimer--;
if (slowmoTimer <= 0) slowmo = false;
}
// Update birds
for (var i = birds.length - 1; i >= 0; i--) {
var bird = birds[i];
if (bird.launched && bird.alive) {
// Slowmo
if (slowmo) {
bird.x += bird.vx * slowmoFactor;
bird.y += bird.vy * slowmoFactor;
bird.vy += bird.gravity * slowmoFactor;
} else {
bird.update();
}
// Collisions with blocks
for (var j = blocks.length - 1; j >= 0; j--) {
var block = blocks[j];
if (!block.broken && rectCircleCollide(block, bird)) {
block.hit(1);
LK.getSound('hit').play();
// Cartoonish bounce and squash effect
tween(block, {
scaleY: 0.7,
scaleX: 1.2
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(block, {
scaleY: 1,
scaleX: 1
}, {
duration: 120,
easing: tween.easeOut
});
}
});
LK.effects.flashObject(block, 0xff0000, 100);
// Exaggerated camera shake
game.cameraShake(18, 320);
// Add a burst of debris for extra cartoon effect
for (var d = 0; d < 3; d++) {
var p = new Particle();
p.init('debris', block.type === 'wood' ? 0xc2b280 : block.type === 'stone' ? 0xaaaaaa : 0x99e6ff);
p.x = block.x + (Math.random() - 0.5) * block.width * 0.7;
p.y = block.y + (Math.random() - 0.5) * block.height * 0.7;
var angle = Math.random() * Math.PI * 2;
var speed = 10 + Math.random() * 8;
p.vx = Math.cos(angle) * speed;
p.vy = Math.sin(angle) * speed - 4;
game.addChild(p);
particles.push(p);
}
triggerSlowmo();
bird.vx *= 0.6;
bird.vy *= 0.6;
}
}
// Collisions with pigs
for (var j = pigs.length - 1; j >= 0; j--) {
var pig = pigs[j];
if (pig.alive && circleCircleCollide(bird, pig)) {
pig.hit(2);
LK.getSound('hit').play();
// Pig bounce and color flash
tween(pig, {
scaleY: 0.6,
scaleX: 1.3
}, {
duration: 90,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(pig, {
scaleY: 1,
scaleX: 1
}, {
duration: 140,
easing: tween.easeOut
});
}
});
LK.effects.flashObject(pig, 0x00ff00, 180);
// Big camera shake and a burst of confetti-like debris
game.cameraShake(28, 400);
for (var d = 0; d < 6; d++) {
var p = new Particle();
p.init('debris', 0x7ed957);
p.x = pig.x + (Math.random() - 0.5) * pig.radius * 1.2;
p.y = pig.y + (Math.random() - 0.5) * pig.radius * 1.2;
var angle = Math.random() * Math.PI * 2;
var speed = 12 + Math.random() * 10;
p.vx = Math.cos(angle) * speed;
p.vy = Math.sin(angle) * speed - 6;
game.addChild(p);
particles.push(p);
}
triggerSlowmo();
bird.vx *= 0.7;
bird.vy *= 0.7;
score += 500;
scoreTxt.setText(score);
}
}
}
// Remove dead birds
if (!bird.alive) {
birds.splice(i, 1);
if (bird === currentBird) {
LK.setTimeout(function () {
spawnNextBird();
}, 700);
}
}
}
// Update pigs
for (var i = pigs.length - 1; i >= 0; i--) {
var pig = pigs[i];
if (!pig.alive) {
pigs.splice(i, 1);
score += 1000;
scoreTxt.setText(score);
// Combo system: pig destroyed triggers combo
comboCount++;
comboTimer = comboTimerMax;
comboTxt.setText('Combo x' + comboCount + '!');
comboTxt.alpha = 1;
tween(comboTxt, {
scaleX: 1.25,
scaleY: 1.25,
alpha: 1
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.easeOut
});
}
});
}
}
// Update blocks
for (var i = blocks.length - 1; i >= 0; i--) {
var block = blocks[i];
if (block.broken) {
blocks.splice(i, 1);
score += 200;
scoreTxt.setText(score);
// Combo system: block destroyed triggers combo
comboCount++;
comboTimer = comboTimerMax;
comboTxt.setText('Combo x' + comboCount + '!');
comboTxt.alpha = 1;
tween(comboTxt, {
scaleX: 1.18,
scaleY: 1.18,
alpha: 1
}, {
duration: 90,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 90,
easing: tween.easeOut
});
}
});
}
}
// Update particles
for (var i = particles.length - 1; i >= 0; i--) {
var p = particles[i];
p.update();
if (p.life <= 0) {
particles.splice(i, 1);
}
}
// Combo timer logic
if (comboCount > 0) {
comboTimer--;
if (comboTimer <= 0) {
// Combo ended, award bonus if comboCount > 1
if (comboCount > 1) {
var bonus = comboCount * 300;
score += bonus;
scoreTxt.setText(score);
comboTxt.setText('Combo Bonus +' + bonus + '!');
comboTxt.alpha = 1;
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 1
}, {
duration: 180,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
comboTxt.setText('');
}
});
}
});
LK.effects.flashScreen(0xFF4081, 300);
game.cameraShake(18, 300);
} else {
comboTxt.setText('');
}
comboCount = 0;
comboTimer = 0;
}
}
// Win condition
if (!levelCleared && pigs.length === 0) {
levelCleared = true;
// Fun effects: screen flash, camera shake, confetti, sound, and more!
LK.effects.flashScreen(0x00ff00, 800);
LK.effects.flashScreen(0xff4081, 600);
LK.effects.flashScreen(0xffff00, 400);
game.cameraShake(60, 900);
LK.getSound('explosionSfx').play();
LK.getSound('break').play();
LK.getSound('hit').play();
LK.getSound('pigOink').play();
// Massive confetti burst (lots of colored particles)
for (var i = 0; i < 64; i++) {
var confetti = new Particle();
confetti.init('debris', [0xFFEB3B, 0xFF4081, 0x7ed957, 0x00bcd4, 0xffffff][Math.floor(Math.random() * 5)]);
confetti.x = 2048 / 2 + (Math.random() - 0.5) * 600;
confetti.y = 2732 / 2 + (Math.random() - 0.5) * 400;
var angle = Math.random() * Math.PI * 2;
var speed = 24 + Math.random() * 18;
confetti.vx = Math.cos(angle) * speed;
confetti.vy = Math.sin(angle) * speed - 12;
game.addChild(confetti);
particles.push(confetti);
}
// Multiple explosions across the screen
for (var e = 0; e < 8; e++) {
var ex = 400 + Math.random() * 1200;
var ey = 1200 + Math.random() * 1000;
game.spawnExplosion(ex, ey, [0xFFEB3B, 0xFF4081, 0x7ed957, 0x00bcd4, 0xffffff][Math.floor(Math.random() * 5)]);
}
// Show fun level complete text
var levelTxt = new Text2('Level ' + (currentLevel + 1) + ' Complete!', {
size: 180,
fill: 0xFFEB3B,
stroke: "#333",
strokeThickness: 10
});
levelTxt.anchor.set(0.5, 0.5);
levelTxt.x = 2048 / 2;
levelTxt.y = 2732 / 2;
game.addChild(levelTxt);
// Animate text: pop and fade out
levelTxt.scale.set(0.7, 0.7);
tween(levelTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(levelTxt, {
scaleX: 1,
scaleY: 1,
alpha: 0
}, {
duration: 800,
delay: 800,
onFinish: function onFinish() {
levelTxt.destroy();
}
});
}
});
// Level progression and end logic
LK.setTimeout(function () {
currentLevel++;
if (currentLevel >= levels.length) {
// After level 10, show you win
LK.showYouWin();
} else {
// For levels 1-9, show "Level X Complete!" and proceed to next level
// (already handled by levelTxt and setupLevel)
setupLevel();
}
}, 1800);
}
};
// Helper: rectangle-circle collision
function rectCircleCollide(rect, circ) {
var rx = rect.x,
ry = rect.y,
rw = rect.width,
rh = rect.height;
var cx = circ.x,
cy = circ.y,
cr = circ.radius;
var testX = cx,
testY = cy;
if (cx < rx - rw / 2) testX = rx - rw / 2;else if (cx > rx + rw / 2) testX = rx + rw / 2;
if (cy < ry - rh / 2) testY = ry - rh / 2;else if (cy > ry + rh / 2) testY = ry + rh / 2;
var distX = cx - testX;
var distY = cy - testY;
return distX * distX + distY * distY <= cr * cr;
}
// Helper: circle-circle collision
function circleCircleCollide(a, b) {
var dx = a.x - b.x,
dy = a.y - b.y;
var r = a.radius + b.radius;
return dx * dx + dy * dy <= r * r;
}
// Start music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
// Start level
setupLevel();
Angry Birds red little bird Red. In-Game asset. 2d. High contrast. No shadows
Angry Birds blue little bird. In-Game asset. 2d. High contrast. No shadows
There is a yellow bird named Angry Birds Chuck, do that. In-Game asset. 2d. High contrast. No shadows
flat glass. In-Game asset. 2d. High contrast. No shadows
BloockWood. In-Game asset. 2d. High contrast. No shadows
Pig Angry Bids. In-Game asset. 2d. High contrast. No shadows