User prompt
oyuncunun uçağının hareketi biraz daha hızlı olsun ama çok değil
User prompt
sadece bazıları coin düşürsün onları topladığımızda eklensin
User prompt
coinler bazılarından 1 tane çıksın daha fazla çıkmasın
User prompt
ekranın sol altına farklı bir sayaç ekleyelim bu sayaç için Bazı uçaklar coin taşısın ve biz onları vurduğumuzda, coin bakiyemiz kalıcı olarak ekranın sol alt köşesine eklensin. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
The green enemy's bullets should be faster
User prompt
The green enemy's bullets should be slowe
User prompt
make playes plane faster
User prompt
The plane should smoothly and quickly follow the mouse cursor’s position in real-time, without reacting to mouse clicks or moving directly to the clicked location.
User prompt
The player's plane is controlled by the mouse and should continuously follow the position of the cursor on the screen
User prompt
plane was gone and there is no main menu 1 get back air plane 2 make starter menu and put a start button to game start
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'if (Math.abs(self.x - player.x) < 80 && self.shootCooldown <= 0) {' Line Number: 102
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'update')' in or related to this line: 'player.update();' Line Number: 516
User prompt
add main menu
User prompt
make game slower
Code edit (1 edits merged)
Please save this source code
User prompt
Aces of Color: Air Combat Evolution
Initial prompt
In this game, the player takes control of a customizable combat aircraft and engages in fast-paced aerial battles against waves of enemy planes, each uniquely colored and possessing distinct abilities. The core gameplay revolves around maneuvering your plane, avoiding incoming attacks, and strategically destroying enemy aircraft to earn points and progress. Each enemy plane is color-coded to indicate its special behavior or trait. For example: Red planes are aggressive and capable of firing projectiles at the player. Blue planes are extremely fast and harder to hit, requiring quick reflexes. Additional colors may represent other unique characteristics such as defensive shields, evasive movement patterns, or explosive self-destruct attacks. As the player eliminates enemy planes, they earn points. The number of points awarded depends on the color (and therefore difficulty) of the enemy destroyed — each color has a fixed point value. Precision, timing, and strategic targeting will be key to maximizing your score. The player's own aircraft has a health bar and takes damage when hit by enemy fire or when colliding with enemy planes. If the health bar reaches zero, the game ends. At the end of each run, the total score is calculated and converted into an in-game currency. The exchange rate is fixed — for example, every 10 points earned equals 1 unit of currency. This currency can be used in the main menu to: Upgrade the aircraft (e.g., increase speed, firepower, health, or special abilities) Unlock and equip new skins to personalize the look of the plane. The goal is not only to survive and achieve high scores, but also to continuously improve your plane and experiment with different styles and builds, making each playthrough feel fresh and rewarding.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currency: 0, unlockedSkins: ["default"], selectedSkin: "default", upgrades: { fireRate: 0, speed: 0, health: 0 } }); /**** * Classes ****/ // CoinDrop: Collectible coin that moves down and can be picked up by the player var CoinDrop = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.1, scaleY: 1.1 }); self.width = asset.width; self.height = asset.height; self.speed = 7; self.lastWasIntersecting = false; self.update = function () { self.y += self.speed; }; return self; }); // Enemy Base Class var EnemyBase = Container.expand(function () { var self = Container.call(this); self.type = 'base'; self.scoreValue = 1; self.health = 1; self.shootCooldown = 0; self.shootRate = 90; self.speed = 4; self.bulletSpeed = 12; self.lastIntersecting = false; self.lastY = 0; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { LK.getSound('enemyExplode').play(); LK.effects.flashObject(self, 0xffff00, 400); // Explosion effect (yellow flash) LK.setScore(LK.getScore() + self.scoreValue); addCurrency(self.scoreValue); showScorePopup(self.x, self.y, self.scoreValue); // Spawn debris parts for (var i = 0; i < 8; i++) { var part = new EnemyPart(); part.x = self.x; part.y = self.y; game.addChild(part); enemyParts.push(part); } // Only CoinEnemy drops a coin, so do not drop a coin here for base enemies self.destroy(); return true; } return false; }; self.shoot = function () { if (self.shootCooldown > 0) return; var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + self.height / 2; // If this is a green enemy, make its bullets faster if (self.type === 'green') { bullet.speed = 14; } enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('enemyShoot').play(); self.shootCooldown = self.shootRate; }; self.update = function () { self.y += self.speed; if (self.shootCooldown > 0) self.shootCooldown--; }; return self; }); // Red Attacker: moves straight, shoots at player var EnemyRed = EnemyBase.expand(function () { var self = EnemyBase.call(this); self.type = 'red'; self.scoreValue = 2; self.health = 1; self.shootRate = 80; self.speed = 6; self.asset = self.attachAsset('enemyRed', { anchorX: 0.5, anchorY: 0.5 }); self.width = self.asset.width; self.height = self.asset.height; self.update = function () { self.y += self.speed; if (self.shootCooldown > 0) self.shootCooldown--; // Shoot if player is roughly aligned if (Math.abs(self.x - player.x) < 80 && self.shootCooldown <= 0) { self.shoot(); } }; return self; }); // Green Tank: slow, high health, shoots var EnemyGreen = EnemyBase.expand(function () { var self = EnemyBase.call(this); self.type = 'green'; self.scoreValue = 5; self.health = 3; // reduced from 6 to 3 self.shootRate = 60; self.speed = 3.5; self.asset = self.attachAsset('enemyGreen', { anchorX: 0.5, anchorY: 0.5 }); self.width = self.asset.width; self.height = self.asset.height; self.update = function () { self.y += self.speed; if (self.shootCooldown > 0) self.shootCooldown--; // Shoots more often if (self.shootCooldown <= 0) { self.shoot(); } }; return self; }); // Blue Speedster: zig-zags, no shooting var EnemyBlue = EnemyBase.expand(function () { var self = EnemyBase.call(this); self.type = 'blue'; self.scoreValue = 3; self.health = 1; self.shootRate = 9999; self.speed = 8; self.asset = self.attachAsset('enemyBlue', { anchorX: 0.5, anchorY: 0.5 }); self.width = self.asset.width; self.height = self.asset.height; self.zigzagDir = Math.random() > 0.5 ? 1 : -1; self.zigzagSpeed = 7 + Math.random() * 3; self.zigzagPhase = Math.random() * 100; self.update = function () { self.y += self.speed; self.x += Math.sin((LK.ticks + self.zigzagPhase) / 18) * self.zigzagSpeed * self.zigzagDir; }; return self; }); // CoinEnemy: Enemies that carry a coin and drop it when destroyed var CoinEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this); self.type = 'coin'; self.scoreValue = 2; self.health = 1; self.shootRate = 120; self.speed = 5; self.asset = self.attachAsset('enemyRed', { anchorX: 0.5, anchorY: 0.5 }); self.width = self.asset.width; self.height = self.asset.height; // Add a coin icon on top of the enemy self.coinIcon = self.attachAsset('coin', { anchorX: 0.5, anchorY: 1.2, scaleX: 0.7, scaleY: 0.7 }); // Override takeDamage to drop a coin self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { LK.getSound('enemyExplode').play(); LK.effects.flashObject(self, 0xffff00, 400); // Explosion effect (yellow flash) LK.setScore(LK.getScore() + self.scoreValue); showScorePopup(self.x, self.y, self.scoreValue); // Spawn debris parts for (var i = 0; i < 8; i++) { var part = new EnemyPart(); part.x = self.x; part.y = self.y; game.addChild(part); enemyParts.push(part); } // Drop a coin at this position, but only once if (!self._coinDropped) { var coin = new CoinDrop(); coin.x = self.x; coin.y = self.y; coinDrops.push(coin); game.addChild(coin); self._coinDropped = true; } self.destroy(); return true; } return false; }; self.update = function () { self.y += self.speed; if (self.shootCooldown > 0) self.shootCooldown--; }; return self; }); // Enemy Bullet var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bullet.width; self.height = bullet.height; self.speed = 8; self.update = function () { self.y += self.speed; }; return self; }); // EnemyPart: Debris piece for enemy explosion var EnemyPart = Container.expand(function () { var self = Container.call(this); // Use a greenCube for debris, but only red and orange colors var colors = [0xff4444, 0xff9900]; var color = colors[Math.floor(Math.random() * colors.length)]; var part = self.attachAsset('greenCube', { anchorX: 0.5, anchorY: 0.5 }); part.tint = color; // Randomize size var scale = 0.4 + Math.random() * 0.5; part.scaleX = scale; part.scaleY = scale; self.width = part.width * scale; self.height = part.height * scale; // Set initial velocity self.vx = (Math.random() - 0.5) * 32; self.vy = (Math.random() - 0.5) * 32 - 8; self.gravity = 2.2 + Math.random() * 0.8; self.life = 36 + Math.floor(Math.random() * 18); // 0.6s self._age = 0; self.update = function () { self.x += self.vx; self.y += self.vy; self.vy += self.gravity; self._age++; // Fade out part.alpha = Math.max(0, 1 - self._age / self.life); if (self._age > self.life) { self.destroy(); } }; return self; }); // Player Bullet var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bullet.width; self.height = bullet.height; self.speed = -8 - (storage.upgrades && storage.upgrades.fireRate ? storage.upgrades.fireRate * 1 : 0); // Slowed down from -12 to -8 self.update = function () { self.y += self.speed; }; return self; }); // Player Plane var PlayerPlane = Container.expand(function () { var self = Container.call(this); // Attach player plane asset self.skin = storage.selectedSkin || 'default'; self.plane = self.attachAsset('playerPlane', { anchorX: 0.5, anchorY: 0.5 }); self.width = self.plane.width; self.height = self.plane.height; self.fireCooldown = 0; self.baseFireRate = 30; // ticks between shots self.baseSpeed = 32; // Increased from 23 for faster movement self.baseHealth = 8; // Increased from 5 to 8 for more player lives self.maxHealth = self.baseHealth + (storage.upgrades && storage.upgrades.health ? storage.upgrades.health : 0); self.health = self.maxHealth; self.updateSkin = function () { // For future: swap asset based on skin // For now, only color changes if (self.skin === 'default') { self.plane.tint = 0x888888; } else if (self.skin === 'gold') { self.plane.tint = 0xffd700; } else if (self.skin === 'blue') { self.plane.tint = 0x2a6edb; } }; self.shoot = function () { if (self.fireCooldown > 0) return; var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - self.height / 2 + 10; playerBullets.push(bullet); game.addChild(bullet); LK.getSound('playerShoot').play(); self.fireCooldown = self.baseFireRate - (storage.upgrades && storage.upgrades.fireRate ? storage.upgrades.fireRate * 4 : 0); if (self.fireCooldown < 8) self.fireCooldown = 8; }; self.takeDamage = function (amount) { self.health -= amount; if (self.health < 0) self.health = 0; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('playerHit').play(); updateHealthBar(); if (self.health <= 0) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } }; self.heal = function (amount) { self.health += amount; if (self.health > self.maxHealth) self.health = self.maxHealth; updateHealthBar(); }; self.update = function () { if (self.fireCooldown > 0) self.fireCooldown--; }; self.updateSkin(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundImage: 'spaceMoonBg' }); /**** * Game Code ****/ // --- Global Variables --- // Player plane (default skin: gray) // Player bullet (yellow) // Enemy: Red Attacker // Enemy: Blue Speedster // Enemy: Green Tank // Enemy bullet (red) // Health bar background // Health bar foreground // Coin icon // Sounds // Music var player; var playerBullets = []; var enemies = []; var enemyBullets = []; var coinDrops = []; var enemyParts = []; var spawnTimer = 0; var spawnInterval = 60; var dragNode = null; var lastPlayerX = 0; var lastPlayerY = 0; var healthBarBg, healthBarFg; var scoreTxt, coinTxt, coinIcon; var currency = storage.currency || 0; // Track how many enemies have been destroyed for health bonus var enemiesDestroyedSinceLastHeal = 0; // --- GUI Elements --- // --- Start Screen State --- var gameState = "start"; // "start", "playing", "market" var startScreenContainer = new Container(); startScreenContainer.width = 2048; startScreenContainer.height = 2732; // --- Start Screen Background --- // 2D sunny forest background var startBg = LK.getAsset('forestBg', { anchorX: 0, anchorY: 0, scaleX: 2048 / 600, scaleY: 2732 / 40, x: 0, y: 0 }); startBg.width = 2048; startBg.height = 2732; startScreenContainer.addChild(startBg); // --- Top Right Coin Display (for start/market screens) --- var coinIconTL = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); coinIconTL.x = 2048 - 160; coinIconTL.y = 120; startScreenContainer.addChild(coinIconTL); var coinTxtTL = new Text2(currency + '', { size: 80, fill: 0xFFD700 }); coinTxtTL.anchor.set(0, 0.5); coinTxtTL.x = 2048 - 120; coinTxtTL.y = 120; startScreenContainer.addChild(coinTxtTL); // --- Start Screen Title --- var titleTxt = new Text2("Uçak Savaşı", { size: 160, fill: "#fff" }); titleTxt.anchor.set(0.5, 0.5); titleTxt.x = 2048 / 2; titleTxt.y = 700; startScreenContainer.addChild(titleTxt); // --- Start Button --- var startBtn = LK.getAsset('playerPlane', { anchorX: 0.5, anchorY: 0.5 }); startBtn.x = 2048 / 2; startBtn.y = 1200; startBtn.scaleX = 1.2; startBtn.scaleY = 1.2; startScreenContainer.addChild(startBtn); var startBtnTxt = new Text2("Başla", { size: 100, fill: "#fff" }); startBtnTxt.anchor.set(0.5, 0.5); startBtnTxt.x = startBtn.x; startBtnTxt.y = startBtn.y + 180; startScreenContainer.addChild(startBtnTxt); // --- Add start screen to game --- game.addChild(startScreenContainer); // --- Hide game GUI until game starts --- function setGameGuiVisible(visible) { if (typeof scoreTxt !== "undefined" && scoreTxt) scoreTxt.visible = visible; if (typeof coinIconBL !== "undefined" && coinIconBL) coinIconBL.visible = visible; if (typeof coinTxtBL !== "undefined" && coinTxtBL) coinTxtBL.visible = visible; if (typeof coinIcon !== "undefined" && coinIcon) coinIcon.visible = visible; if (typeof coinTxt !== "undefined" && coinTxt) coinTxt.visible = visible; if (typeof healthBarBg !== "undefined" && healthBarBg) healthBarBg.visible = visible; if (typeof healthBarFg !== "undefined" && healthBarFg) healthBarFg.visible = visible; } setGameGuiVisible(false); // --- GUI for in-game (unchanged) --- scoreTxt = new Text2('0', { size: 100, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Coin GUI for bottom left var coinIconBL = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); coinIconBL.x = 80; coinIconBL.y = -80; LK.gui.bottomLeft.addChild(coinIconBL); var coinTxtBL = new Text2(currency + '', { size: 80, fill: 0xFFD700 }); coinTxtBL.anchor.set(0, 0.5); coinTxtBL.x = 120; coinTxtBL.y = -80; LK.gui.bottomLeft.addChild(coinTxtBL); // (Retain top right coin for reference, but main is bottom left) coinIcon = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); coinIcon.x = 0; coinIcon.y = 0; LK.gui.topRight.addChild(coinIcon); coinTxt = new Text2(currency + '', { size: 80, fill: 0xFFD700 }); coinTxt.anchor.set(0, 0.5); coinTxt.x = 40; coinTxt.y = 0; LK.gui.topRight.addChild(coinTxt); // Health bar healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0, anchorY: 0.5 }); healthBarBg.x = 200; healthBarBg.y = 120; LK.gui.top.addChild(healthBarBg); healthBarFg = LK.getAsset('healthBarFg', { anchorX: 0, anchorY: 0.5 }); healthBarFg.x = 200; healthBarFg.y = 120; LK.gui.top.addChild(healthBarFg); function updateHealthBar() { var ratio = player.health / player.maxHealth; if (ratio < 0) ratio = 0; healthBarFg.width = 600 * ratio; } // --- Player Initialization --- player = new PlayerPlane(); player.x = 2048 / 2; player.y = 2732 - 350; game.addChild(player); // Set initial follow target to player's starting position game._lastMoveX = player.x; game._lastMoveY = player.y; updateHealthBar(); // --- Show/Hide Screens --- function showStartScreen() { gameState = "start"; startScreenContainer.visible = true; // marketScreenContainer.visible = false;//{3P} // Removed: marketScreenContainer is not defined setGameGuiVisible(false); player.visible = false; coinTxtTL.setText(currency + ''); } function startGame() { gameState = "playing"; startScreenContainer.visible = false; // marketScreenContainer.visible = false;//{3T} // Removed: marketScreenContainer is not defined setGameGuiVisible(true); player.visible = true; // Reset player position and health player.x = 2048 / 2; player.y = 2732 - 350; player.maxHealth = player.baseHealth + (storage.upgrades && storage.upgrades.health ? storage.upgrades.health : 0); // Ensure maxHealth is recalculated player.health = player.maxHealth; player.skin = storage.selectedSkin || "default"; player.updateSkin(); updateHealthBar(); // Clear all bullets, enemies, coins for (var i = playerBullets.length - 1; i >= 0; i--) { playerBullets[i].destroy(); playerBullets.splice(i, 1); } for (var i = enemyBullets.length - 1; i >= 0; i--) { enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); enemies.splice(i, 1); } for (var i = coinDrops.length - 1; i >= 0; i--) { coinDrops[i].destroy(); coinDrops.splice(i, 1); } LK.setScore(0); scoreTxt.setText("0"); coinTxtBL.setText(currency + ''); coinTxt.setText(currency + ''); } // --- Start/Market Button Events --- startBtn.interactive = true; startBtn.on('down', function (x, y, obj) { startGame(); }); // --- Start in start screen --- showStartScreen(); // --- Utility Functions --- function addCurrency(amount) { currency += amount; storage.currency = currency; coinTxt.setText(currency + ''); if (typeof coinTxtBL !== "undefined") { coinTxtBL.setText(currency + ''); } LK.getSound('coin').play(); } function showScorePopup(x, y, value) { var popup = new Text2('+' + value, { size: 70, fill: "#fff" }); popup.anchor.set(0.5, 0.5); popup.x = x; popup.y = y; game.addChild(popup); tween(popup, { y: y - 100, alpha: 0 }, { duration: 900, easing: tween.easeOut, onFinish: function onFinish() { popup.destroy(); } }); } // --- Enemy Spawning --- function spawnEnemy() { var r = Math.random(); var enemy; // 15% chance to spawn a CoinEnemy (only these drop coins) // Reduce green plane spawn rate: now only 10% (was 20%) // Slightly increase blue plane spawn rate (from 40% to 45%) if (r < 0.15) { enemy = new CoinEnemy(); } else if (r < 0.45) { enemy = new EnemyRed(); } else if (r < 0.9) { enemy = new EnemyBlue(); } else { enemy = new EnemyGreen(); } enemy.x = 180 + Math.random() * (2048 - 360); enemy.y = -enemy.height / 2; enemies.push(enemy); game.addChild(enemy); } // --- Game Move/Touch Controls --- function handleMove(x, y, obj) { if (gameState !== "playing") return; // Always track last move position for smooth following game._lastMoveX = x; game._lastMoveY = y; // No dragNode logic needed; player always follows cursor/touch position } game.move = handleMove; game.down = function (x, y, obj) { if (gameState !== "playing") return; handleMove(x, y, obj); }; game.up = function (x, y, obj) { if (gameState !== "playing") return; }; // --- Game Update Loop --- game.update = function () { if (gameState !== "playing") return; // --- Player follows cursor/touch position smoothly --- if (game._lastMoveX !== undefined && game._lastMoveY !== undefined) { // Clamp to game area var minX = player.width / 2 + 40; var maxX = 2048 - player.width / 2 - 40; var minY = 200 + player.height / 2; var maxY = 2732 - player.height / 2 - 40; var targetX = game._lastMoveX; var targetY = game._lastMoveY; if (targetX < minX) targetX = minX; if (targetX > maxX) targetX = maxX; if (targetY < minY) targetY = minY; if (targetY > maxY) targetY = maxY; // Move smoothly toward target (lerp) var speed = player.baseSpeed + (storage.upgrades && storage.upgrades.speed ? storage.upgrades.speed : 0); // Slightly increase lerp responsiveness for snappier feel speed *= 1.08; var dx = targetX - player.x; var dy = targetY - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > speed) { player.x += dx / dist * speed; player.y += dy / dist * speed; } else { player.x = targetX; player.y = targetY; } } // Player update player.update(); // Player auto-shoot // 2 bullets per second at 60FPS: 60/2 = 30 ticks interval if (LK.ticks % 30 === 0) { player.shoot(); } // Player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; b.update(); // Track bullet creation time if not already set if (typeof b._createdAt === "undefined") { b._createdAt = LK.ticks; } // Remove if off screen if (b.y < -50 || typeof b._createdAt !== "undefined" && LK.ticks - b._createdAt >= 180) { b.destroy(); playerBullets.splice(i, 1); continue; } // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; if (b.intersects(e)) { var killed = e.takeDamage(1); b.destroy(); playerBullets.splice(i, 1); if (killed) { e.destroy(); enemies.splice(j, 1); // --- Health bonus for every 3 destroyed enemies --- enemiesDestroyedSinceLastHeal++; if (enemiesDestroyedSinceLastHeal >= 3) { enemiesDestroyedSinceLastHeal = 0; if (player && typeof player.heal === "function") { player.heal(1); } } // --- End health bonus --- } break; } } } // Enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var b = enemyBullets[i]; b.update(); if (b.y > 2732 + 50) { b.destroy(); enemyBullets.splice(i, 1); continue; } // Check collision with player if (b.intersects(player)) { player.takeDamage(1); b.destroy(); enemyBullets.splice(i, 1); continue; } } // Coin drops: move, check pickup, remove if off screen for (var i = coinDrops.length - 1; i >= 0; i--) { var c = coinDrops[i]; c.update(); // Remove if off screen if (c.y > 2732 + 80) { c.destroy(); coinDrops.splice(i, 1); continue; } // Check pickup by player (only on the frame it starts intersecting) if (!c.lastWasIntersecting && c.intersects(player)) { addCurrency(1); c.destroy(); coinDrops.splice(i, 1); continue; } c.lastWasIntersecting = c.intersects(player); } // Enemy debris parts if (typeof enemyParts === "undefined") enemyParts = []; for (var i = enemyParts.length - 1; i >= 0; i--) { var part = enemyParts[i]; if (part.parent) part.update(); if (!part.parent) { enemyParts.splice(i, 1); } } // Enemies for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Remove if off screen if (e.y > 2732 + 100) { e.destroy(); enemies.splice(i, 1); // Decrease score by 2 for each enemy that leaves the screen without being destroyed LK.setScore(LK.getScore() - 2); scoreTxt.setText(LK.getScore()); // If score drops below zero, trigger game over if (LK.getScore() < 0) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } continue; } // Check collision with player if (e.intersects(player)) { player.takeDamage(2); LK.effects.flashObject(e, 0xff0000, 200); e.destroy(); enemies.splice(i, 1); continue; } } // Enemy spawn logic: increase spawn rate over time if (spawnTimer <= 0) { spawnEnemy(); spawnInterval = 90 - Math.floor(LK.getScore() / 10) * 4; // Increased base interval from 60 to 90 for slower spawns if (spawnInterval < 28) spawnInterval = 28; // Minimum interval increased from 18 to 28 spawnTimer = spawnInterval; } else { spawnTimer--; } // Update score scoreTxt.setText(LK.getScore()); // Win condition: player wins at 200 score if (LK.getScore() >= 200) { LK.showYouWin(); return; } scoreTxt.setText(LK.getScore()); }; // --- Music --- LK.playMusic('bgmusic', { fade: { start: 0, end: 1, duration: 1200 } }); // --- Game Over Handler (currency gain) --- LK.on('gameover', function () { // Add score to currency addCurrency(LK.getScore()); // Save currency storage.currency = currency; coinTxt.setText(currency + ''); coinTxtBL.setText(currency + ''); coinTxtTL.setText(currency + ''); // After a short delay, show start screen again LK.setTimeout(function () { showStartScreen(); }, 1200); // Reset upgrades/skins for next run if needed (not implemented here) }); // --- YouWin Handler (not used, but for future) --- LK.on('youwin', function () { // Could reward bonus currency, etc. }); // --- Prevent elements in top left 100x100 // (All GUI elements are placed away from top left, and player cannot move there)
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currency: 0,
unlockedSkins: ["default"],
selectedSkin: "default",
upgrades: {
fireRate: 0,
speed: 0,
health: 0
}
});
/****
* Classes
****/
// CoinDrop: Collectible coin that moves down and can be picked up by the player
var CoinDrop = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1
});
self.width = asset.width;
self.height = asset.height;
self.speed = 7;
self.lastWasIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Base Class
var EnemyBase = Container.expand(function () {
var self = Container.call(this);
self.type = 'base';
self.scoreValue = 1;
self.health = 1;
self.shootCooldown = 0;
self.shootRate = 90;
self.speed = 4;
self.bulletSpeed = 12;
self.lastIntersecting = false;
self.lastY = 0;
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
LK.getSound('enemyExplode').play();
LK.effects.flashObject(self, 0xffff00, 400); // Explosion effect (yellow flash)
LK.setScore(LK.getScore() + self.scoreValue);
addCurrency(self.scoreValue);
showScorePopup(self.x, self.y, self.scoreValue);
// Spawn debris parts
for (var i = 0; i < 8; i++) {
var part = new EnemyPart();
part.x = self.x;
part.y = self.y;
game.addChild(part);
enemyParts.push(part);
}
// Only CoinEnemy drops a coin, so do not drop a coin here for base enemies
self.destroy();
return true;
}
return false;
};
self.shoot = function () {
if (self.shootCooldown > 0) return;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + self.height / 2;
// If this is a green enemy, make its bullets faster
if (self.type === 'green') {
bullet.speed = 14;
}
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
self.shootCooldown = self.shootRate;
};
self.update = function () {
self.y += self.speed;
if (self.shootCooldown > 0) self.shootCooldown--;
};
return self;
});
// Red Attacker: moves straight, shoots at player
var EnemyRed = EnemyBase.expand(function () {
var self = EnemyBase.call(this);
self.type = 'red';
self.scoreValue = 2;
self.health = 1;
self.shootRate = 80;
self.speed = 6;
self.asset = self.attachAsset('enemyRed', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.asset.width;
self.height = self.asset.height;
self.update = function () {
self.y += self.speed;
if (self.shootCooldown > 0) self.shootCooldown--;
// Shoot if player is roughly aligned
if (Math.abs(self.x - player.x) < 80 && self.shootCooldown <= 0) {
self.shoot();
}
};
return self;
});
// Green Tank: slow, high health, shoots
var EnemyGreen = EnemyBase.expand(function () {
var self = EnemyBase.call(this);
self.type = 'green';
self.scoreValue = 5;
self.health = 3; // reduced from 6 to 3
self.shootRate = 60;
self.speed = 3.5;
self.asset = self.attachAsset('enemyGreen', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.asset.width;
self.height = self.asset.height;
self.update = function () {
self.y += self.speed;
if (self.shootCooldown > 0) self.shootCooldown--;
// Shoots more often
if (self.shootCooldown <= 0) {
self.shoot();
}
};
return self;
});
// Blue Speedster: zig-zags, no shooting
var EnemyBlue = EnemyBase.expand(function () {
var self = EnemyBase.call(this);
self.type = 'blue';
self.scoreValue = 3;
self.health = 1;
self.shootRate = 9999;
self.speed = 8;
self.asset = self.attachAsset('enemyBlue', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.asset.width;
self.height = self.asset.height;
self.zigzagDir = Math.random() > 0.5 ? 1 : -1;
self.zigzagSpeed = 7 + Math.random() * 3;
self.zigzagPhase = Math.random() * 100;
self.update = function () {
self.y += self.speed;
self.x += Math.sin((LK.ticks + self.zigzagPhase) / 18) * self.zigzagSpeed * self.zigzagDir;
};
return self;
});
// CoinEnemy: Enemies that carry a coin and drop it when destroyed
var CoinEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this);
self.type = 'coin';
self.scoreValue = 2;
self.health = 1;
self.shootRate = 120;
self.speed = 5;
self.asset = self.attachAsset('enemyRed', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.asset.width;
self.height = self.asset.height;
// Add a coin icon on top of the enemy
self.coinIcon = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 1.2,
scaleX: 0.7,
scaleY: 0.7
});
// Override takeDamage to drop a coin
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
LK.getSound('enemyExplode').play();
LK.effects.flashObject(self, 0xffff00, 400); // Explosion effect (yellow flash)
LK.setScore(LK.getScore() + self.scoreValue);
showScorePopup(self.x, self.y, self.scoreValue);
// Spawn debris parts
for (var i = 0; i < 8; i++) {
var part = new EnemyPart();
part.x = self.x;
part.y = self.y;
game.addChild(part);
enemyParts.push(part);
}
// Drop a coin at this position, but only once
if (!self._coinDropped) {
var coin = new CoinDrop();
coin.x = self.x;
coin.y = self.y;
coinDrops.push(coin);
game.addChild(coin);
self._coinDropped = true;
}
self.destroy();
return true;
}
return false;
};
self.update = function () {
self.y += self.speed;
if (self.shootCooldown > 0) self.shootCooldown--;
};
return self;
});
// Enemy Bullet
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bullet.width;
self.height = bullet.height;
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
// EnemyPart: Debris piece for enemy explosion
var EnemyPart = Container.expand(function () {
var self = Container.call(this);
// Use a greenCube for debris, but only red and orange colors
var colors = [0xff4444, 0xff9900];
var color = colors[Math.floor(Math.random() * colors.length)];
var part = self.attachAsset('greenCube', {
anchorX: 0.5,
anchorY: 0.5
});
part.tint = color;
// Randomize size
var scale = 0.4 + Math.random() * 0.5;
part.scaleX = scale;
part.scaleY = scale;
self.width = part.width * scale;
self.height = part.height * scale;
// Set initial velocity
self.vx = (Math.random() - 0.5) * 32;
self.vy = (Math.random() - 0.5) * 32 - 8;
self.gravity = 2.2 + Math.random() * 0.8;
self.life = 36 + Math.floor(Math.random() * 18); // 0.6s
self._age = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.vy += self.gravity;
self._age++;
// Fade out
part.alpha = Math.max(0, 1 - self._age / self.life);
if (self._age > self.life) {
self.destroy();
}
};
return self;
});
// Player Bullet
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bullet.width;
self.height = bullet.height;
self.speed = -8 - (storage.upgrades && storage.upgrades.fireRate ? storage.upgrades.fireRate * 1 : 0); // Slowed down from -12 to -8
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Plane
var PlayerPlane = Container.expand(function () {
var self = Container.call(this);
// Attach player plane asset
self.skin = storage.selectedSkin || 'default';
self.plane = self.attachAsset('playerPlane', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.plane.width;
self.height = self.plane.height;
self.fireCooldown = 0;
self.baseFireRate = 30; // ticks between shots
self.baseSpeed = 32; // Increased from 23 for faster movement
self.baseHealth = 8; // Increased from 5 to 8 for more player lives
self.maxHealth = self.baseHealth + (storage.upgrades && storage.upgrades.health ? storage.upgrades.health : 0);
self.health = self.maxHealth;
self.updateSkin = function () {
// For future: swap asset based on skin
// For now, only color changes
if (self.skin === 'default') {
self.plane.tint = 0x888888;
} else if (self.skin === 'gold') {
self.plane.tint = 0xffd700;
} else if (self.skin === 'blue') {
self.plane.tint = 0x2a6edb;
}
};
self.shoot = function () {
if (self.fireCooldown > 0) return;
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - self.height / 2 + 10;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('playerShoot').play();
self.fireCooldown = self.baseFireRate - (storage.upgrades && storage.upgrades.fireRate ? storage.upgrades.fireRate * 4 : 0);
if (self.fireCooldown < 8) self.fireCooldown = 8;
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) self.health = 0;
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('playerHit').play();
updateHealthBar();
if (self.health <= 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
};
self.heal = function (amount) {
self.health += amount;
if (self.health > self.maxHealth) self.health = self.maxHealth;
updateHealthBar();
};
self.update = function () {
if (self.fireCooldown > 0) self.fireCooldown--;
};
self.updateSkin();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundImage: 'spaceMoonBg'
});
/****
* Game Code
****/
// --- Global Variables ---
// Player plane (default skin: gray)
// Player bullet (yellow)
// Enemy: Red Attacker
// Enemy: Blue Speedster
// Enemy: Green Tank
// Enemy bullet (red)
// Health bar background
// Health bar foreground
// Coin icon
// Sounds
// Music
var player;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var coinDrops = [];
var enemyParts = [];
var spawnTimer = 0;
var spawnInterval = 60;
var dragNode = null;
var lastPlayerX = 0;
var lastPlayerY = 0;
var healthBarBg, healthBarFg;
var scoreTxt, coinTxt, coinIcon;
var currency = storage.currency || 0;
// Track how many enemies have been destroyed for health bonus
var enemiesDestroyedSinceLastHeal = 0;
// --- GUI Elements ---
// --- Start Screen State ---
var gameState = "start"; // "start", "playing", "market"
var startScreenContainer = new Container();
startScreenContainer.width = 2048;
startScreenContainer.height = 2732;
// --- Start Screen Background ---
// 2D sunny forest background
var startBg = LK.getAsset('forestBg', {
anchorX: 0,
anchorY: 0,
scaleX: 2048 / 600,
scaleY: 2732 / 40,
x: 0,
y: 0
});
startBg.width = 2048;
startBg.height = 2732;
startScreenContainer.addChild(startBg);
// --- Top Right Coin Display (for start/market screens) ---
var coinIconTL = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinIconTL.x = 2048 - 160;
coinIconTL.y = 120;
startScreenContainer.addChild(coinIconTL);
var coinTxtTL = new Text2(currency + '', {
size: 80,
fill: 0xFFD700
});
coinTxtTL.anchor.set(0, 0.5);
coinTxtTL.x = 2048 - 120;
coinTxtTL.y = 120;
startScreenContainer.addChild(coinTxtTL);
// --- Start Screen Title ---
var titleTxt = new Text2("Uçak Savaşı", {
size: 160,
fill: "#fff"
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 2048 / 2;
titleTxt.y = 700;
startScreenContainer.addChild(titleTxt);
// --- Start Button ---
var startBtn = LK.getAsset('playerPlane', {
anchorX: 0.5,
anchorY: 0.5
});
startBtn.x = 2048 / 2;
startBtn.y = 1200;
startBtn.scaleX = 1.2;
startBtn.scaleY = 1.2;
startScreenContainer.addChild(startBtn);
var startBtnTxt = new Text2("Başla", {
size: 100,
fill: "#fff"
});
startBtnTxt.anchor.set(0.5, 0.5);
startBtnTxt.x = startBtn.x;
startBtnTxt.y = startBtn.y + 180;
startScreenContainer.addChild(startBtnTxt);
// --- Add start screen to game ---
game.addChild(startScreenContainer);
// --- Hide game GUI until game starts ---
function setGameGuiVisible(visible) {
if (typeof scoreTxt !== "undefined" && scoreTxt) scoreTxt.visible = visible;
if (typeof coinIconBL !== "undefined" && coinIconBL) coinIconBL.visible = visible;
if (typeof coinTxtBL !== "undefined" && coinTxtBL) coinTxtBL.visible = visible;
if (typeof coinIcon !== "undefined" && coinIcon) coinIcon.visible = visible;
if (typeof coinTxt !== "undefined" && coinTxt) coinTxt.visible = visible;
if (typeof healthBarBg !== "undefined" && healthBarBg) healthBarBg.visible = visible;
if (typeof healthBarFg !== "undefined" && healthBarFg) healthBarFg.visible = visible;
}
setGameGuiVisible(false);
// --- GUI for in-game (unchanged) ---
scoreTxt = new Text2('0', {
size: 100,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Coin GUI for bottom left
var coinIconBL = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinIconBL.x = 80;
coinIconBL.y = -80;
LK.gui.bottomLeft.addChild(coinIconBL);
var coinTxtBL = new Text2(currency + '', {
size: 80,
fill: 0xFFD700
});
coinTxtBL.anchor.set(0, 0.5);
coinTxtBL.x = 120;
coinTxtBL.y = -80;
LK.gui.bottomLeft.addChild(coinTxtBL);
// (Retain top right coin for reference, but main is bottom left)
coinIcon = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinIcon.x = 0;
coinIcon.y = 0;
LK.gui.topRight.addChild(coinIcon);
coinTxt = new Text2(currency + '', {
size: 80,
fill: 0xFFD700
});
coinTxt.anchor.set(0, 0.5);
coinTxt.x = 40;
coinTxt.y = 0;
LK.gui.topRight.addChild(coinTxt);
// Health bar
healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0.5
});
healthBarBg.x = 200;
healthBarBg.y = 120;
LK.gui.top.addChild(healthBarBg);
healthBarFg = LK.getAsset('healthBarFg', {
anchorX: 0,
anchorY: 0.5
});
healthBarFg.x = 200;
healthBarFg.y = 120;
LK.gui.top.addChild(healthBarFg);
function updateHealthBar() {
var ratio = player.health / player.maxHealth;
if (ratio < 0) ratio = 0;
healthBarFg.width = 600 * ratio;
}
// --- Player Initialization ---
player = new PlayerPlane();
player.x = 2048 / 2;
player.y = 2732 - 350;
game.addChild(player);
// Set initial follow target to player's starting position
game._lastMoveX = player.x;
game._lastMoveY = player.y;
updateHealthBar();
// --- Show/Hide Screens ---
function showStartScreen() {
gameState = "start";
startScreenContainer.visible = true;
// marketScreenContainer.visible = false;//{3P} // Removed: marketScreenContainer is not defined
setGameGuiVisible(false);
player.visible = false;
coinTxtTL.setText(currency + '');
}
function startGame() {
gameState = "playing";
startScreenContainer.visible = false;
// marketScreenContainer.visible = false;//{3T} // Removed: marketScreenContainer is not defined
setGameGuiVisible(true);
player.visible = true;
// Reset player position and health
player.x = 2048 / 2;
player.y = 2732 - 350;
player.maxHealth = player.baseHealth + (storage.upgrades && storage.upgrades.health ? storage.upgrades.health : 0); // Ensure maxHealth is recalculated
player.health = player.maxHealth;
player.skin = storage.selectedSkin || "default";
player.updateSkin();
updateHealthBar();
// Clear all bullets, enemies, coins
for (var i = playerBullets.length - 1; i >= 0; i--) {
playerBullets[i].destroy();
playerBullets.splice(i, 1);
}
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].destroy();
enemyBullets.splice(i, 1);
}
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
for (var i = coinDrops.length - 1; i >= 0; i--) {
coinDrops[i].destroy();
coinDrops.splice(i, 1);
}
LK.setScore(0);
scoreTxt.setText("0");
coinTxtBL.setText(currency + '');
coinTxt.setText(currency + '');
}
// --- Start/Market Button Events ---
startBtn.interactive = true;
startBtn.on('down', function (x, y, obj) {
startGame();
});
// --- Start in start screen ---
showStartScreen();
// --- Utility Functions ---
function addCurrency(amount) {
currency += amount;
storage.currency = currency;
coinTxt.setText(currency + '');
if (typeof coinTxtBL !== "undefined") {
coinTxtBL.setText(currency + '');
}
LK.getSound('coin').play();
}
function showScorePopup(x, y, value) {
var popup = new Text2('+' + value, {
size: 70,
fill: "#fff"
});
popup.anchor.set(0.5, 0.5);
popup.x = x;
popup.y = y;
game.addChild(popup);
tween(popup, {
y: y - 100,
alpha: 0
}, {
duration: 900,
easing: tween.easeOut,
onFinish: function onFinish() {
popup.destroy();
}
});
}
// --- Enemy Spawning ---
function spawnEnemy() {
var r = Math.random();
var enemy;
// 15% chance to spawn a CoinEnemy (only these drop coins)
// Reduce green plane spawn rate: now only 10% (was 20%)
// Slightly increase blue plane spawn rate (from 40% to 45%)
if (r < 0.15) {
enemy = new CoinEnemy();
} else if (r < 0.45) {
enemy = new EnemyRed();
} else if (r < 0.9) {
enemy = new EnemyBlue();
} else {
enemy = new EnemyGreen();
}
enemy.x = 180 + Math.random() * (2048 - 360);
enemy.y = -enemy.height / 2;
enemies.push(enemy);
game.addChild(enemy);
}
// --- Game Move/Touch Controls ---
function handleMove(x, y, obj) {
if (gameState !== "playing") return;
// Always track last move position for smooth following
game._lastMoveX = x;
game._lastMoveY = y;
// No dragNode logic needed; player always follows cursor/touch position
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (gameState !== "playing") return;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (gameState !== "playing") return;
};
// --- Game Update Loop ---
game.update = function () {
if (gameState !== "playing") return;
// --- Player follows cursor/touch position smoothly ---
if (game._lastMoveX !== undefined && game._lastMoveY !== undefined) {
// Clamp to game area
var minX = player.width / 2 + 40;
var maxX = 2048 - player.width / 2 - 40;
var minY = 200 + player.height / 2;
var maxY = 2732 - player.height / 2 - 40;
var targetX = game._lastMoveX;
var targetY = game._lastMoveY;
if (targetX < minX) targetX = minX;
if (targetX > maxX) targetX = maxX;
if (targetY < minY) targetY = minY;
if (targetY > maxY) targetY = maxY;
// Move smoothly toward target (lerp)
var speed = player.baseSpeed + (storage.upgrades && storage.upgrades.speed ? storage.upgrades.speed : 0);
// Slightly increase lerp responsiveness for snappier feel
speed *= 1.08;
var dx = targetX - player.x;
var dy = targetY - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > speed) {
player.x += dx / dist * speed;
player.y += dy / dist * speed;
} else {
player.x = targetX;
player.y = targetY;
}
}
// Player update
player.update();
// Player auto-shoot
// 2 bullets per second at 60FPS: 60/2 = 30 ticks interval
if (LK.ticks % 30 === 0) {
player.shoot();
}
// Player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
// Track bullet creation time if not already set
if (typeof b._createdAt === "undefined") {
b._createdAt = LK.ticks;
}
// Remove if off screen
if (b.y < -50 || typeof b._createdAt !== "undefined" && LK.ticks - b._createdAt >= 180) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
var killed = e.takeDamage(1);
b.destroy();
playerBullets.splice(i, 1);
if (killed) {
e.destroy();
enemies.splice(j, 1);
// --- Health bonus for every 3 destroyed enemies ---
enemiesDestroyedSinceLastHeal++;
if (enemiesDestroyedSinceLastHeal >= 3) {
enemiesDestroyedSinceLastHeal = 0;
if (player && typeof player.heal === "function") {
player.heal(1);
}
}
// --- End health bonus ---
}
break;
}
}
}
// Enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var b = enemyBullets[i];
b.update();
if (b.y > 2732 + 50) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (b.intersects(player)) {
player.takeDamage(1);
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
}
// Coin drops: move, check pickup, remove if off screen
for (var i = coinDrops.length - 1; i >= 0; i--) {
var c = coinDrops[i];
c.update();
// Remove if off screen
if (c.y > 2732 + 80) {
c.destroy();
coinDrops.splice(i, 1);
continue;
}
// Check pickup by player (only on the frame it starts intersecting)
if (!c.lastWasIntersecting && c.intersects(player)) {
addCurrency(1);
c.destroy();
coinDrops.splice(i, 1);
continue;
}
c.lastWasIntersecting = c.intersects(player);
}
// Enemy debris parts
if (typeof enemyParts === "undefined") enemyParts = [];
for (var i = enemyParts.length - 1; i >= 0; i--) {
var part = enemyParts[i];
if (part.parent) part.update();
if (!part.parent) {
enemyParts.splice(i, 1);
}
}
// Enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Remove if off screen
if (e.y > 2732 + 100) {
e.destroy();
enemies.splice(i, 1);
// Decrease score by 2 for each enemy that leaves the screen without being destroyed
LK.setScore(LK.getScore() - 2);
scoreTxt.setText(LK.getScore());
// If score drops below zero, trigger game over
if (LK.getScore() < 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
continue;
}
// Check collision with player
if (e.intersects(player)) {
player.takeDamage(2);
LK.effects.flashObject(e, 0xff0000, 200);
e.destroy();
enemies.splice(i, 1);
continue;
}
}
// Enemy spawn logic: increase spawn rate over time
if (spawnTimer <= 0) {
spawnEnemy();
spawnInterval = 90 - Math.floor(LK.getScore() / 10) * 4; // Increased base interval from 60 to 90 for slower spawns
if (spawnInterval < 28) spawnInterval = 28; // Minimum interval increased from 18 to 28
spawnTimer = spawnInterval;
} else {
spawnTimer--;
}
// Update score
scoreTxt.setText(LK.getScore());
// Win condition: player wins at 200 score
if (LK.getScore() >= 200) {
LK.showYouWin();
return;
}
scoreTxt.setText(LK.getScore());
};
// --- Music ---
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
// --- Game Over Handler (currency gain) ---
LK.on('gameover', function () {
// Add score to currency
addCurrency(LK.getScore());
// Save currency
storage.currency = currency;
coinTxt.setText(currency + '');
coinTxtBL.setText(currency + '');
coinTxtTL.setText(currency + '');
// After a short delay, show start screen again
LK.setTimeout(function () {
showStartScreen();
}, 1200);
// Reset upgrades/skins for next run if needed (not implemented here)
});
// --- YouWin Handler (not used, but for future) ---
LK.on('youwin', function () {
// Could reward bonus currency, etc.
});
// --- Prevent elements in top left 100x100
// (All GUI elements are placed away from top left, and player cannot move there)
coin. In-Game asset. 2d. High contrast. No shadows
mavi ufo. In-Game asset. 2d. High contrast. No shadows
bir mermi ama ters . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
yeşil 2d pixel simetrik uçak In-Game asset. 2d. High contrast. No shadows
kırmızı 2d pixel simetrik uçak In-Game asset. 2d. High contrast. No shadows
gri 2d piksel yüksek techizatlı uçak. In-Game asset. 2d. High contrast. No shadows
mermi. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat