User prompt
So every so often red sunbeams appear that need two snowflakes to be destroyed.
User prompt
So the song Frozen Savior plays all the time in the game
User prompt
So when the ice cube is destroyed it generates ice particles βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Create a power up that makes you throw 10 snowflakes instead of 1 for 5 seconds βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
So the sun rays are bigger and there is a problem that makes the canyon shake, solve it
User prompt
So the snowflakes are bigger
User prompt
Now so the cannon is bigger much bigger
User prompt
So the game gets bigger
Code edit (1 edits merged)
Please save this source code
User prompt
Arctic Guardian: Polar Bear Rescue
Initial prompt
Create a game where you have to move an ice beam from right to left that points upwards, that every 2 seconds throws a snowflake and that rays of sun fall randomly from the sky And they are destroyed by colliding with snowflakes the objective is to protect the Arctic from the sun's rays at the top a sad polar bear appears in a block of ice when you complete a level it will change Happy polar bear
/**** * 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