User prompt
Level increases every 10 kills
User prompt
The rocket only moves left and right.
User prompt
rocket moves and fires with the left mouse button
User prompt
bu roket ateş etmiyor
User prompt
The rocket can move and shoot at the same time with the mouse.
User prompt
The rocket is fired with the right mouse button.
User prompt
let the rocket move as the mouse moves
User prompt
let the rocket move
Code edit (1 edits merged)
Please save this source code
User prompt
Rocket vs Alien Swarm
Initial prompt
let's have a rocket in space. Let the aliens attack this rocket. And let the rocket shoot at these aliens. for every alien who touches the rocket, let the rocket's life decrease. And for every alien hit by the rocket, let the rocket's level rise. Let the aliens disappear in 2 strokes. An increase in the level 7 of the rocket alien.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Alien class var Alien = Container.expand(function () { var self = Container.call(this); var alienAsset = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5 }); self.width = alienAsset.width; self.height = alienAsset.height; self.hp = 2; // Each alien takes 2 hits (all aliens always 2 hits) self.isHit = false; self.hitTween = null; // For hit flash self.flash = function () { // If a previous hitTween is running, stop it if (self.hitTween) { tween.stop(alienAsset, { tint: true }); } // Set alien to red tint alienAsset.tint = 0xff5252; // Tween back to normal color (no tint) over 120ms self.hitTween = tween(alienAsset, { tint: 0xffffff }, { duration: 120, easing: tween.linear, onFinish: function onFinish() { self.hitTween = null; } }); }; // For movement self.speed = 8 + Math.random() * 4; // Slightly random speed self.update = function () { // Only move downwards, do not follow rocket's x position self.y += self.speed; }; return self; }); // Bigger Alien class (for level > 3, 3 hits to kill, larger) var BiggerAlien = Container.expand(function () { var self = Container.call(this); var alienAsset = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.width = alienAsset.width * 1.5; self.height = alienAsset.height * 1.5; self.hp = 2; // Takes 2 hits (all enemies always 2 hits) self.isHit = false; self.hitTween = null; self.flash = function () { if (self.hitTween) { tween.stop(alienAsset, { tint: true }); } alienAsset.tint = 0xff5252; self.hitTween = tween(alienAsset, { tint: 0xffffff }, { duration: 120, easing: tween.linear, onFinish: function onFinish() { self.hitTween = null; } }); }; // For movement self.speed = 10 + Math.random() * 2; // Slightly slower than strong alien self.update = function () { self.y += self.speed; }; return self; }); // Boss Alien class (for level 7) var BossAlien = Container.expand(function () { var self = Container.call(this); var bossAsset = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.7, scaleY: 1.7 }); self.width = bossAsset.width * 1.7; self.height = bossAsset.height * 1.7; self.hp = 2; // Boss takes 2 hits (all enemies always 2 hits) self.isHit = false; self.hitTween = null; self.flash = function () { if (self.hitTween) { tween.stop(bossAsset, { tint: true }); } bossAsset.tint = 0xff5252; self.hitTween = tween(bossAsset, { tint: 0xffffff }, { duration: 120, easing: tween.linear, onFinish: function onFinish() { self.hitTween = null; } }); }; self.speed = 10; // Boss is faster self.update = function () { // Only move downwards, do not follow rocket's x position self.y += self.speed; }; return self; }); // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -32; // Upwards self.power = bulletPower; // Set bullet power at creation self.update = function () { self.y += self.speed; }; return self; }); // Enemy bullet class (alien shoots at player) var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); bulletAsset.tint = 0xff5252; // Red tint for enemy bullets self.speed = 27; // Downwards, 1.5x faster than before self.update = function () { self.y += self.speed; }; return self; }); // Rocket (player) class var Rocket = Container.expand(function () { var self = Container.call(this); var rocketAsset = self.attachAsset('rocket', { anchorX: 0.5, anchorY: 0.5 }); self.width = rocketAsset.width; self.height = rocketAsset.height; // For hit flash self.flashTween = null; // Show hit flash self.flash = function () { // If a previous flashTween is running, stop it if (self.flashTween) { tween.stop(rocketAsset, { tint: true }); } // Set rocket to reddish tint rocketAsset.tint = 0xff5252; // Tween back to normal color (white) over 200ms self.flashTween = tween(rocketAsset, { tint: 0xffffff }, { duration: 200, easing: tween.linear, onFinish: function onFinish() { self.flashTween = null; } }); }; return self; }); // Star class for animated background stars var Star = Container.expand(function () { var self = Container.call(this); // Use a larger ellipse for the star to make it more visible var size = 6 + Math.random() * 8; // Increased min and max size var starAsset = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: size / 160, scaleY: size / 160 }); // Brighter color choices for more visibility var colorChoices = [0xffffff, 0xe3f2fd, 0xfffde7, 0xb3e5fc, 0xfff9c4]; starAsset.tint = colorChoices[Math.floor(Math.random() * colorChoices.length)]; self.width = size; self.height = size; self.speed = 2.5 + Math.random() * 4.5; // Higher minimum alpha for more visible stars self.alpha = 0.7 + Math.random() * 0.3; self.update = function () { self.y += self.speed; if (self.y > GAME_HEIGHT + 10) { // Respawn at top self.y = -10; self.x = 10 + Math.random() * (GAME_WIDTH - 20); self.speed = 2.5 + Math.random() * 4.5; self.alpha = 0.7 + Math.random() * 0.3; } }; return self; }); // Strong Alien class (tougher, faster) var StrongAlien = Container.expand(function () { var self = Container.call(this); var alienAsset = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); self.width = alienAsset.width * 1.2; self.height = alienAsset.height * 1.2; self.hp = 2; // Strong alien takes 2 hits (all enemies always 2 hits) self.isHit = false; self.hitTween = null; self.flash = function () { if (self.hitTween) { tween.stop(alienAsset, { tint: true }); } alienAsset.tint = 0xff5252; self.hitTween = tween(alienAsset, { tint: 0xffffff }, { duration: 120, easing: tween.linear, onFinish: function onFinish() { self.hitTween = null; } }); }; // For movement self.speed = 12 + Math.random() * 3; // Stronger and faster self.update = function () { // Only move downwards, do not follow rocket's x position self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game constants // Rocket (player) // Alien (enemy) // Bullet // Alien hit flash // Life bar // Life bar background var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; // --- Kill Counter (top right) --- var killNumberText = new Text2("0", { size: 68, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", shadow: { color: 0x1976D2, blur: 8, offsetX: 0, offsetY: 2 } }); killNumberText.anchor.set(1, 0); // right anchor, top edge killNumberText.x = GAME_WIDTH - 40; killNumberText.y = 40; LK.gui.top.addChild(killNumberText); // --- Starfield background --- var stars = []; var STAR_COUNT = 60; for (var i = 0; i < STAR_COUNT; ++i) { var star = new Star(); star.x = 10 + Math.random() * (GAME_WIDTH - 20); star.y = Math.random() * GAME_HEIGHT; stars.push(star); game.addChildAt(star, 0); // Add behind all other objects } var ROCKET_START_LIFE = 5; var LEVEL_TO_BOSS = 7; // Game state var rocket = null; var bullets = []; var aliens = []; var level = 1; var rocketLife = ROCKET_START_LIFE; var bulletPower = 1; // Bullet power, increases every level var canShoot = true; var shootCooldown = 0; var dragNode = null; var lastMoveX = 0; var lastMoveY = 0; var score = 0; var bossSpawned = false; var enemyBullets = []; // Track enemy bullets // --- Shield state for rocket --- var rocketShieldActive = false; var rocketShieldTimer = 0; var rocketShieldVisual = null; // GUI elements var scoreTxt = new Text2('0', { size: 90, fill: "#fff" }); scoreTxt.anchor.set(0.5, 1); // Ensure score is always visible scoreTxt.alpha = 1; scoreTxt.visible = true; // Position the score text horizontally aligned with the rocket, above it scoreTxt.x = GAME_WIDTH / 2; scoreTxt.y = GAME_HEIGHT - 400 - (rocket ? rocket.height / 2 : 110) - 40; // 40px above rocket top, fallback if rocket not yet created LK.gui.top.addChild(scoreTxt); if (LK.gui.top.children && LK.gui.top.children.length > 1) { LK.gui.top.setChildIndex(scoreTxt, LK.gui.top.children.length - 1); } // New health bar will be created below // updateLevelBar and updateLevelText helpers removed as level bar is no longer shown // Helper to update score text function updateScoreText() { scoreTxt.setText(score); // Update kill counter text (if defined) if (typeof killCounterText !== "undefined") { killCounterText.setText(score.toString()); } // Update kill number text (top right) if (typeof killNumberText !== "undefined") { killNumberText.setText(score.toString()); } // Update health bar kill counter text (if defined) if (typeof healthBarKillCounterText !== "undefined") { healthBarKillCounterText.setText(score.toString()); } // Update rocket kill counter text (above rocket) if (typeof rocketKillCounterText !== "undefined") { rocketKillCounterText.setText(score.toString()); } // updateLevelBar removed } // Spawn a new alien function spawnAlien() { var alien; if (level === LEVEL_TO_BOSS && !bossSpawned) { alien = new BossAlien(); alien.hp = 2; // Boss always 2 hits bossSpawned = true; } else { // 20% chance to spawn a BiggerAlien after level 3, 30% StrongAlien, otherwise normal Alien if (level > 3 && Math.random() < 0.2) { alien = new BiggerAlien(); alien.hp = 2; // Always 2 hits for bigger alien } else if (Math.random() < 0.3 && level > 2) { alien = new StrongAlien(); alien.hp = 2; // Always 2 hits for strong alien } else { alien = new Alien(); alien.hp = 2; // Always 2 hits for normal alien } } // Defensive: always set hp to 2 for all enemy types if (alien) { alien.hp = 2; // 1. seviyede düşmanlar 1.5 kat hızlı gelsin if (level === 1 && typeof alien.speed === "number") { alien.speed *= 1.5; } } // Random x, but keep inside screen var margin = 120; alien.x = margin + Math.random() * (GAME_WIDTH - margin * 2); alien.y = -alien.height / 2; aliens.push(alien); game.addChild(alien); } // Reset game state function resetGame() { // Remove all bullets and aliens for (var i = 0; i < bullets.length; ++i) { bullets[i].destroy(); } for (var j = 0; j < aliens.length; ++j) { aliens[j].destroy(); } for (var k = 0; k < enemyBullets.length; ++k) { enemyBullets[k].destroy(); } bullets = []; aliens = []; enemyBullets = []; level = 1; rocketLife = ROCKET_START_LIFE; bulletPower = 1; // Always 1, so all enemies take 2 hits canShoot = true; shootCooldown = 0; dragNode = null; lastMoveX = 0; lastMoveY = 0; score = 0; bossSpawned = false; // updateLevelText and updateLevelBar removed updateScoreText(); updateLevelBar(); updateHealthBar(); } // Initialize rocket rocket = new Rocket(); rocket.x = GAME_WIDTH / 2; rocket.y = GAME_HEIGHT - 400; game.addChild(rocket); // --- Rocket health bar that follows rocket --- var rocketLifeBarBg = LK.getAsset('lifeBarBg', { anchorX: 0.5, anchorY: 0, x: 0, y: 0, width: 220, height: 18 }); var rocketLifeBar = LK.getAsset('lifeBar', { anchorX: 0, anchorY: 0, x: -110, y: 0, width: 220, height: 18 }); var rocketLifeBarContainer = new Container(); rocketLifeBarContainer.addChild(rocketLifeBarBg); rocketLifeBarContainer.addChild(rocketLifeBar); rocketLifeBarContainer.x = rocket.x; rocketLifeBarContainer.y = rocket.y + rocket.height / 2 + 12; // 12px below rocket game.addChild(rocketLifeBarContainer); // Move scoreTxt to be above the rocket, horizontally aligned scoreTxt.x = rocket.x; scoreTxt.y = rocket.y - rocket.height / 2 - 40; // 40px above rocket top // --- Kill Counter above Rocket --- // Create kill counter text to be placed above the rocket var rocketKillCounterText = new Text2("0", { size: 54, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", shadow: { color: 0x1976D2, blur: 8, offsetX: 0, offsetY: 2 } }); rocketKillCounterText.anchor.set(0.5, 1); // center anchor, bottom edge rocketKillCounterText.x = rocket.x; rocketKillCounterText.y = rocket.y - rocket.height / 2 - 60; // 60px above rocket top game.addChild(rocketKillCounterText); // --- New Health Bar (top center) --- var healthBarBg = LK.getAsset('lifeBarBg', { anchorX: 0.5, anchorY: 0.5, width: 440, height: 44, x: 0, y: 0 }); var healthBar = LK.getAsset('lifeBar', { anchorX: 0, anchorY: 0.5, width: 400, height: 36, x: -200, y: 0 }); var healthBarContainer = new Container(); healthBarContainer.addChild(healthBarBg); healthBarContainer.addChild(healthBar); healthBarContainer.x = GAME_WIDTH / 2; healthBarContainer.y = 110; LK.gui.top.addChild(healthBarContainer); // --- Kill Counter below Health Bar (top center) --- var healthBarKillCounterText = new Text2("0", { size: 54, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", shadow: { color: 0x1976D2, blur: 8, offsetX: 0, offsetY: 2 } }); healthBarKillCounterText.anchor.set(0.5, 0); // center anchor, top edge healthBarKillCounterText.x = GAME_WIDTH / 2; healthBarKillCounterText.y = healthBarContainer.y + 32; // just below health bar LK.gui.top.addChild(healthBarKillCounterText); // Helper to update health bar function updateHealthBar() { var percent = rocketLife / ROCKET_START_LIFE; if (percent < 0) { percent = 0; } if (percent > 1) { percent = 1; } healthBar.width = 400 * percent; if (percent > 0.5) { healthBar.tint = 0x43a047; } else if (percent > 0.2) { healthBar.tint = 0xffc107; } else { healthBar.tint = 0xd32f2f; } } // Initial GUI // updateLevelText and updateLevelBar removed updateScoreText(); updateHealthBar(); // Touch/move controls game.down = function (x, y, obj) { // Only start drag if touch is on rocket var local = rocket.toLocal(game.toGlobal({ x: x, y: y })); if (local.x > -rocket.width / 2 && local.x < rocket.width / 2 && local.y > -rocket.height / 2 && local.y < rocket.height / 2) { dragNode = rocket; lastMoveX = x; lastMoveY = y; } }; game.move = function (x, y, obj) { // Always move the rocket to the mouse/touch position, clamped to screen var newX = x; var halfW = rocket && rocket.width ? rocket.width / 2 : 70; // fallback to 70 if rocket is null if (newX < halfW) { newX = halfW; } if (newX > GAME_WIDTH - halfW) { newX = GAME_WIDTH - halfW; } if (rocket) { rocket.x = newX; // Y position stays fixed at the starting Y rocket.y = GAME_HEIGHT - 400; } lastMoveX = x; lastMoveY = y; }; game.up = function (x, y, obj) { dragNode = null; }; // Tap to shoot (left mouse button or tap) game.down = function (x, y, obj) { // Only start drag if touch is on rocket var local = rocket.toLocal(game.toGlobal({ x: x, y: y })); if (local.x > -rocket.width / 2 && local.x < rocket.width / 2 && local.y > -rocket.height / 2 && local.y < rocket.height / 2) { dragNode = rocket; lastMoveX = x; lastMoveY = y; } // Always allow shooting with left mouse button/tap, regardless of drag state if (canShoot) { shootBullet(); } }; // Shoot bullet function shootBullet() { if (!canShoot) { return; } var bullet = new Bullet(); bullet.x = rocket.x; bullet.y = rocket.y - rocket.height / 2 - 20; bullets.push(bullet); game.addChild(bullet); // Play laser gun sound effect LK.getSound('dfds').play(); canShoot = false; shootCooldown = 10; // 10 ticks cooldown } // Main update loop game.update = function () { // Shooting cooldown if (!canShoot) { shootCooldown--; if (shootCooldown <= 0) { canShoot = true; } } // --- Shield logic update --- if (rocketShieldActive) { rocketShieldTimer--; // Keep shield visual in sync with rocket if (rocket && rocketShieldVisual && rocket.children.indexOf(rocketShieldVisual) === -1) { rocket.addChild(rocketShieldVisual); if (rocket.children.length > 1) { rocket.setChildIndex(rocketShieldVisual, 0); } } if (rocketShieldTimer <= 0) { rocketShieldActive = false; rocketShieldTimer = 0; // Remove shield visual if (rocketShieldVisual && rocket) { rocket.removeChild(rocketShieldVisual); } rocketShieldVisual = null; } } else { // Defensive: remove shield visual if not active if (rocketShieldVisual && rocket) { rocket.removeChild(rocketShieldVisual); rocketShieldVisual = null; } } // Update stars for (var si = 0; si < stars.length; ++si) { stars[si].update(); } // Keep score counter aligned with rocket scoreTxt.x = rocket.x; scoreTxt.y = rocket.y - rocket.height / 2 - 40; // 40px above rocket top // Move rocket kill counter above rocket if (typeof rocketKillCounterText !== "undefined" && rocket) { rocketKillCounterText.x = rocket.x; rocketKillCounterText.y = rocket.y - rocket.height / 2 - 60; } // Move kill counter to the right of the rocket, just above it if (typeof killCounterText !== "undefined" && rocket) { killCounterText.x = rocket.x + rocket.width / 2 + 32; killCounterText.y = rocket.y - rocket.height / 2 - 40; } // Move rocket health bar with rocket if (typeof rocketLifeBarContainer !== "undefined") { rocketLifeBarContainer.x = rocket.x; rocketLifeBarContainer.y = rocket.y + rocket.height / 2 + 12; // 12px below rocket // Update width and color var percent = rocketLife / ROCKET_START_LIFE; if (percent < 0) { percent = 0; } rocketLifeBar.width = 220 * percent; if (percent > 0.5) { rocketLifeBar.tint = 0x43a047; } else if (percent > 0.2) { rocketLifeBar.tint = 0xffc107; } else { rocketLifeBar.tint = 0xd32f2f; } // Do NOT change rocket color based on health } // (level bar stays fixed in GUI, do not move with rocket) // Update bullets for (var i = bullets.length - 1; i >= 0; --i) { var b = bullets[i]; b.update(); // Remove if off screen if (b.y < -100) { b.destroy(); bullets.splice(i, 1); continue; } } // Update aliens for (var j = aliens.length - 1; j >= 0; --j) { var a = aliens[j]; a.update(); // Remove if off screen if (a.y > GAME_HEIGHT + 200) { a.destroy(); aliens.splice(j, 1); continue; } // Alien shooting logic: all aliens shoot every eligible tick (no randomness, no alignment check) if (level > 1 && a.y > 0 && a.y < GAME_HEIGHT - 400) { if (LK.ticks % Math.max(60 - level * 4, 18) === 0) { if (level >= 5) { // Shoot two bullets, slightly offset horizontally var offset = 38; for (var bidx = -1; bidx <= 1; bidx += 2) { var enemyBullet = new EnemyBullet(); enemyBullet.x = a.x + bidx * offset; enemyBullet.y = a.y + a.height / 2 + 10; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); } } else { // Shoot one bullet as before var enemyBullet = new EnemyBullet(); enemyBullet.x = a.x; enemyBullet.y = a.y + a.height / 2 + 10; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); } } } // Check collision with rocket (alien-rocket contact) if (a.intersects(rocket)) { if (!rocketShieldActive && rocketLife > 0) { rocketLife--; updateHealthBar(); rocket.flash(); // Destroy rocket if it has taken 5 damage if (rocketLife <= 0) { // Play rocket explosion sound when rocket's life reaches zero LK.getSound('patlama').play(); if (rocket && typeof rocket.destroy === "function") { rocket.destroy(); rocket = null; } } } // Remove alien on contact a.destroy(); aliens.splice(j, 1); // Check for game over if (rocketLife <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.getSound('patlama').play(); LK.showGameOver(); return; } } // No alien-rocket collision: aliens do not damage rocket by contact } // Update enemy bullets for (var eb = enemyBullets.length - 1; eb >= 0; --eb) { var ebull = enemyBullets[eb]; ebull.update(); // Remove if off screen if (ebull.y > GAME_HEIGHT + 100) { ebull.destroy(); enemyBullets.splice(eb, 1); continue; } // Check collision with rocket if (ebull.intersects(rocket)) { if (!rocketShieldActive && rocketLife > 0) { if (level >= 6) { rocketLife = 0; } else { rocketLife -= 0.5; } updateHealthBar(); rocket.flash(); // Destroy rocket if it has taken 5 damage if (rocketLife <= 0) { if (rocket && typeof rocket.destroy === "function") { // Play rocket explosion sound LK.getSound('patlama').play(); rocket.destroy(); rocket = null; } } } ebull.destroy(); enemyBullets.splice(eb, 1); // Check for game over if (rocketLife <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } } // Bullet-alien collisions for (var i2 = bullets.length - 1; i2 >= 0; --i2) { var b2 = bullets[i2]; for (var j2 = aliens.length - 1; j2 >= 0; --j2) { var a2 = aliens[j2]; if (b2.intersects(a2)) { a2.hp -= b2.power !== undefined ? b2.power : 1; // Use bullet power, fallback to 1 a2.flash(); b2.destroy(); bullets.splice(i2, 1); if (a2.hp <= 0) { a2.destroy(); aliens.splice(j2, 1); score++; updateScoreText(); updateLevelBar(); // Increase level every 10 kills if (level < LEVEL_TO_BOSS && score % 10 === 0) { level++; // Flash the screen to indicate level up LK.effects.flashScreen(0xffffff, 600); // White flash for 600ms // Activate 4s shield when reaching level 3 if (level === 3) { rocketShieldActive = true; rocketShieldTimer = 240; // 4 seconds at 60 FPS // Add shield visual if not present if (!rocketShieldVisual && rocket) { rocketShieldVisual = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.1, scaleY: 2.1, x: 0, y: 0, color: 0x2196f3, tint: 0x2196f3 }); rocketShieldVisual.alpha = 0.38; rocket.addChild(rocketShieldVisual); // Make sure shield is behind rocket sprite if (rocket.children.length > 1) { rocket.setChildIndex(rocketShieldVisual, 0); } } } // End game after level 6 (when level becomes 7) if (level === LEVEL_TO_BOSS) { LK.effects.flashScreen(0x00e676, 1000); LK.showYouWin(); return; } bulletPower = 1; // Always 1, so all enemies take 2 hits rocketLife = ROCKET_START_LIFE; // Full heal on level up updateHealthBar(); updateLevelBar(); // Star explosion effect at center of screen for (var sx = 0; sx < 18; ++sx) { (function (sx) { var star = new Star(); star.x = GAME_WIDTH / 2; star.y = GAME_HEIGHT / 2; // Give each star a random direction and speed var angle = Math.PI * 2 * (sx / 18); var speed = 18 + Math.random() * 12; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; var life = 32 + Math.floor(Math.random() * 16); var tick = 0; // Animate star outward and fade out star.update = function () { star.x += vx; star.y += vy; star.alpha -= 0.025; tick++; if (tick > life || star.alpha <= 0) { star.destroy(); } }; game.addChild(star); })(sx); } // Change all background star colors var colorChoices = [0xffffff, 0xe3f2fd, 0xfffde7, 0xb3e5fc, 0xfff9c4, 0xffb3c6, 0xc5e1a5, 0xffcc80, 0x90caf9, 0xf8bbd0]; for (var sc = 0; sc < stars.length; ++sc) { var starObj = stars[sc]; // Only change tint if starObj has children and a valid asset if (starObj.children && starObj.children.length > 0 && starObj.children[0]) { var newColor = colorChoices[Math.floor(Math.random() * colorChoices.length)]; starObj.children[0].tint = newColor; } } // Add more stars to the background on each level up var additionalStars = 8; // Number of stars to add per level up for (var addStar = 0; addStar < additionalStars; ++addStar) { var newStar = new Star(); newStar.x = 10 + Math.random() * (GAME_WIDTH - 20); newStar.y = Math.random() * GAME_HEIGHT; stars.push(newStar); game.addChildAt(newStar, 0); // Add behind all other objects } } // If boss defeated, win if (level === LEVEL_TO_BOSS && bossSpawned && aliens.length === 0) { LK.effects.flashScreen(0x00e676, 1000); LK.showYouWin(); return; } } break; } } } // Alien spawn logic if (level < LEVEL_TO_BOSS) { // Increase max aliens on screen as level increases var maxAliens = 2 + Math.floor((level - 1) / 2); // +1 every 2 levels (2,3,4,5...) // Double the number of aliens on level 5 and above if (level >= 5) { maxAliens *= 2; } // Increase spawn rate as level increases var spawnRate = Math.max(1, 1 + Math.floor((level - 1) / 2)); // +1 spawn per 2 levels if (level >= 5) { spawnRate *= 2; } if (aliens.length < maxAliens && LK.ticks % (60 - level * 4) === 0) { for (var s = 0; s < spawnRate && aliens.length < maxAliens; ++s) { spawnAlien(); } } } else if (level === LEVEL_TO_BOSS && !bossSpawned) { // Spawn boss spawnAlien(); } }; // --- Level Bar (next to Seviye text) --- // Level text var levelText = new Text2("Seviye", { size: 68, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", shadow: { color: 0x1976D2, blur: 8, offsetX: 0, offsetY: 2 } }); levelText.anchor.set(1, 0.5); // Level bar background var levelBarBg = LK.getAsset('lifeBarBg', { anchorX: 0, anchorY: 0.5, width: 420, height: 64, x: 0, y: 0 }); // Level bar fill (fills with each kill) var levelBar = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0.5, width: 420, height: 48, x: 0, y: 0, color: 0x2196f3, tint: 0x2196f3 // blue }); // Container for text and bar var levelBarContainer = new Container(); // Kill counter text (will be placed to the right of the rocket) var killCounterText = new Text2("0", { size: 68, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", shadow: { color: 0x1976D2, blur: 8, offsetX: 0, offsetY: 2 } }); killCounterText.anchor.set(0, 0.5); // left anchor for right-of-rocket placement // Level number text (shows current level, right of 'Seviye') var levelNumberText = new Text2(level.toString(), { size: 68, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma", shadow: { color: 0x1976D2, blur: 8, offsetX: 0, offsetY: 2 } }); levelText.anchor.set(1, 0.5); levelNumberText.anchor.set(0, 0.5); // Place 'Seviye', then bar, then number (kill counter will be right of rocket, not in this container) levelText.x = 0; levelText.y = 0; var gapBetween = 24; // small gap between 'Seviye' and bar var barStartX = levelText.x + levelText.width + gapBetween; levelBarBg.x = barStartX; levelBar.x = barStartX; levelBarBg.y = 0; levelBar.y = 0; // Center the level number between 'Seviye' and the bar levelNumberText.x = barStartX / 2 + levelText.x / 2 - levelNumberText.width / 2; levelNumberText.y = 0; // Only add levelText, levelNumberText, levelBarBg, levelBar to container levelBarContainer.addChild(levelText); levelBarContainer.addChild(levelNumberText); levelBarContainer.addChild(levelBarBg); levelBarContainer.addChild(levelBar); // Position: move level bar container further left (reduce left margin) levelBarContainer.x = 10; levelBarContainer.y = 66; LK.gui.top.addChild(levelBarContainer); // Place kill counter to the right of the rocket, just above it killCounterText.x = typeof rocket !== "undefined" && rocket ? rocket.x + (rocket.width ? rocket.width / 2 : 70) + 32 : GAME_WIDTH / 2 + 140; killCounterText.y = typeof rocket !== "undefined" && rocket ? rocket.y - (rocket.height ? rocket.height / 2 : 110) - 40 : GAME_HEIGHT - 400 - 110 - 40; LK.gui.top.addChild(killCounterText); // Helper to update level bar and level text function updateLevelBar() { // Progress to next level: score % 10 (10 kills per level) var killsThisLevel = score % 10; if (killsThisLevel < 0) { killsThisLevel = 0; } if (killsThisLevel > 10) { killsThisLevel = 10; } // Each kill paints a segment of the bar var segmentCount = 10; var segmentWidth = 420 / segmentCount; // Match new bar width var targetWidth = segmentWidth * killsThisLevel; // Animate the level bar fill width to visually show progress if (typeof levelBar.lastWidth === "undefined") { levelBar.lastWidth = 0; } if (Math.abs(levelBar.width - targetWidth) > 2) { // Animate width smoothly if (!levelBar.widthTween) { levelBar.widthTween = tween(levelBar, { width: targetWidth }, { duration: 250, easing: tween.linear, onFinish: function onFinish() { levelBar.widthTween = null; levelBar.width = targetWidth; levelBar.lastWidth = targetWidth; } }); } } else { // Snap to target if very close if (levelBar.widthTween) { tween.stop(levelBar, { width: true }); levelBar.widthTween = null; } levelBar.width = targetWidth; levelBar.lastWidth = targetWidth; } // Color: fill blue on every kill levelBar.tint = 0x2196f3; // blue // Update level text (static, just "Seviye") if (typeof levelText !== "undefined") { levelText.setText("Seviye"); } // Update level number text to show current level if (typeof levelNumberText !== "undefined") { levelNumberText.setText(level.toString()); } } // Update level bar on score change and level up var oldUpdateScoreText = updateScoreText; updateLevelBar(); // Initial spawn spawnAlien(); // Play background music at game start LK.playMusic('Bckgrnd'); // Play background music at game start LK.playMusic('Bckgrnd');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Alien class
var Alien = Container.expand(function () {
var self = Container.call(this);
var alienAsset = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = alienAsset.width;
self.height = alienAsset.height;
self.hp = 2; // Each alien takes 2 hits (all aliens always 2 hits)
self.isHit = false;
self.hitTween = null;
// For hit flash
self.flash = function () {
// If a previous hitTween is running, stop it
if (self.hitTween) {
tween.stop(alienAsset, {
tint: true
});
}
// Set alien to red tint
alienAsset.tint = 0xff5252;
// Tween back to normal color (no tint) over 120ms
self.hitTween = tween(alienAsset, {
tint: 0xffffff
}, {
duration: 120,
easing: tween.linear,
onFinish: function onFinish() {
self.hitTween = null;
}
});
};
// For movement
self.speed = 8 + Math.random() * 4; // Slightly random speed
self.update = function () {
// Only move downwards, do not follow rocket's x position
self.y += self.speed;
};
return self;
});
// Bigger Alien class (for level > 3, 3 hits to kill, larger)
var BiggerAlien = Container.expand(function () {
var self = Container.call(this);
var alienAsset = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.width = alienAsset.width * 1.5;
self.height = alienAsset.height * 1.5;
self.hp = 2; // Takes 2 hits (all enemies always 2 hits)
self.isHit = false;
self.hitTween = null;
self.flash = function () {
if (self.hitTween) {
tween.stop(alienAsset, {
tint: true
});
}
alienAsset.tint = 0xff5252;
self.hitTween = tween(alienAsset, {
tint: 0xffffff
}, {
duration: 120,
easing: tween.linear,
onFinish: function onFinish() {
self.hitTween = null;
}
});
};
// For movement
self.speed = 10 + Math.random() * 2; // Slightly slower than strong alien
self.update = function () {
self.y += self.speed;
};
return self;
});
// Boss Alien class (for level 7)
var BossAlien = Container.expand(function () {
var self = Container.call(this);
var bossAsset = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.7,
scaleY: 1.7
});
self.width = bossAsset.width * 1.7;
self.height = bossAsset.height * 1.7;
self.hp = 2; // Boss takes 2 hits (all enemies always 2 hits)
self.isHit = false;
self.hitTween = null;
self.flash = function () {
if (self.hitTween) {
tween.stop(bossAsset, {
tint: true
});
}
bossAsset.tint = 0xff5252;
self.hitTween = tween(bossAsset, {
tint: 0xffffff
}, {
duration: 120,
easing: tween.linear,
onFinish: function onFinish() {
self.hitTween = null;
}
});
};
self.speed = 10; // Boss is faster
self.update = function () {
// Only move downwards, do not follow rocket's x position
self.y += self.speed;
};
return self;
});
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -32; // Upwards
self.power = bulletPower; // Set bullet power at creation
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy bullet class (alien shoots at player)
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletAsset.tint = 0xff5252; // Red tint for enemy bullets
self.speed = 27; // Downwards, 1.5x faster than before
self.update = function () {
self.y += self.speed;
};
return self;
});
// Rocket (player) class
var Rocket = Container.expand(function () {
var self = Container.call(this);
var rocketAsset = self.attachAsset('rocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = rocketAsset.width;
self.height = rocketAsset.height;
// For hit flash
self.flashTween = null;
// Show hit flash
self.flash = function () {
// If a previous flashTween is running, stop it
if (self.flashTween) {
tween.stop(rocketAsset, {
tint: true
});
}
// Set rocket to reddish tint
rocketAsset.tint = 0xff5252;
// Tween back to normal color (white) over 200ms
self.flashTween = tween(rocketAsset, {
tint: 0xffffff
}, {
duration: 200,
easing: tween.linear,
onFinish: function onFinish() {
self.flashTween = null;
}
});
};
return self;
});
// Star class for animated background stars
var Star = Container.expand(function () {
var self = Container.call(this);
// Use a larger ellipse for the star to make it more visible
var size = 6 + Math.random() * 8; // Increased min and max size
var starAsset = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size / 160,
scaleY: size / 160
});
// Brighter color choices for more visibility
var colorChoices = [0xffffff, 0xe3f2fd, 0xfffde7, 0xb3e5fc, 0xfff9c4];
starAsset.tint = colorChoices[Math.floor(Math.random() * colorChoices.length)];
self.width = size;
self.height = size;
self.speed = 2.5 + Math.random() * 4.5;
// Higher minimum alpha for more visible stars
self.alpha = 0.7 + Math.random() * 0.3;
self.update = function () {
self.y += self.speed;
if (self.y > GAME_HEIGHT + 10) {
// Respawn at top
self.y = -10;
self.x = 10 + Math.random() * (GAME_WIDTH - 20);
self.speed = 2.5 + Math.random() * 4.5;
self.alpha = 0.7 + Math.random() * 0.3;
}
};
return self;
});
// Strong Alien class (tougher, faster)
var StrongAlien = Container.expand(function () {
var self = Container.call(this);
var alienAsset = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
self.width = alienAsset.width * 1.2;
self.height = alienAsset.height * 1.2;
self.hp = 2; // Strong alien takes 2 hits (all enemies always 2 hits)
self.isHit = false;
self.hitTween = null;
self.flash = function () {
if (self.hitTween) {
tween.stop(alienAsset, {
tint: true
});
}
alienAsset.tint = 0xff5252;
self.hitTween = tween(alienAsset, {
tint: 0xffffff
}, {
duration: 120,
easing: tween.linear,
onFinish: function onFinish() {
self.hitTween = null;
}
});
};
// For movement
self.speed = 12 + Math.random() * 3; // Stronger and faster
self.update = function () {
// Only move downwards, do not follow rocket's x position
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game constants
// Rocket (player)
// Alien (enemy)
// Bullet
// Alien hit flash
// Life bar
// Life bar background
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// --- Kill Counter (top right) ---
var killNumberText = new Text2("0", {
size: 68,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
shadow: {
color: 0x1976D2,
blur: 8,
offsetX: 0,
offsetY: 2
}
});
killNumberText.anchor.set(1, 0); // right anchor, top edge
killNumberText.x = GAME_WIDTH - 40;
killNumberText.y = 40;
LK.gui.top.addChild(killNumberText);
// --- Starfield background ---
var stars = [];
var STAR_COUNT = 60;
for (var i = 0; i < STAR_COUNT; ++i) {
var star = new Star();
star.x = 10 + Math.random() * (GAME_WIDTH - 20);
star.y = Math.random() * GAME_HEIGHT;
stars.push(star);
game.addChildAt(star, 0); // Add behind all other objects
}
var ROCKET_START_LIFE = 5;
var LEVEL_TO_BOSS = 7;
// Game state
var rocket = null;
var bullets = [];
var aliens = [];
var level = 1;
var rocketLife = ROCKET_START_LIFE;
var bulletPower = 1; // Bullet power, increases every level
var canShoot = true;
var shootCooldown = 0;
var dragNode = null;
var lastMoveX = 0;
var lastMoveY = 0;
var score = 0;
var bossSpawned = false;
var enemyBullets = []; // Track enemy bullets
// --- Shield state for rocket ---
var rocketShieldActive = false;
var rocketShieldTimer = 0;
var rocketShieldVisual = null;
// GUI elements
var scoreTxt = new Text2('0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 1);
// Ensure score is always visible
scoreTxt.alpha = 1;
scoreTxt.visible = true;
// Position the score text horizontally aligned with the rocket, above it
scoreTxt.x = GAME_WIDTH / 2;
scoreTxt.y = GAME_HEIGHT - 400 - (rocket ? rocket.height / 2 : 110) - 40; // 40px above rocket top, fallback if rocket not yet created
LK.gui.top.addChild(scoreTxt);
if (LK.gui.top.children && LK.gui.top.children.length > 1) {
LK.gui.top.setChildIndex(scoreTxt, LK.gui.top.children.length - 1);
}
// New health bar will be created below
// updateLevelBar and updateLevelText helpers removed as level bar is no longer shown
// Helper to update score text
function updateScoreText() {
scoreTxt.setText(score);
// Update kill counter text (if defined)
if (typeof killCounterText !== "undefined") {
killCounterText.setText(score.toString());
}
// Update kill number text (top right)
if (typeof killNumberText !== "undefined") {
killNumberText.setText(score.toString());
}
// Update health bar kill counter text (if defined)
if (typeof healthBarKillCounterText !== "undefined") {
healthBarKillCounterText.setText(score.toString());
}
// Update rocket kill counter text (above rocket)
if (typeof rocketKillCounterText !== "undefined") {
rocketKillCounterText.setText(score.toString());
}
// updateLevelBar removed
}
// Spawn a new alien
function spawnAlien() {
var alien;
if (level === LEVEL_TO_BOSS && !bossSpawned) {
alien = new BossAlien();
alien.hp = 2; // Boss always 2 hits
bossSpawned = true;
} else {
// 20% chance to spawn a BiggerAlien after level 3, 30% StrongAlien, otherwise normal Alien
if (level > 3 && Math.random() < 0.2) {
alien = new BiggerAlien();
alien.hp = 2; // Always 2 hits for bigger alien
} else if (Math.random() < 0.3 && level > 2) {
alien = new StrongAlien();
alien.hp = 2; // Always 2 hits for strong alien
} else {
alien = new Alien();
alien.hp = 2; // Always 2 hits for normal alien
}
}
// Defensive: always set hp to 2 for all enemy types
if (alien) {
alien.hp = 2;
// 1. seviyede düşmanlar 1.5 kat hızlı gelsin
if (level === 1 && typeof alien.speed === "number") {
alien.speed *= 1.5;
}
}
// Random x, but keep inside screen
var margin = 120;
alien.x = margin + Math.random() * (GAME_WIDTH - margin * 2);
alien.y = -alien.height / 2;
aliens.push(alien);
game.addChild(alien);
}
// Reset game state
function resetGame() {
// Remove all bullets and aliens
for (var i = 0; i < bullets.length; ++i) {
bullets[i].destroy();
}
for (var j = 0; j < aliens.length; ++j) {
aliens[j].destroy();
}
for (var k = 0; k < enemyBullets.length; ++k) {
enemyBullets[k].destroy();
}
bullets = [];
aliens = [];
enemyBullets = [];
level = 1;
rocketLife = ROCKET_START_LIFE;
bulletPower = 1; // Always 1, so all enemies take 2 hits
canShoot = true;
shootCooldown = 0;
dragNode = null;
lastMoveX = 0;
lastMoveY = 0;
score = 0;
bossSpawned = false;
// updateLevelText and updateLevelBar removed
updateScoreText();
updateLevelBar();
updateHealthBar();
}
// Initialize rocket
rocket = new Rocket();
rocket.x = GAME_WIDTH / 2;
rocket.y = GAME_HEIGHT - 400;
game.addChild(rocket);
// --- Rocket health bar that follows rocket ---
var rocketLifeBarBg = LK.getAsset('lifeBarBg', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 0,
width: 220,
height: 18
});
var rocketLifeBar = LK.getAsset('lifeBar', {
anchorX: 0,
anchorY: 0,
x: -110,
y: 0,
width: 220,
height: 18
});
var rocketLifeBarContainer = new Container();
rocketLifeBarContainer.addChild(rocketLifeBarBg);
rocketLifeBarContainer.addChild(rocketLifeBar);
rocketLifeBarContainer.x = rocket.x;
rocketLifeBarContainer.y = rocket.y + rocket.height / 2 + 12; // 12px below rocket
game.addChild(rocketLifeBarContainer);
// Move scoreTxt to be above the rocket, horizontally aligned
scoreTxt.x = rocket.x;
scoreTxt.y = rocket.y - rocket.height / 2 - 40; // 40px above rocket top
// --- Kill Counter above Rocket ---
// Create kill counter text to be placed above the rocket
var rocketKillCounterText = new Text2("0", {
size: 54,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
shadow: {
color: 0x1976D2,
blur: 8,
offsetX: 0,
offsetY: 2
}
});
rocketKillCounterText.anchor.set(0.5, 1); // center anchor, bottom edge
rocketKillCounterText.x = rocket.x;
rocketKillCounterText.y = rocket.y - rocket.height / 2 - 60; // 60px above rocket top
game.addChild(rocketKillCounterText);
// --- New Health Bar (top center) ---
var healthBarBg = LK.getAsset('lifeBarBg', {
anchorX: 0.5,
anchorY: 0.5,
width: 440,
height: 44,
x: 0,
y: 0
});
var healthBar = LK.getAsset('lifeBar', {
anchorX: 0,
anchorY: 0.5,
width: 400,
height: 36,
x: -200,
y: 0
});
var healthBarContainer = new Container();
healthBarContainer.addChild(healthBarBg);
healthBarContainer.addChild(healthBar);
healthBarContainer.x = GAME_WIDTH / 2;
healthBarContainer.y = 110;
LK.gui.top.addChild(healthBarContainer);
// --- Kill Counter below Health Bar (top center) ---
var healthBarKillCounterText = new Text2("0", {
size: 54,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
shadow: {
color: 0x1976D2,
blur: 8,
offsetX: 0,
offsetY: 2
}
});
healthBarKillCounterText.anchor.set(0.5, 0); // center anchor, top edge
healthBarKillCounterText.x = GAME_WIDTH / 2;
healthBarKillCounterText.y = healthBarContainer.y + 32; // just below health bar
LK.gui.top.addChild(healthBarKillCounterText);
// Helper to update health bar
function updateHealthBar() {
var percent = rocketLife / ROCKET_START_LIFE;
if (percent < 0) {
percent = 0;
}
if (percent > 1) {
percent = 1;
}
healthBar.width = 400 * percent;
if (percent > 0.5) {
healthBar.tint = 0x43a047;
} else if (percent > 0.2) {
healthBar.tint = 0xffc107;
} else {
healthBar.tint = 0xd32f2f;
}
}
// Initial GUI
// updateLevelText and updateLevelBar removed
updateScoreText();
updateHealthBar();
// Touch/move controls
game.down = function (x, y, obj) {
// Only start drag if touch is on rocket
var local = rocket.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x > -rocket.width / 2 && local.x < rocket.width / 2 && local.y > -rocket.height / 2 && local.y < rocket.height / 2) {
dragNode = rocket;
lastMoveX = x;
lastMoveY = y;
}
};
game.move = function (x, y, obj) {
// Always move the rocket to the mouse/touch position, clamped to screen
var newX = x;
var halfW = rocket && rocket.width ? rocket.width / 2 : 70; // fallback to 70 if rocket is null
if (newX < halfW) {
newX = halfW;
}
if (newX > GAME_WIDTH - halfW) {
newX = GAME_WIDTH - halfW;
}
if (rocket) {
rocket.x = newX;
// Y position stays fixed at the starting Y
rocket.y = GAME_HEIGHT - 400;
}
lastMoveX = x;
lastMoveY = y;
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Tap to shoot (left mouse button or tap)
game.down = function (x, y, obj) {
// Only start drag if touch is on rocket
var local = rocket.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x > -rocket.width / 2 && local.x < rocket.width / 2 && local.y > -rocket.height / 2 && local.y < rocket.height / 2) {
dragNode = rocket;
lastMoveX = x;
lastMoveY = y;
}
// Always allow shooting with left mouse button/tap, regardless of drag state
if (canShoot) {
shootBullet();
}
};
// Shoot bullet
function shootBullet() {
if (!canShoot) {
return;
}
var bullet = new Bullet();
bullet.x = rocket.x;
bullet.y = rocket.y - rocket.height / 2 - 20;
bullets.push(bullet);
game.addChild(bullet);
// Play laser gun sound effect
LK.getSound('dfds').play();
canShoot = false;
shootCooldown = 10; // 10 ticks cooldown
}
// Main update loop
game.update = function () {
// Shooting cooldown
if (!canShoot) {
shootCooldown--;
if (shootCooldown <= 0) {
canShoot = true;
}
}
// --- Shield logic update ---
if (rocketShieldActive) {
rocketShieldTimer--;
// Keep shield visual in sync with rocket
if (rocket && rocketShieldVisual && rocket.children.indexOf(rocketShieldVisual) === -1) {
rocket.addChild(rocketShieldVisual);
if (rocket.children.length > 1) {
rocket.setChildIndex(rocketShieldVisual, 0);
}
}
if (rocketShieldTimer <= 0) {
rocketShieldActive = false;
rocketShieldTimer = 0;
// Remove shield visual
if (rocketShieldVisual && rocket) {
rocket.removeChild(rocketShieldVisual);
}
rocketShieldVisual = null;
}
} else {
// Defensive: remove shield visual if not active
if (rocketShieldVisual && rocket) {
rocket.removeChild(rocketShieldVisual);
rocketShieldVisual = null;
}
}
// Update stars
for (var si = 0; si < stars.length; ++si) {
stars[si].update();
}
// Keep score counter aligned with rocket
scoreTxt.x = rocket.x;
scoreTxt.y = rocket.y - rocket.height / 2 - 40; // 40px above rocket top
// Move rocket kill counter above rocket
if (typeof rocketKillCounterText !== "undefined" && rocket) {
rocketKillCounterText.x = rocket.x;
rocketKillCounterText.y = rocket.y - rocket.height / 2 - 60;
}
// Move kill counter to the right of the rocket, just above it
if (typeof killCounterText !== "undefined" && rocket) {
killCounterText.x = rocket.x + rocket.width / 2 + 32;
killCounterText.y = rocket.y - rocket.height / 2 - 40;
}
// Move rocket health bar with rocket
if (typeof rocketLifeBarContainer !== "undefined") {
rocketLifeBarContainer.x = rocket.x;
rocketLifeBarContainer.y = rocket.y + rocket.height / 2 + 12; // 12px below rocket
// Update width and color
var percent = rocketLife / ROCKET_START_LIFE;
if (percent < 0) {
percent = 0;
}
rocketLifeBar.width = 220 * percent;
if (percent > 0.5) {
rocketLifeBar.tint = 0x43a047;
} else if (percent > 0.2) {
rocketLifeBar.tint = 0xffc107;
} else {
rocketLifeBar.tint = 0xd32f2f;
}
// Do NOT change rocket color based on health
}
// (level bar stays fixed in GUI, do not move with rocket)
// Update bullets
for (var i = bullets.length - 1; i >= 0; --i) {
var b = bullets[i];
b.update();
// Remove if off screen
if (b.y < -100) {
b.destroy();
bullets.splice(i, 1);
continue;
}
}
// Update aliens
for (var j = aliens.length - 1; j >= 0; --j) {
var a = aliens[j];
a.update();
// Remove if off screen
if (a.y > GAME_HEIGHT + 200) {
a.destroy();
aliens.splice(j, 1);
continue;
}
// Alien shooting logic: all aliens shoot every eligible tick (no randomness, no alignment check)
if (level > 1 && a.y > 0 && a.y < GAME_HEIGHT - 400) {
if (LK.ticks % Math.max(60 - level * 4, 18) === 0) {
if (level >= 5) {
// Shoot two bullets, slightly offset horizontally
var offset = 38;
for (var bidx = -1; bidx <= 1; bidx += 2) {
var enemyBullet = new EnemyBullet();
enemyBullet.x = a.x + bidx * offset;
enemyBullet.y = a.y + a.height / 2 + 10;
enemyBullets.push(enemyBullet);
game.addChild(enemyBullet);
}
} else {
// Shoot one bullet as before
var enemyBullet = new EnemyBullet();
enemyBullet.x = a.x;
enemyBullet.y = a.y + a.height / 2 + 10;
enemyBullets.push(enemyBullet);
game.addChild(enemyBullet);
}
}
}
// Check collision with rocket (alien-rocket contact)
if (a.intersects(rocket)) {
if (!rocketShieldActive && rocketLife > 0) {
rocketLife--;
updateHealthBar();
rocket.flash();
// Destroy rocket if it has taken 5 damage
if (rocketLife <= 0) {
// Play rocket explosion sound when rocket's life reaches zero
LK.getSound('patlama').play();
if (rocket && typeof rocket.destroy === "function") {
rocket.destroy();
rocket = null;
}
}
}
// Remove alien on contact
a.destroy();
aliens.splice(j, 1);
// Check for game over
if (rocketLife <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('patlama').play();
LK.showGameOver();
return;
}
}
// No alien-rocket collision: aliens do not damage rocket by contact
}
// Update enemy bullets
for (var eb = enemyBullets.length - 1; eb >= 0; --eb) {
var ebull = enemyBullets[eb];
ebull.update();
// Remove if off screen
if (ebull.y > GAME_HEIGHT + 100) {
ebull.destroy();
enemyBullets.splice(eb, 1);
continue;
}
// Check collision with rocket
if (ebull.intersects(rocket)) {
if (!rocketShieldActive && rocketLife > 0) {
if (level >= 6) {
rocketLife = 0;
} else {
rocketLife -= 0.5;
}
updateHealthBar();
rocket.flash();
// Destroy rocket if it has taken 5 damage
if (rocketLife <= 0) {
if (rocket && typeof rocket.destroy === "function") {
// Play rocket explosion sound
LK.getSound('patlama').play();
rocket.destroy();
rocket = null;
}
}
}
ebull.destroy();
enemyBullets.splice(eb, 1);
// Check for game over
if (rocketLife <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
// Bullet-alien collisions
for (var i2 = bullets.length - 1; i2 >= 0; --i2) {
var b2 = bullets[i2];
for (var j2 = aliens.length - 1; j2 >= 0; --j2) {
var a2 = aliens[j2];
if (b2.intersects(a2)) {
a2.hp -= b2.power !== undefined ? b2.power : 1; // Use bullet power, fallback to 1
a2.flash();
b2.destroy();
bullets.splice(i2, 1);
if (a2.hp <= 0) {
a2.destroy();
aliens.splice(j2, 1);
score++;
updateScoreText();
updateLevelBar();
// Increase level every 10 kills
if (level < LEVEL_TO_BOSS && score % 10 === 0) {
level++;
// Flash the screen to indicate level up
LK.effects.flashScreen(0xffffff, 600); // White flash for 600ms
// Activate 4s shield when reaching level 3
if (level === 3) {
rocketShieldActive = true;
rocketShieldTimer = 240; // 4 seconds at 60 FPS
// Add shield visual if not present
if (!rocketShieldVisual && rocket) {
rocketShieldVisual = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.1,
scaleY: 2.1,
x: 0,
y: 0,
color: 0x2196f3,
tint: 0x2196f3
});
rocketShieldVisual.alpha = 0.38;
rocket.addChild(rocketShieldVisual);
// Make sure shield is behind rocket sprite
if (rocket.children.length > 1) {
rocket.setChildIndex(rocketShieldVisual, 0);
}
}
}
// End game after level 6 (when level becomes 7)
if (level === LEVEL_TO_BOSS) {
LK.effects.flashScreen(0x00e676, 1000);
LK.showYouWin();
return;
}
bulletPower = 1; // Always 1, so all enemies take 2 hits
rocketLife = ROCKET_START_LIFE; // Full heal on level up
updateHealthBar();
updateLevelBar();
// Star explosion effect at center of screen
for (var sx = 0; sx < 18; ++sx) {
(function (sx) {
var star = new Star();
star.x = GAME_WIDTH / 2;
star.y = GAME_HEIGHT / 2;
// Give each star a random direction and speed
var angle = Math.PI * 2 * (sx / 18);
var speed = 18 + Math.random() * 12;
var vx = Math.cos(angle) * speed;
var vy = Math.sin(angle) * speed;
var life = 32 + Math.floor(Math.random() * 16);
var tick = 0;
// Animate star outward and fade out
star.update = function () {
star.x += vx;
star.y += vy;
star.alpha -= 0.025;
tick++;
if (tick > life || star.alpha <= 0) {
star.destroy();
}
};
game.addChild(star);
})(sx);
}
// Change all background star colors
var colorChoices = [0xffffff, 0xe3f2fd, 0xfffde7, 0xb3e5fc, 0xfff9c4, 0xffb3c6, 0xc5e1a5, 0xffcc80, 0x90caf9, 0xf8bbd0];
for (var sc = 0; sc < stars.length; ++sc) {
var starObj = stars[sc];
// Only change tint if starObj has children and a valid asset
if (starObj.children && starObj.children.length > 0 && starObj.children[0]) {
var newColor = colorChoices[Math.floor(Math.random() * colorChoices.length)];
starObj.children[0].tint = newColor;
}
}
// Add more stars to the background on each level up
var additionalStars = 8; // Number of stars to add per level up
for (var addStar = 0; addStar < additionalStars; ++addStar) {
var newStar = new Star();
newStar.x = 10 + Math.random() * (GAME_WIDTH - 20);
newStar.y = Math.random() * GAME_HEIGHT;
stars.push(newStar);
game.addChildAt(newStar, 0); // Add behind all other objects
}
}
// If boss defeated, win
if (level === LEVEL_TO_BOSS && bossSpawned && aliens.length === 0) {
LK.effects.flashScreen(0x00e676, 1000);
LK.showYouWin();
return;
}
}
break;
}
}
}
// Alien spawn logic
if (level < LEVEL_TO_BOSS) {
// Increase max aliens on screen as level increases
var maxAliens = 2 + Math.floor((level - 1) / 2); // +1 every 2 levels (2,3,4,5...)
// Double the number of aliens on level 5 and above
if (level >= 5) {
maxAliens *= 2;
}
// Increase spawn rate as level increases
var spawnRate = Math.max(1, 1 + Math.floor((level - 1) / 2)); // +1 spawn per 2 levels
if (level >= 5) {
spawnRate *= 2;
}
if (aliens.length < maxAliens && LK.ticks % (60 - level * 4) === 0) {
for (var s = 0; s < spawnRate && aliens.length < maxAliens; ++s) {
spawnAlien();
}
}
} else if (level === LEVEL_TO_BOSS && !bossSpawned) {
// Spawn boss
spawnAlien();
}
};
// --- Level Bar (next to Seviye text) ---
// Level text
var levelText = new Text2("Seviye", {
size: 68,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
shadow: {
color: 0x1976D2,
blur: 8,
offsetX: 0,
offsetY: 2
}
});
levelText.anchor.set(1, 0.5);
// Level bar background
var levelBarBg = LK.getAsset('lifeBarBg', {
anchorX: 0,
anchorY: 0.5,
width: 420,
height: 64,
x: 0,
y: 0
});
// Level bar fill (fills with each kill)
var levelBar = LK.getAsset('centerCircle', {
anchorX: 0,
anchorY: 0.5,
width: 420,
height: 48,
x: 0,
y: 0,
color: 0x2196f3,
tint: 0x2196f3 // blue
});
// Container for text and bar
var levelBarContainer = new Container();
// Kill counter text (will be placed to the right of the rocket)
var killCounterText = new Text2("0", {
size: 68,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
shadow: {
color: 0x1976D2,
blur: 8,
offsetX: 0,
offsetY: 2
}
});
killCounterText.anchor.set(0, 0.5); // left anchor for right-of-rocket placement
// Level number text (shows current level, right of 'Seviye')
var levelNumberText = new Text2(level.toString(), {
size: 68,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma",
shadow: {
color: 0x1976D2,
blur: 8,
offsetX: 0,
offsetY: 2
}
});
levelText.anchor.set(1, 0.5);
levelNumberText.anchor.set(0, 0.5);
// Place 'Seviye', then bar, then number (kill counter will be right of rocket, not in this container)
levelText.x = 0;
levelText.y = 0;
var gapBetween = 24; // small gap between 'Seviye' and bar
var barStartX = levelText.x + levelText.width + gapBetween;
levelBarBg.x = barStartX;
levelBar.x = barStartX;
levelBarBg.y = 0;
levelBar.y = 0;
// Center the level number between 'Seviye' and the bar
levelNumberText.x = barStartX / 2 + levelText.x / 2 - levelNumberText.width / 2;
levelNumberText.y = 0;
// Only add levelText, levelNumberText, levelBarBg, levelBar to container
levelBarContainer.addChild(levelText);
levelBarContainer.addChild(levelNumberText);
levelBarContainer.addChild(levelBarBg);
levelBarContainer.addChild(levelBar);
// Position: move level bar container further left (reduce left margin)
levelBarContainer.x = 10;
levelBarContainer.y = 66;
LK.gui.top.addChild(levelBarContainer);
// Place kill counter to the right of the rocket, just above it
killCounterText.x = typeof rocket !== "undefined" && rocket ? rocket.x + (rocket.width ? rocket.width / 2 : 70) + 32 : GAME_WIDTH / 2 + 140;
killCounterText.y = typeof rocket !== "undefined" && rocket ? rocket.y - (rocket.height ? rocket.height / 2 : 110) - 40 : GAME_HEIGHT - 400 - 110 - 40;
LK.gui.top.addChild(killCounterText);
// Helper to update level bar and level text
function updateLevelBar() {
// Progress to next level: score % 10 (10 kills per level)
var killsThisLevel = score % 10;
if (killsThisLevel < 0) {
killsThisLevel = 0;
}
if (killsThisLevel > 10) {
killsThisLevel = 10;
}
// Each kill paints a segment of the bar
var segmentCount = 10;
var segmentWidth = 420 / segmentCount; // Match new bar width
var targetWidth = segmentWidth * killsThisLevel;
// Animate the level bar fill width to visually show progress
if (typeof levelBar.lastWidth === "undefined") {
levelBar.lastWidth = 0;
}
if (Math.abs(levelBar.width - targetWidth) > 2) {
// Animate width smoothly
if (!levelBar.widthTween) {
levelBar.widthTween = tween(levelBar, {
width: targetWidth
}, {
duration: 250,
easing: tween.linear,
onFinish: function onFinish() {
levelBar.widthTween = null;
levelBar.width = targetWidth;
levelBar.lastWidth = targetWidth;
}
});
}
} else {
// Snap to target if very close
if (levelBar.widthTween) {
tween.stop(levelBar, {
width: true
});
levelBar.widthTween = null;
}
levelBar.width = targetWidth;
levelBar.lastWidth = targetWidth;
}
// Color: fill blue on every kill
levelBar.tint = 0x2196f3; // blue
// Update level text (static, just "Seviye")
if (typeof levelText !== "undefined") {
levelText.setText("Seviye");
}
// Update level number text to show current level
if (typeof levelNumberText !== "undefined") {
levelNumberText.setText(level.toString());
}
}
// Update level bar on score change and level up
var oldUpdateScoreText = updateScoreText;
updateLevelBar();
// Initial spawn
spawnAlien();
// Play background music at game start
LK.playMusic('Bckgrnd');
// Play background music at game start
LK.playMusic('Bckgrnd');