/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var AutoCannon = Container.expand(function () { var self = Container.call(this); var cannonGraphics = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 1.0, scaleX: 0.8, scaleY: 0.8 }); cannonGraphics.tint = 0xffd700; // Golden tint self.moveSpeed = 8; self.targetX = self.x; self.isMoving = false; self.lastShotTime = 0; self.shootInterval = 1500; // Shoot every 1.5 seconds self.update = function () { // Find nearest target (prioritize red sunrays) var nearestTarget = null; var nearestDistance = Infinity; // Check red sunrays first (priority) for (var i = 0; i < redSunrays.length; i++) { var redSunray = redSunrays[i]; var distance = Math.abs(redSunray.x - self.x); if (distance < nearestDistance) { nearestDistance = distance; nearestTarget = redSunray; } } // If no red sunrays, check regular sunrays if (!nearestTarget) { for (var j = 0; j < sunrays.length; j++) { var sunray = sunrays[j]; var distance = Math.abs(sunray.x - self.x); if (distance < nearestDistance) { nearestDistance = distance; nearestTarget = sunray; } } } // Move toward target if (nearestTarget) { self.targetX = nearestTarget.x; self.isMoving = true; } // Handle movement if (self.isMoving) { var diff = self.targetX - self.x; if (Math.abs(diff) > 4) { self.x += diff > 0 ? self.moveSpeed : -self.moveSpeed; } else { self.x = self.targetX; self.isMoving = false; } } // Keep cannon within screen bounds if (self.x < 150) self.x = 150; if (self.x > 1898) self.x = 1898; // Auto-shoot var currentTime = LK.ticks * 16.67; if (currentTime - self.lastShotTime >= self.shootInterval && nearestTarget) { var newSnowflake = new Snowflake(); newSnowflake.x = self.x; newSnowflake.y = self.y - 120; newSnowflake.lastY = newSnowflake.y; snowflakes.push(newSnowflake); game.addChild(newSnowflake); self.lastShotTime = currentTime; LK.getSound('shoot').play(); } }; return self; }); var Cannon = Container.expand(function () { var self = Container.call(this); var cannonGraphics = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 1.0 }); // Shield effect var shieldGraphics = self.attachAsset('snowflake', { anchorX: 0.5, anchorY: 0.5, scaleX: 6, scaleY: 6, alpha: 0, y: -80 }); shieldGraphics.tint = 0x00ffff; self.moveSpeed = 12; self.isMoving = false; self.targetX = self.x; self.hasShield = false; self.shieldTime = 0; self.rapidFireActive = false; self.rapidFireTime = 0; self.multishotActive = false; self.multishotTime = 0; self.shieldBobTimer = 0; self.update = function () { if (self.isMoving) { var diff = self.targetX - self.x; if (Math.abs(diff) > 2) { self.x += diff > 0 ? self.moveSpeed : -self.moveSpeed; } else { self.x = self.targetX; self.isMoving = false; } } // Keep cannon within screen bounds if (self.x < 150) self.x = 150; if (self.x > 1898) self.x = 1898; // Update shield if (self.hasShield) { self.shieldTime--; self.shieldBobTimer += 0.1; shieldGraphics.alpha = 0.6 + Math.sin(self.shieldBobTimer) * 0.2; shieldGraphics.rotation += 0.05; if (self.shieldTime <= 0) { self.hasShield = false; shieldGraphics.alpha = 0; } } // Update rapid fire if (self.rapidFireActive) { self.rapidFireTime--; cannonGraphics.tint = 0xff6600; if (self.rapidFireTime <= 0) { self.rapidFireActive = false; cannonGraphics.tint = 0xffffff; } } // Update multishot if (self.multishotActive) { self.multishotTime--; if (self.multishotTime <= 0) { self.multishotActive = false; } } }; self.moveTo = function (targetX) { self.targetX = targetX; self.isMoving = true; }; self.activateShield = function () { self.hasShield = true; self.shieldTime = 600; // 10 seconds at 60fps }; self.activateRapidFire = function () { self.rapidFireActive = true; self.rapidFireTime = 600; // 10 seconds at 60fps }; self.activateMultishot = function () { self.multishotActive = true; self.multishotTime = 300; // 5 seconds at 60fps }; return self; }); var CannonPowerUp = Container.expand(function () { var self = Container.call(this); var cannonGraphics = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); cannonGraphics.tint = 0xffd700; // Golden tint self.speed = 2; self.bobTimer = 0; self.update = function () { self.y += self.speed; self.bobTimer += 0.1; cannonGraphics.y = Math.sin(self.bobTimer) * 10; cannonGraphics.rotation += 0.05; }; return self; }); var GreenSnowflakePowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('snowflake', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); powerUpGraphics.tint = 0x00ff00; // Green tint self.speed = 2; self.bobTimer = 0; self.update = function () { self.y += self.speed; self.bobTimer += 0.1; powerUpGraphics.y = Math.sin(self.bobTimer) * 10; powerUpGraphics.rotation += 0.05; }; return self; }); var IceCubePowerUp = Container.expand(function () { var self = Container.call(this); var iceCubeGraphics = self.attachAsset('iceblocksad', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); iceCubeGraphics.tint = 0x87CEEB; // Light blue tint self.speed = 2; self.bobTimer = 0; self.update = function () { self.y += self.speed; self.bobTimer += 0.1; iceCubeGraphics.y = Math.sin(self.bobTimer) * 15; iceCubeGraphics.rotation += 0.03; }; return self; }); var ParticleEffect = Container.expand(function () { var self = Container.call(this); var particles = []; self.createExplosion = function (x, y, color, count) { for (var i = 0; i < count; i++) { var particle = self.attachAsset('snowflake', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, x: x, y: y }); particle.tint = color; var angle = Math.PI * 2 * i / count; var speed = 100 + Math.random() * 100; particle.vx = Math.cos(angle) * speed; particle.vy = Math.sin(angle) * speed; particle.life = 60; // frames particles.push(particle); } }; self.update = function () { for (var i = particles.length - 1; i >= 0; i--) { var particle = particles[i]; particle.x += particle.vx * 0.016; particle.y += particle.vy * 0.016; particle.vy += 200 * 0.016; // gravity particle.life--; particle.alpha = particle.life / 60; if (particle.life <= 0) { particle.destroy(); particles.splice(i, 1); } } }; return self; }); var PolarBearDisplay = Container.expand(function () { var self = Container.call(this); var iceBlock = self.attachAsset('iceblocksad', { anchorX: 0.5, anchorY: 0.5 }); var bearSad = self.attachAsset('polarbearsad', { anchorX: 0.5, anchorY: 0.5, y: 10 }); var bearHappy = self.attachAsset('polarbearhappy', { anchorX: 0.5, anchorY: 0.5, y: 10, alpha: 0 }); self.showHappy = function () { // Generate ice particles when ice cube is destroyed particleSystem.createExplosion(self.x, self.y - 20, 0xb0e0e6, 15); tween(iceBlock, { alpha: 0 }, { duration: 1000 }); tween(bearSad, { alpha: 0 }, { duration: 1000 }); tween(bearHappy, { alpha: 1 }, { duration: 1000 }); }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.type = 'shield'; // 'shield', 'rapidfire', or 'multishot' var powerUpGraphics = self.attachAsset('snowflake', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); if (self.type === 'rapidfire') { powerUpGraphics.tint = 0xff6600; } else if (self.type === 'multishot') { powerUpGraphics.tint = 0xff00ff; } else { powerUpGraphics.tint = 0x00ffff; } self.speed = 2; self.bobTimer = 0; self.update = function () { self.y += self.speed; self.bobTimer += 0.1; powerUpGraphics.y = Math.sin(self.bobTimer) * 10; powerUpGraphics.rotation += 0.05; }; return self; }); var RedSunRay = Container.expand(function () { var self = Container.call(this); var sunrayGraphics = self.attachAsset('sunray', { anchorX: 0.5, anchorY: 0.5 }); sunrayGraphics.tint = 0xff0000; // Make it red self.speed = 2; self.hits = 0; self.maxHits = 2; self.flashTimer = 0; self.update = function () { self.y += self.speed; // Flash effect when hit if (self.flashTimer > 0) { self.flashTimer--; var alpha = 0.3 + Math.sin(self.flashTimer * 0.5) * 0.3; sunrayGraphics.alpha = alpha; if (self.flashTimer <= 0) { sunrayGraphics.alpha = 1; } } }; self.hit = function () { self.hits++; self.flashTimer = 30; // Flash for 0.5 seconds // Scale down slightly when hit var newScale = 1 - self.hits / self.maxHits * 0.3; sunrayGraphics.scaleX = newScale; sunrayGraphics.scaleY = newScale; return self.hits >= self.maxHits; }; return self; }); var Snowflake = Container.expand(function () { var self = Container.call(this); var snowflakeGraphics = self.attachAsset('snowflake', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -12; self.update = function () { self.y += self.speed; }; return self; }); var SunRay = Container.expand(function () { var self = Container.call(this); var sunrayGraphics = self.attachAsset('sunray', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Add frozen tundra background var backgroundTundra = game.attachAsset('frozentundra', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); var cannon; var snowflakes = []; var sunrays = []; var redSunrays = []; var powerUps = []; var cannonPowerUps = []; var autoCannons = []; var polarBearDisplay; var particleSystem; var lastShotTime = 0; var lastSunRaySpawn = 0; var lastPowerUpSpawn = 0; var sunRaySpawnInterval = 3000; // 3 seconds initially var powerUpSpawnInterval = 15000; // 15 seconds var raysDestroyed = 0; var raysNeededForLevel = 10; var currentLevel = 1; var gameWon = false; var totalScore = 0; var cannonPowerUpTriggered = false; // Track if 200-point cannon power-up was spawned var tank500PowerUpTriggered = false; // Track if 500-point tank power-up was spawned var tank2000PowerUpTriggered = false; // Track if 2000-point tank power-up was spawned var combo = 0; var comboTimer = 0; var redSunraySpawnChance = 0.2; // Default 20% chance var redSunrayChanceReduced = false; var redSunrayChanceTimer = 0; var playerLives = 3; var maxLives = 3; var iceCubePowerUps = []; var greenSnowflakePowerUps = []; var greenTransformActive = false; var greenTransformTimer = 0; var originalSunRaySpeeds = []; // Create score display var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Create combo display var comboText = new Text2('', { size: 40, fill: 0xFFD700 }); comboText.anchor.set(0.5, 0); comboText.y = 80; LK.gui.top.addChild(comboText); // Create level display var levelText = new Text2('Level: 1', { size: 50, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); levelText.x = 150; levelText.y = 20; LK.gui.topRight.addChild(levelText); // Create power-up status var powerUpText = new Text2('', { size: 35, fill: 0x00FFFF }); powerUpText.anchor.set(0, 0); powerUpText.x = 150; powerUpText.y = 80; LK.gui.topRight.addChild(powerUpText); // Create lives display var livesContainer = new Container(); var livesDisplay = []; for (var l = 0; l < maxLives; l++) { var lifeIcon = LK.getAsset('iceblocksad', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, x: l * 80, y: 0 }); livesDisplay.push(lifeIcon); livesContainer.addChild(lifeIcon); } livesContainer.x = 100; livesContainer.y = 100; LK.gui.topLeft.addChild(livesContainer); // Function to update lives display function updateLivesDisplay() { for (var i = 0; i < livesDisplay.length; i++) { if (i < playerLives) { livesDisplay[i].alpha = 1; } else { livesDisplay[i].alpha = 0.3; } } } // Initialize lives display updateLivesDisplay(); // Start playing background music LK.playMusic('FrozenSavior'); // Create cannon cannon = game.addChild(new Cannon()); cannon.x = 1024; cannon.y = 2680; // Create particle system particleSystem = game.addChild(new ParticleEffect()); // Create polar bear display polarBearDisplay = game.addChild(new PolarBearDisplay()); polarBearDisplay.x = 1024; polarBearDisplay.y = 200; // Touch controls game.down = function (x, y, obj) { cannon.moveTo(x); }; game.move = function (x, y, obj) { cannon.moveTo(x); }; // Main game update loop game.update = function () { var currentTime = LK.ticks * 16.67; // Convert to milliseconds // Update combo timer if (comboTimer > 0) { comboTimer--; if (comboTimer <= 0) { combo = 0; comboText.setText(''); } } // Update red sunray chance reduction timer if (redSunrayChanceReduced) { redSunrayChanceTimer--; if (redSunrayChanceTimer <= 0) { redSunrayChanceReduced = false; redSunraySpawnChance = 0.2; // Reset to 20% } } // Update green transform timer if (greenTransformActive) { greenTransformTimer--; if (greenTransformTimer <= 0) { // Restore original sun ray behavior greenTransformActive = false; for (var gsr = 0; gsr < sunrays.length; gsr++) { var sunray = sunrays[gsr]; if (sunray.speed === 0) { sunray.speed = 4; // Restore original speed tween(sunray, { tint: 0xffffff }, { duration: 500 }); } } for (var grsr = 0; grsr < redSunrays.length; grsr++) { var redSunray = redSunrays[grsr]; if (redSunray.speed === 0) { redSunray.speed = 2; // Restore original speed tween(redSunray, { tint: 0xff0000 }, { duration: 500 }); } } } } // Auto-shoot snowflakes (faster with rapid fire and score-based speed boosts) var baseShootInterval = 2000; // Default 2 seconds if (totalScore >= 3000) { baseShootInterval = 800; // Very fast at 3000+ points } else if (totalScore >= 1000) { baseShootInterval = 1200; // Faster at 1000+ points } var shootInterval = cannon.rapidFireActive ? 500 : baseShootInterval; if (currentTime - lastShotTime >= shootInterval) { var snowflakeCount = cannon.multishotActive ? 10 : 1; for (var shot = 0; shot < snowflakeCount; shot++) { var newSnowflake = new Snowflake(); if (snowflakeCount === 1) { newSnowflake.x = cannon.x; } else { // Spread snowflakes in an arc var spreadAngle = (shot - (snowflakeCount - 1) / 2) * 0.3; newSnowflake.x = cannon.x + Math.sin(spreadAngle) * 50; } newSnowflake.y = cannon.y - 120; newSnowflake.lastY = newSnowflake.y; snowflakes.push(newSnowflake); game.addChild(newSnowflake); } lastShotTime = currentTime; LK.getSound('shoot').play(); } // Spawn sun rays if (currentTime - lastSunRaySpawn >= sunRaySpawnInterval) { // Dynamic chance to spawn red sunray if (Math.random() < redSunraySpawnChance) { var newRedSunRay = new RedSunRay(); newRedSunRay.x = Math.random() * (2048 - 120) + 60; newRedSunRay.y = -30; newRedSunRay.lastY = newRedSunRay.y; redSunrays.push(newRedSunRay); game.addChild(newRedSunRay); } else { var newSunRay = new SunRay(); newSunRay.x = Math.random() * (2048 - 120) + 60; newSunRay.y = -30; newSunRay.lastY = newSunRay.y; sunrays.push(newSunRay); game.addChild(newSunRay); } lastSunRaySpawn = currentTime; // Randomly vary spawn interval sunRaySpawnInterval = Math.max(800, 2000 + Math.random() * 2000 - currentLevel * 100); } // Spawn special cannon power-up at 200 points if (totalScore >= 200 && !cannonPowerUpTriggered) { var specialCannonPowerUp = new CannonPowerUp(); specialCannonPowerUp.x = Math.random() * (2048 - 200) + 100; specialCannonPowerUp.y = -30; cannonPowerUps.push(specialCannonPowerUp); game.addChild(specialCannonPowerUp); cannonPowerUpTriggered = true; } // Spawn tank power-up at 500 points if (totalScore >= 500 && !tank500PowerUpTriggered) { var tank500PowerUp = new CannonPowerUp(); tank500PowerUp.x = Math.random() * (2048 - 200) + 100; tank500PowerUp.y = -30; cannonPowerUps.push(tank500PowerUp); game.addChild(tank500PowerUp); tank500PowerUpTriggered = true; } // Spawn tank power-up at 2000 points if (totalScore >= 2000 && !tank2000PowerUpTriggered) { var tank2000PowerUp = new CannonPowerUp(); tank2000PowerUp.x = Math.random() * (2048 - 200) + 100; tank2000PowerUp.y = -30; cannonPowerUps.push(tank2000PowerUp); game.addChild(tank2000PowerUp); tank2000PowerUpTriggered = true; } // Spawn power-ups if (currentTime - lastPowerUpSpawn >= powerUpSpawnInterval) { // Regular power-ups only var newPowerUp = new PowerUp(); var regularType = Math.random(); if (regularType < 0.33) { newPowerUp.type = 'shield'; } else if (regularType < 0.66) { newPowerUp.type = 'rapidfire'; } else { newPowerUp.type = 'multishot'; } newPowerUp.x = Math.random() * (2048 - 200) + 100; newPowerUp.y = -30; powerUps.push(newPowerUp); game.addChild(newPowerUp); lastPowerUpSpawn = currentTime; powerUpSpawnInterval = 12000 + Math.random() * 8000; } // Spawn ice cube power-up only if missing lives if (playerLives < maxLives && Math.random() < 0.002) { // Low spawn chance var newIceCube = new IceCubePowerUp(); newIceCube.x = Math.random() * (2048 - 200) + 100; newIceCube.y = -30; iceCubePowerUps.push(newIceCube); game.addChild(newIceCube); } // Spawn green snowflake power-up if (Math.random() < 0.0003) { // Very low spawn chance - rarest power-up var newGreenSnowflake = new GreenSnowflakePowerUp(); newGreenSnowflake.x = Math.random() * (2048 - 200) + 100; newGreenSnowflake.y = -30; greenSnowflakePowerUps.push(newGreenSnowflake); game.addChild(newGreenSnowflake); } // Update power-up status display var statusText = ''; if (cannon.hasShield) { statusText += 'SHIELD: ' + Math.ceil(cannon.shieldTime / 60) + 's '; } if (cannon.rapidFireActive) { statusText += 'RAPID FIRE: ' + Math.ceil(cannon.rapidFireTime / 60) + 's'; } if (cannon.multishotActive) { statusText += 'MULTISHOT: ' + Math.ceil(cannon.multishotTime / 60) + 's'; } powerUpText.setText(statusText); // Update and check snowflakes for (var i = snowflakes.length - 1; i >= 0; i--) { var snowflake = snowflakes[i]; // Check if snowflake went off screen if (snowflake.lastY >= -50 && snowflake.y < -50) { snowflake.destroy(); snowflakes.splice(i, 1); continue; } snowflake.lastY = snowflake.y; } // Update power-ups for (var p = powerUps.length - 1; p >= 0; p--) { var powerUp = powerUps[p]; if (powerUp.y > 2800) { powerUp.destroy(); powerUps.splice(p, 1); continue; } // Check collision with cannon if (powerUp.intersects(cannon)) { if (powerUp.type === 'shield') { cannon.activateShield(); } else if (powerUp.type === 'rapidfire') { cannon.activateRapidFire(); } else if (powerUp.type === 'multishot') { cannon.activateMultishot(); } particleSystem.createExplosion(powerUp.x, powerUp.y, 0x00ffff, 8); powerUp.destroy(); powerUps.splice(p, 1); } } // Update ice cube power-ups for (var ice = iceCubePowerUps.length - 1; ice >= 0; ice--) { var iceCube = iceCubePowerUps[ice]; if (iceCube.y > 2800) { iceCube.destroy(); iceCubePowerUps.splice(ice, 1); continue; } // Check collision with cannon if (iceCube.intersects(cannon)) { if (playerLives < maxLives) { playerLives++; updateLivesDisplay(); particleSystem.createExplosion(iceCube.x, iceCube.y, 0x87CEEB, 12); } iceCube.destroy(); iceCubePowerUps.splice(ice, 1); } } // Update green snowflake power-ups for (var gsf = greenSnowflakePowerUps.length - 1; gsf >= 0; gsf--) { var greenSnowflake = greenSnowflakePowerUps[gsf]; if (greenSnowflake.y > 2800) { greenSnowflake.destroy(); greenSnowflakePowerUps.splice(gsf, 1); continue; } // Check collision with cannon if (greenSnowflake.intersects(cannon)) { // Activate green transform greenTransformActive = true; greenTransformTimer = 300; // 5 seconds at 60fps // Transform all current sun rays to green and make them still for (var tsr = 0; tsr < sunrays.length; tsr++) { var sunray = sunrays[tsr]; sunray.speed = 0; // Stop movement tween(sunray, { tint: 0x00ff00 }, { duration: 500 }); } for (var trsr = 0; trsr < redSunrays.length; trsr++) { var redSunray = redSunrays[trsr]; redSunray.speed = 0; // Stop movement tween(redSunray, { tint: 0x00ff00 }, { duration: 500 }); } particleSystem.createExplosion(greenSnowflake.x, greenSnowflake.y, 0x00ff00, 12); greenSnowflake.destroy(); greenSnowflakePowerUps.splice(gsf, 1); } } // Update cannon power-ups for (var cp = cannonPowerUps.length - 1; cp >= 0; cp--) { var cannonPowerUp = cannonPowerUps[cp]; if (cannonPowerUp.y > 2800) { cannonPowerUp.destroy(); cannonPowerUps.splice(cp, 1); continue; } // Check collision with cannon if (cannonPowerUp.intersects(cannon)) { // Create new auto cannon var newAutoCannon = new AutoCannon(); newAutoCannon.x = cannon.x + (Math.random() - 0.5) * 200; // Spawn near main cannon newAutoCannon.y = cannon.y; autoCannons.push(newAutoCannon); game.addChild(newAutoCannon); particleSystem.createExplosion(cannonPowerUp.x, cannonPowerUp.y, 0xffd700, 12); cannonPowerUp.destroy(); cannonPowerUps.splice(cp, 1); } } // Update auto-cannons for (var ac = autoCannons.length - 1; ac >= 0; ac--) { var autoCannon = autoCannons[ac]; // Auto-cannons now stay indefinitely - no lifespan logic } // Update and check sun rays for (var j = sunrays.length - 1; j >= 0; j--) { var sunray = sunrays[j]; // Check if sun ray reached ground if (sunray.lastY <= 2750 && sunray.y > 2750) { if (!cannon.hasShield) { playerLives--; updateLivesDisplay(); LK.effects.flashScreen(0xff0000, 1000); if (playerLives <= 0) { LK.showGameOver(); return; } } else { // Shield absorbs the hit cannon.hasShield = false; cannon.shieldTime = 0; particleSystem.createExplosion(sunray.x, sunray.y, 0x00ffff, 12); } sunray.destroy(); sunrays.splice(j, 1); } sunray.lastY = sunray.y; } // Update and check red sun rays for (var k = redSunrays.length - 1; k >= 0; k--) { var redSunray = redSunrays[k]; // Check if red sun ray reached ground if (redSunray.lastY <= 2750 && redSunray.y > 2750) { if (!cannon.hasShield) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } else { // Shield absorbs the hit cannon.hasShield = false; cannon.shieldTime = 0; particleSystem.createExplosion(redSunray.x, redSunray.y, 0x00ffff, 12); redSunray.destroy(); redSunrays.splice(k, 1); } } redSunray.lastY = redSunray.y; } // Check collisions between snowflakes and sun rays for (var s = snowflakes.length - 1; s >= 0; s--) { var snowflake = snowflakes[s]; for (var r = sunrays.length - 1; r >= 0; r--) { var sunray = sunrays[r]; if (snowflake.intersects(sunray)) { // Collision detected raysDestroyed++; combo++; comboTimer = 180; // 3 seconds at 60fps var points = 10 + (combo - 1) * 5; totalScore += points; scoreText.setText('Score: ' + totalScore); if (combo > 1) { comboText.setText('COMBO x' + combo + ' (+' + points + ')'); } LK.getSound('hit').play(); // Create explosion effect particleSystem.createExplosion(sunray.x, sunray.y, 0xffd700, 10); // Remove both objects snowflake.destroy(); snowflakes.splice(s, 1); sunray.destroy(); sunrays.splice(r, 1); // Check level completion if (raysDestroyed >= raysNeededForLevel && !gameWon) { gameWon = true; polarBearDisplay.showHappy(); LK.getSound('levelcomplete').play(); LK.setTimeout(function () { // Next level currentLevel++; levelText.setText('Level: ' + currentLevel); raysNeededForLevel += 5; gameWon = false; combo = 0; comboTimer = 0; comboText.setText(''); // Reset polar bear display polarBearDisplay.destroy(); polarBearDisplay = game.addChild(new PolarBearDisplay()); polarBearDisplay.x = 1024; polarBearDisplay.y = 200; }, 3000); } break; } } } // Check collisions between snowflakes and red sun rays for (var s2 = snowflakes.length - 1; s2 >= 0; s2--) { var snowflake2 = snowflakes[s2]; for (var r2 = redSunrays.length - 1; r2 >= 0; r2--) { var redSunray2 = redSunrays[r2]; if (snowflake2.intersects(redSunray2)) { // Hit the red sunray var isDestroyed = redSunray2.hit(); LK.getSound('hit').play(); // Remove snowflake snowflake2.destroy(); snowflakes.splice(s2, 1); if (isDestroyed) { // Red sunray is destroyed after 2 hits raysDestroyed++; combo++; comboTimer = 180; // 3 seconds at 60fps var points = 20 + (combo - 1) * 10; // Double points for red sunrays totalScore += points; scoreText.setText('Score: ' + totalScore); if (combo > 1) { comboText.setText('COMBO x' + combo + ' (+' + points + ')'); } // Create explosion effect particleSystem.createExplosion(redSunray2.x, redSunray2.y, 0xff0000, 15); // Remove red sunray redSunray2.destroy(); redSunrays.splice(r2, 1); // Reduce red sunray spawn chance for 10 seconds redSunrayChanceReduced = true; redSunraySpawnChance = 0.05; // Reduce to 5% redSunrayChanceTimer = 600; // 10 seconds at 60fps // Check level completion if (raysDestroyed >= raysNeededForLevel && !gameWon) { gameWon = true; polarBearDisplay.showHappy(); LK.getSound('levelcomplete').play(); LK.setTimeout(function () { // Next level currentLevel++; levelText.setText('Level: ' + currentLevel); raysNeededForLevel += 5; gameWon = false; combo = 0; comboTimer = 0; comboText.setText(''); // Reset polar bear display polarBearDisplay.destroy(); polarBearDisplay = game.addChild(new PolarBearDisplay()); polarBearDisplay.x = 1024; polarBearDisplay.y = 200; }, 3000); } } else { // Create small hit effect for first hit particleSystem.createExplosion(redSunray2.x, redSunray2.y, 0xff6666, 5); } break; } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AutoCannon = Container.expand(function () {
var self = Container.call(this);
var cannonGraphics = self.attachAsset('cannon', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.8,
scaleY: 0.8
});
cannonGraphics.tint = 0xffd700; // Golden tint
self.moveSpeed = 8;
self.targetX = self.x;
self.isMoving = false;
self.lastShotTime = 0;
self.shootInterval = 1500; // Shoot every 1.5 seconds
self.update = function () {
// Find nearest target (prioritize red sunrays)
var nearestTarget = null;
var nearestDistance = Infinity;
// Check red sunrays first (priority)
for (var i = 0; i < redSunrays.length; i++) {
var redSunray = redSunrays[i];
var distance = Math.abs(redSunray.x - self.x);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestTarget = redSunray;
}
}
// If no red sunrays, check regular sunrays
if (!nearestTarget) {
for (var j = 0; j < sunrays.length; j++) {
var sunray = sunrays[j];
var distance = Math.abs(sunray.x - self.x);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestTarget = sunray;
}
}
}
// Move toward target
if (nearestTarget) {
self.targetX = nearestTarget.x;
self.isMoving = true;
}
// Handle movement
if (self.isMoving) {
var diff = self.targetX - self.x;
if (Math.abs(diff) > 4) {
self.x += diff > 0 ? self.moveSpeed : -self.moveSpeed;
} else {
self.x = self.targetX;
self.isMoving = false;
}
}
// Keep cannon within screen bounds
if (self.x < 150) self.x = 150;
if (self.x > 1898) self.x = 1898;
// Auto-shoot
var currentTime = LK.ticks * 16.67;
if (currentTime - self.lastShotTime >= self.shootInterval && nearestTarget) {
var newSnowflake = new Snowflake();
newSnowflake.x = self.x;
newSnowflake.y = self.y - 120;
newSnowflake.lastY = newSnowflake.y;
snowflakes.push(newSnowflake);
game.addChild(newSnowflake);
self.lastShotTime = currentTime;
LK.getSound('shoot').play();
}
};
return self;
});
var Cannon = Container.expand(function () {
var self = Container.call(this);
var cannonGraphics = self.attachAsset('cannon', {
anchorX: 0.5,
anchorY: 1.0
});
// Shield effect
var shieldGraphics = self.attachAsset('snowflake', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 6,
alpha: 0,
y: -80
});
shieldGraphics.tint = 0x00ffff;
self.moveSpeed = 12;
self.isMoving = false;
self.targetX = self.x;
self.hasShield = false;
self.shieldTime = 0;
self.rapidFireActive = false;
self.rapidFireTime = 0;
self.multishotActive = false;
self.multishotTime = 0;
self.shieldBobTimer = 0;
self.update = function () {
if (self.isMoving) {
var diff = self.targetX - self.x;
if (Math.abs(diff) > 2) {
self.x += diff > 0 ? self.moveSpeed : -self.moveSpeed;
} else {
self.x = self.targetX;
self.isMoving = false;
}
}
// Keep cannon within screen bounds
if (self.x < 150) self.x = 150;
if (self.x > 1898) self.x = 1898;
// Update shield
if (self.hasShield) {
self.shieldTime--;
self.shieldBobTimer += 0.1;
shieldGraphics.alpha = 0.6 + Math.sin(self.shieldBobTimer) * 0.2;
shieldGraphics.rotation += 0.05;
if (self.shieldTime <= 0) {
self.hasShield = false;
shieldGraphics.alpha = 0;
}
}
// Update rapid fire
if (self.rapidFireActive) {
self.rapidFireTime--;
cannonGraphics.tint = 0xff6600;
if (self.rapidFireTime <= 0) {
self.rapidFireActive = false;
cannonGraphics.tint = 0xffffff;
}
}
// Update multishot
if (self.multishotActive) {
self.multishotTime--;
if (self.multishotTime <= 0) {
self.multishotActive = false;
}
}
};
self.moveTo = function (targetX) {
self.targetX = targetX;
self.isMoving = true;
};
self.activateShield = function () {
self.hasShield = true;
self.shieldTime = 600; // 10 seconds at 60fps
};
self.activateRapidFire = function () {
self.rapidFireActive = true;
self.rapidFireTime = 600; // 10 seconds at 60fps
};
self.activateMultishot = function () {
self.multishotActive = true;
self.multishotTime = 300; // 5 seconds at 60fps
};
return self;
});
var CannonPowerUp = Container.expand(function () {
var self = Container.call(this);
var cannonGraphics = self.attachAsset('cannon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
cannonGraphics.tint = 0xffd700; // Golden tint
self.speed = 2;
self.bobTimer = 0;
self.update = function () {
self.y += self.speed;
self.bobTimer += 0.1;
cannonGraphics.y = Math.sin(self.bobTimer) * 10;
cannonGraphics.rotation += 0.05;
};
return self;
});
var GreenSnowflakePowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('snowflake', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
powerUpGraphics.tint = 0x00ff00; // Green tint
self.speed = 2;
self.bobTimer = 0;
self.update = function () {
self.y += self.speed;
self.bobTimer += 0.1;
powerUpGraphics.y = Math.sin(self.bobTimer) * 10;
powerUpGraphics.rotation += 0.05;
};
return self;
});
var IceCubePowerUp = Container.expand(function () {
var self = Container.call(this);
var iceCubeGraphics = self.attachAsset('iceblocksad', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
iceCubeGraphics.tint = 0x87CEEB; // Light blue tint
self.speed = 2;
self.bobTimer = 0;
self.update = function () {
self.y += self.speed;
self.bobTimer += 0.1;
iceCubeGraphics.y = Math.sin(self.bobTimer) * 15;
iceCubeGraphics.rotation += 0.03;
};
return self;
});
var ParticleEffect = Container.expand(function () {
var self = Container.call(this);
var particles = [];
self.createExplosion = function (x, y, color, count) {
for (var i = 0; i < count; i++) {
var particle = self.attachAsset('snowflake', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: x,
y: y
});
particle.tint = color;
var angle = Math.PI * 2 * i / count;
var speed = 100 + Math.random() * 100;
particle.vx = Math.cos(angle) * speed;
particle.vy = Math.sin(angle) * speed;
particle.life = 60; // frames
particles.push(particle);
}
};
self.update = function () {
for (var i = particles.length - 1; i >= 0; i--) {
var particle = particles[i];
particle.x += particle.vx * 0.016;
particle.y += particle.vy * 0.016;
particle.vy += 200 * 0.016; // gravity
particle.life--;
particle.alpha = particle.life / 60;
if (particle.life <= 0) {
particle.destroy();
particles.splice(i, 1);
}
}
};
return self;
});
var PolarBearDisplay = Container.expand(function () {
var self = Container.call(this);
var iceBlock = self.attachAsset('iceblocksad', {
anchorX: 0.5,
anchorY: 0.5
});
var bearSad = self.attachAsset('polarbearsad', {
anchorX: 0.5,
anchorY: 0.5,
y: 10
});
var bearHappy = self.attachAsset('polarbearhappy', {
anchorX: 0.5,
anchorY: 0.5,
y: 10,
alpha: 0
});
self.showHappy = function () {
// Generate ice particles when ice cube is destroyed
particleSystem.createExplosion(self.x, self.y - 20, 0xb0e0e6, 15);
tween(iceBlock, {
alpha: 0
}, {
duration: 1000
});
tween(bearSad, {
alpha: 0
}, {
duration: 1000
});
tween(bearHappy, {
alpha: 1
}, {
duration: 1000
});
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'shield'; // 'shield', 'rapidfire', or 'multishot'
var powerUpGraphics = self.attachAsset('snowflake', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
if (self.type === 'rapidfire') {
powerUpGraphics.tint = 0xff6600;
} else if (self.type === 'multishot') {
powerUpGraphics.tint = 0xff00ff;
} else {
powerUpGraphics.tint = 0x00ffff;
}
self.speed = 2;
self.bobTimer = 0;
self.update = function () {
self.y += self.speed;
self.bobTimer += 0.1;
powerUpGraphics.y = Math.sin(self.bobTimer) * 10;
powerUpGraphics.rotation += 0.05;
};
return self;
});
var RedSunRay = Container.expand(function () {
var self = Container.call(this);
var sunrayGraphics = self.attachAsset('sunray', {
anchorX: 0.5,
anchorY: 0.5
});
sunrayGraphics.tint = 0xff0000; // Make it red
self.speed = 2;
self.hits = 0;
self.maxHits = 2;
self.flashTimer = 0;
self.update = function () {
self.y += self.speed;
// Flash effect when hit
if (self.flashTimer > 0) {
self.flashTimer--;
var alpha = 0.3 + Math.sin(self.flashTimer * 0.5) * 0.3;
sunrayGraphics.alpha = alpha;
if (self.flashTimer <= 0) {
sunrayGraphics.alpha = 1;
}
}
};
self.hit = function () {
self.hits++;
self.flashTimer = 30; // Flash for 0.5 seconds
// Scale down slightly when hit
var newScale = 1 - self.hits / self.maxHits * 0.3;
sunrayGraphics.scaleX = newScale;
sunrayGraphics.scaleY = newScale;
return self.hits >= self.maxHits;
};
return self;
});
var Snowflake = Container.expand(function () {
var self = Container.call(this);
var snowflakeGraphics = self.attachAsset('snowflake', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var SunRay = Container.expand(function () {
var self = Container.call(this);
var sunrayGraphics = self.attachAsset('sunray', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Add frozen tundra background
var backgroundTundra = game.attachAsset('frozentundra', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
var cannon;
var snowflakes = [];
var sunrays = [];
var redSunrays = [];
var powerUps = [];
var cannonPowerUps = [];
var autoCannons = [];
var polarBearDisplay;
var particleSystem;
var lastShotTime = 0;
var lastSunRaySpawn = 0;
var lastPowerUpSpawn = 0;
var sunRaySpawnInterval = 3000; // 3 seconds initially
var powerUpSpawnInterval = 15000; // 15 seconds
var raysDestroyed = 0;
var raysNeededForLevel = 10;
var currentLevel = 1;
var gameWon = false;
var totalScore = 0;
var cannonPowerUpTriggered = false; // Track if 200-point cannon power-up was spawned
var tank500PowerUpTriggered = false; // Track if 500-point tank power-up was spawned
var tank2000PowerUpTriggered = false; // Track if 2000-point tank power-up was spawned
var combo = 0;
var comboTimer = 0;
var redSunraySpawnChance = 0.2; // Default 20% chance
var redSunrayChanceReduced = false;
var redSunrayChanceTimer = 0;
var playerLives = 3;
var maxLives = 3;
var iceCubePowerUps = [];
var greenSnowflakePowerUps = [];
var greenTransformActive = false;
var greenTransformTimer = 0;
var originalSunRaySpeeds = [];
// Create score display
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create combo display
var comboText = new Text2('', {
size: 40,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.y = 80;
LK.gui.top.addChild(comboText);
// Create level display
var levelText = new Text2('Level: 1', {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 150;
levelText.y = 20;
LK.gui.topRight.addChild(levelText);
// Create power-up status
var powerUpText = new Text2('', {
size: 35,
fill: 0x00FFFF
});
powerUpText.anchor.set(0, 0);
powerUpText.x = 150;
powerUpText.y = 80;
LK.gui.topRight.addChild(powerUpText);
// Create lives display
var livesContainer = new Container();
var livesDisplay = [];
for (var l = 0; l < maxLives; l++) {
var lifeIcon = LK.getAsset('iceblocksad', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: l * 80,
y: 0
});
livesDisplay.push(lifeIcon);
livesContainer.addChild(lifeIcon);
}
livesContainer.x = 100;
livesContainer.y = 100;
LK.gui.topLeft.addChild(livesContainer);
// Function to update lives display
function updateLivesDisplay() {
for (var i = 0; i < livesDisplay.length; i++) {
if (i < playerLives) {
livesDisplay[i].alpha = 1;
} else {
livesDisplay[i].alpha = 0.3;
}
}
}
// Initialize lives display
updateLivesDisplay();
// Start playing background music
LK.playMusic('FrozenSavior');
// Create cannon
cannon = game.addChild(new Cannon());
cannon.x = 1024;
cannon.y = 2680;
// Create particle system
particleSystem = game.addChild(new ParticleEffect());
// Create polar bear display
polarBearDisplay = game.addChild(new PolarBearDisplay());
polarBearDisplay.x = 1024;
polarBearDisplay.y = 200;
// Touch controls
game.down = function (x, y, obj) {
cannon.moveTo(x);
};
game.move = function (x, y, obj) {
cannon.moveTo(x);
};
// Main game update loop
game.update = function () {
var currentTime = LK.ticks * 16.67; // Convert to milliseconds
// Update combo timer
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0) {
combo = 0;
comboText.setText('');
}
}
// Update red sunray chance reduction timer
if (redSunrayChanceReduced) {
redSunrayChanceTimer--;
if (redSunrayChanceTimer <= 0) {
redSunrayChanceReduced = false;
redSunraySpawnChance = 0.2; // Reset to 20%
}
}
// Update green transform timer
if (greenTransformActive) {
greenTransformTimer--;
if (greenTransformTimer <= 0) {
// Restore original sun ray behavior
greenTransformActive = false;
for (var gsr = 0; gsr < sunrays.length; gsr++) {
var sunray = sunrays[gsr];
if (sunray.speed === 0) {
sunray.speed = 4; // Restore original speed
tween(sunray, {
tint: 0xffffff
}, {
duration: 500
});
}
}
for (var grsr = 0; grsr < redSunrays.length; grsr++) {
var redSunray = redSunrays[grsr];
if (redSunray.speed === 0) {
redSunray.speed = 2; // Restore original speed
tween(redSunray, {
tint: 0xff0000
}, {
duration: 500
});
}
}
}
}
// Auto-shoot snowflakes (faster with rapid fire and score-based speed boosts)
var baseShootInterval = 2000; // Default 2 seconds
if (totalScore >= 3000) {
baseShootInterval = 800; // Very fast at 3000+ points
} else if (totalScore >= 1000) {
baseShootInterval = 1200; // Faster at 1000+ points
}
var shootInterval = cannon.rapidFireActive ? 500 : baseShootInterval;
if (currentTime - lastShotTime >= shootInterval) {
var snowflakeCount = cannon.multishotActive ? 10 : 1;
for (var shot = 0; shot < snowflakeCount; shot++) {
var newSnowflake = new Snowflake();
if (snowflakeCount === 1) {
newSnowflake.x = cannon.x;
} else {
// Spread snowflakes in an arc
var spreadAngle = (shot - (snowflakeCount - 1) / 2) * 0.3;
newSnowflake.x = cannon.x + Math.sin(spreadAngle) * 50;
}
newSnowflake.y = cannon.y - 120;
newSnowflake.lastY = newSnowflake.y;
snowflakes.push(newSnowflake);
game.addChild(newSnowflake);
}
lastShotTime = currentTime;
LK.getSound('shoot').play();
}
// Spawn sun rays
if (currentTime - lastSunRaySpawn >= sunRaySpawnInterval) {
// Dynamic chance to spawn red sunray
if (Math.random() < redSunraySpawnChance) {
var newRedSunRay = new RedSunRay();
newRedSunRay.x = Math.random() * (2048 - 120) + 60;
newRedSunRay.y = -30;
newRedSunRay.lastY = newRedSunRay.y;
redSunrays.push(newRedSunRay);
game.addChild(newRedSunRay);
} else {
var newSunRay = new SunRay();
newSunRay.x = Math.random() * (2048 - 120) + 60;
newSunRay.y = -30;
newSunRay.lastY = newSunRay.y;
sunrays.push(newSunRay);
game.addChild(newSunRay);
}
lastSunRaySpawn = currentTime;
// Randomly vary spawn interval
sunRaySpawnInterval = Math.max(800, 2000 + Math.random() * 2000 - currentLevel * 100);
}
// Spawn special cannon power-up at 200 points
if (totalScore >= 200 && !cannonPowerUpTriggered) {
var specialCannonPowerUp = new CannonPowerUp();
specialCannonPowerUp.x = Math.random() * (2048 - 200) + 100;
specialCannonPowerUp.y = -30;
cannonPowerUps.push(specialCannonPowerUp);
game.addChild(specialCannonPowerUp);
cannonPowerUpTriggered = true;
}
// Spawn tank power-up at 500 points
if (totalScore >= 500 && !tank500PowerUpTriggered) {
var tank500PowerUp = new CannonPowerUp();
tank500PowerUp.x = Math.random() * (2048 - 200) + 100;
tank500PowerUp.y = -30;
cannonPowerUps.push(tank500PowerUp);
game.addChild(tank500PowerUp);
tank500PowerUpTriggered = true;
}
// Spawn tank power-up at 2000 points
if (totalScore >= 2000 && !tank2000PowerUpTriggered) {
var tank2000PowerUp = new CannonPowerUp();
tank2000PowerUp.x = Math.random() * (2048 - 200) + 100;
tank2000PowerUp.y = -30;
cannonPowerUps.push(tank2000PowerUp);
game.addChild(tank2000PowerUp);
tank2000PowerUpTriggered = true;
}
// Spawn power-ups
if (currentTime - lastPowerUpSpawn >= powerUpSpawnInterval) {
// Regular power-ups only
var newPowerUp = new PowerUp();
var regularType = Math.random();
if (regularType < 0.33) {
newPowerUp.type = 'shield';
} else if (regularType < 0.66) {
newPowerUp.type = 'rapidfire';
} else {
newPowerUp.type = 'multishot';
}
newPowerUp.x = Math.random() * (2048 - 200) + 100;
newPowerUp.y = -30;
powerUps.push(newPowerUp);
game.addChild(newPowerUp);
lastPowerUpSpawn = currentTime;
powerUpSpawnInterval = 12000 + Math.random() * 8000;
}
// Spawn ice cube power-up only if missing lives
if (playerLives < maxLives && Math.random() < 0.002) {
// Low spawn chance
var newIceCube = new IceCubePowerUp();
newIceCube.x = Math.random() * (2048 - 200) + 100;
newIceCube.y = -30;
iceCubePowerUps.push(newIceCube);
game.addChild(newIceCube);
}
// Spawn green snowflake power-up
if (Math.random() < 0.0003) {
// Very low spawn chance - rarest power-up
var newGreenSnowflake = new GreenSnowflakePowerUp();
newGreenSnowflake.x = Math.random() * (2048 - 200) + 100;
newGreenSnowflake.y = -30;
greenSnowflakePowerUps.push(newGreenSnowflake);
game.addChild(newGreenSnowflake);
}
// Update power-up status display
var statusText = '';
if (cannon.hasShield) {
statusText += 'SHIELD: ' + Math.ceil(cannon.shieldTime / 60) + 's ';
}
if (cannon.rapidFireActive) {
statusText += 'RAPID FIRE: ' + Math.ceil(cannon.rapidFireTime / 60) + 's';
}
if (cannon.multishotActive) {
statusText += 'MULTISHOT: ' + Math.ceil(cannon.multishotTime / 60) + 's';
}
powerUpText.setText(statusText);
// Update and check snowflakes
for (var i = snowflakes.length - 1; i >= 0; i--) {
var snowflake = snowflakes[i];
// Check if snowflake went off screen
if (snowflake.lastY >= -50 && snowflake.y < -50) {
snowflake.destroy();
snowflakes.splice(i, 1);
continue;
}
snowflake.lastY = snowflake.y;
}
// Update power-ups
for (var p = powerUps.length - 1; p >= 0; p--) {
var powerUp = powerUps[p];
if (powerUp.y > 2800) {
powerUp.destroy();
powerUps.splice(p, 1);
continue;
}
// Check collision with cannon
if (powerUp.intersects(cannon)) {
if (powerUp.type === 'shield') {
cannon.activateShield();
} else if (powerUp.type === 'rapidfire') {
cannon.activateRapidFire();
} else if (powerUp.type === 'multishot') {
cannon.activateMultishot();
}
particleSystem.createExplosion(powerUp.x, powerUp.y, 0x00ffff, 8);
powerUp.destroy();
powerUps.splice(p, 1);
}
}
// Update ice cube power-ups
for (var ice = iceCubePowerUps.length - 1; ice >= 0; ice--) {
var iceCube = iceCubePowerUps[ice];
if (iceCube.y > 2800) {
iceCube.destroy();
iceCubePowerUps.splice(ice, 1);
continue;
}
// Check collision with cannon
if (iceCube.intersects(cannon)) {
if (playerLives < maxLives) {
playerLives++;
updateLivesDisplay();
particleSystem.createExplosion(iceCube.x, iceCube.y, 0x87CEEB, 12);
}
iceCube.destroy();
iceCubePowerUps.splice(ice, 1);
}
}
// Update green snowflake power-ups
for (var gsf = greenSnowflakePowerUps.length - 1; gsf >= 0; gsf--) {
var greenSnowflake = greenSnowflakePowerUps[gsf];
if (greenSnowflake.y > 2800) {
greenSnowflake.destroy();
greenSnowflakePowerUps.splice(gsf, 1);
continue;
}
// Check collision with cannon
if (greenSnowflake.intersects(cannon)) {
// Activate green transform
greenTransformActive = true;
greenTransformTimer = 300; // 5 seconds at 60fps
// Transform all current sun rays to green and make them still
for (var tsr = 0; tsr < sunrays.length; tsr++) {
var sunray = sunrays[tsr];
sunray.speed = 0; // Stop movement
tween(sunray, {
tint: 0x00ff00
}, {
duration: 500
});
}
for (var trsr = 0; trsr < redSunrays.length; trsr++) {
var redSunray = redSunrays[trsr];
redSunray.speed = 0; // Stop movement
tween(redSunray, {
tint: 0x00ff00
}, {
duration: 500
});
}
particleSystem.createExplosion(greenSnowflake.x, greenSnowflake.y, 0x00ff00, 12);
greenSnowflake.destroy();
greenSnowflakePowerUps.splice(gsf, 1);
}
}
// Update cannon power-ups
for (var cp = cannonPowerUps.length - 1; cp >= 0; cp--) {
var cannonPowerUp = cannonPowerUps[cp];
if (cannonPowerUp.y > 2800) {
cannonPowerUp.destroy();
cannonPowerUps.splice(cp, 1);
continue;
}
// Check collision with cannon
if (cannonPowerUp.intersects(cannon)) {
// Create new auto cannon
var newAutoCannon = new AutoCannon();
newAutoCannon.x = cannon.x + (Math.random() - 0.5) * 200; // Spawn near main cannon
newAutoCannon.y = cannon.y;
autoCannons.push(newAutoCannon);
game.addChild(newAutoCannon);
particleSystem.createExplosion(cannonPowerUp.x, cannonPowerUp.y, 0xffd700, 12);
cannonPowerUp.destroy();
cannonPowerUps.splice(cp, 1);
}
}
// Update auto-cannons
for (var ac = autoCannons.length - 1; ac >= 0; ac--) {
var autoCannon = autoCannons[ac];
// Auto-cannons now stay indefinitely - no lifespan logic
}
// Update and check sun rays
for (var j = sunrays.length - 1; j >= 0; j--) {
var sunray = sunrays[j];
// Check if sun ray reached ground
if (sunray.lastY <= 2750 && sunray.y > 2750) {
if (!cannon.hasShield) {
playerLives--;
updateLivesDisplay();
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
} else {
// Shield absorbs the hit
cannon.hasShield = false;
cannon.shieldTime = 0;
particleSystem.createExplosion(sunray.x, sunray.y, 0x00ffff, 12);
}
sunray.destroy();
sunrays.splice(j, 1);
}
sunray.lastY = sunray.y;
}
// Update and check red sun rays
for (var k = redSunrays.length - 1; k >= 0; k--) {
var redSunray = redSunrays[k];
// Check if red sun ray reached ground
if (redSunray.lastY <= 2750 && redSunray.y > 2750) {
if (!cannon.hasShield) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
} else {
// Shield absorbs the hit
cannon.hasShield = false;
cannon.shieldTime = 0;
particleSystem.createExplosion(redSunray.x, redSunray.y, 0x00ffff, 12);
redSunray.destroy();
redSunrays.splice(k, 1);
}
}
redSunray.lastY = redSunray.y;
}
// Check collisions between snowflakes and sun rays
for (var s = snowflakes.length - 1; s >= 0; s--) {
var snowflake = snowflakes[s];
for (var r = sunrays.length - 1; r >= 0; r--) {
var sunray = sunrays[r];
if (snowflake.intersects(sunray)) {
// Collision detected
raysDestroyed++;
combo++;
comboTimer = 180; // 3 seconds at 60fps
var points = 10 + (combo - 1) * 5;
totalScore += points;
scoreText.setText('Score: ' + totalScore);
if (combo > 1) {
comboText.setText('COMBO x' + combo + ' (+' + points + ')');
}
LK.getSound('hit').play();
// Create explosion effect
particleSystem.createExplosion(sunray.x, sunray.y, 0xffd700, 10);
// Remove both objects
snowflake.destroy();
snowflakes.splice(s, 1);
sunray.destroy();
sunrays.splice(r, 1);
// Check level completion
if (raysDestroyed >= raysNeededForLevel && !gameWon) {
gameWon = true;
polarBearDisplay.showHappy();
LK.getSound('levelcomplete').play();
LK.setTimeout(function () {
// Next level
currentLevel++;
levelText.setText('Level: ' + currentLevel);
raysNeededForLevel += 5;
gameWon = false;
combo = 0;
comboTimer = 0;
comboText.setText('');
// Reset polar bear display
polarBearDisplay.destroy();
polarBearDisplay = game.addChild(new PolarBearDisplay());
polarBearDisplay.x = 1024;
polarBearDisplay.y = 200;
}, 3000);
}
break;
}
}
}
// Check collisions between snowflakes and red sun rays
for (var s2 = snowflakes.length - 1; s2 >= 0; s2--) {
var snowflake2 = snowflakes[s2];
for (var r2 = redSunrays.length - 1; r2 >= 0; r2--) {
var redSunray2 = redSunrays[r2];
if (snowflake2.intersects(redSunray2)) {
// Hit the red sunray
var isDestroyed = redSunray2.hit();
LK.getSound('hit').play();
// Remove snowflake
snowflake2.destroy();
snowflakes.splice(s2, 1);
if (isDestroyed) {
// Red sunray is destroyed after 2 hits
raysDestroyed++;
combo++;
comboTimer = 180; // 3 seconds at 60fps
var points = 20 + (combo - 1) * 10; // Double points for red sunrays
totalScore += points;
scoreText.setText('Score: ' + totalScore);
if (combo > 1) {
comboText.setText('COMBO x' + combo + ' (+' + points + ')');
}
// Create explosion effect
particleSystem.createExplosion(redSunray2.x, redSunray2.y, 0xff0000, 15);
// Remove red sunray
redSunray2.destroy();
redSunrays.splice(r2, 1);
// Reduce red sunray spawn chance for 10 seconds
redSunrayChanceReduced = true;
redSunraySpawnChance = 0.05; // Reduce to 5%
redSunrayChanceTimer = 600; // 10 seconds at 60fps
// Check level completion
if (raysDestroyed >= raysNeededForLevel && !gameWon) {
gameWon = true;
polarBearDisplay.showHappy();
LK.getSound('levelcomplete').play();
LK.setTimeout(function () {
// Next level
currentLevel++;
levelText.setText('Level: ' + currentLevel);
raysNeededForLevel += 5;
gameWon = false;
combo = 0;
comboTimer = 0;
comboText.setText('');
// Reset polar bear display
polarBearDisplay.destroy();
polarBearDisplay = game.addChild(new PolarBearDisplay());
polarBearDisplay.x = 1024;
polarBearDisplay.y = 200;
}, 3000);
}
} else {
// Create small hit effect for first hit
particleSystem.createExplosion(redSunray2.x, redSunray2.y, 0xff6666, 5);
}
break;
}
}
}
};
Snowflake. In-Game asset. 2d. High contrast. No shadows
Sad baby polar bear. In-Game asset. 2d. High contrast. No shadows
Happy baby polar bear. In-Game asset. 2d. High contrast. No shadows
Gigantic ice tundra. In-Game asset. 2d. High contrast. No shadows
Ice cube seen from the front. In-Game asset. 2d. High contrast. No shadows