User prompt
bazı düşmanlar atnı coinler gibi yeşil küpler düşürsün ve bunlarıda toplaya bilelim
User prompt
başlangıç ekranının boyutunu belirle
User prompt
başlangıç arkaplanı 2d güneşli bi orman olsun oyun arkaplanı ayın olduğu bir uzay olsun marketşn arkaplanı market olsun
User prompt
başlangıca oyunaa ve markete bi background ekle
User prompt
oyuncunun mermi atış hızını azalt
User prompt
oyuncunun mermi hızını biraz yavaşlat
User prompt
oyuncunun canını arttır
User prompt
Please fix the bug: 'ReferenceError: EnemyGreen is not defined' in or related to this line: 'enemy = new EnemyGreen();' Line Number: 601
User prompt
Please fix the bug: 'ReferenceError: EnemyGreen is not defined' in or related to this line: 'enemy = new EnemyGreen();' Line Number: 632
User prompt
Please fix the bug: 'ReferenceError: PlayerBullet is not defined' in or related to this line: 'var bullet = new PlayerBullet();' Line Number: 123
User prompt
Please fix the bug: 'ReferenceError: EnemyRed is not defined' in or related to this line: 'enemy = new EnemyRed();' Line Number: 577
User prompt
Please fix the bug: 'ReferenceError: EnemyBlue is not defined' in or related to this line: 'enemy = new EnemyBlue();' Line Number: 548
User prompt
Please fix the bug: 'PlayerPlane is not defined' in or related to this line: 'player = new PlayerPlane();' Line Number: 225
User prompt
Please fix the bug: 'ReferenceError: EnemyGreen is not defined' in or related to this line: 'enemy = new EnemyGreen();' Line Number: 599
User prompt
Please fix the bug: 'ReferenceError: EnemyRed is not defined' in or related to this line: 'enemy = new EnemyRed();' Line Number: 555
User prompt
Please fix the bug: 'PlayerPlane is not defined' in or related to this line: 'player = new PlayerPlane();' Line Number: 225
User prompt
Please fix the bug: 'PlayerPlane is not defined' in or related to this line: 'player = new PlayerPlane();' Line Number: 225
User prompt
Please fix the bug: 'ReferenceError: EnemyBlue is not defined' in or related to this line: 'enemy = new EnemyBlue();' Line Number: 624
User prompt
Please fix the bug: 'ReferenceError: EnemyGreen is not defined' in or related to this line: 'enemy = new EnemyGreen();' Line Number: 586
User prompt
Please fix the bug: 'ReferenceError: EnemyGreen is not defined' in or related to this line: 'enemy = new EnemyGreen();' Line Number: 586
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var i = 0; i < skinList.length; i++) {' Line Number: 52
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var i = 0; i < skinList.length; i++) {' Line Number: 52
User prompt
Please fix the bug: 'PlayerPlane is not defined' in or related to this line: 'player = new PlayerPlane();' Line Number: 231
User prompt
Please fix the bug: 'ReferenceError: EnemyBlue is not defined' in or related to this line: 'enemy = new EnemyBlue();' Line Number: 645
User prompt
Please fix the bug: 'ReferenceError: CoinEnemy is not defined' in or related to this line: 'enemy = new CoinEnemy();' Line Number: 597
/**** * 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 ****/ // --- CoinEnemy Class --- var CoinEnemy = Container.expand(function () { var self = Container.call(this); // Attach coin asset (for visual, can be replaced with a unique enemy look) self.asset = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); // Set size for collision self.width = self.asset.width; self.height = self.asset.height; // Health (1 hit to kill) self.health = 1; // Speed (slower than normal enemies) self.speed = 12; // Update (move down) self.update = function () { if (typeof self.lastY === "undefined") self.lastY = self.y; self.y += self.speed; self.lastY = self.y; }; // Take damage, return true if killed self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { // Drop a coin at this position var coin = new CoinDrop(); coin.x = self.x; coin.y = self.y; coinDrops.push(coin); game.addChild(coin); // Show popup showScorePopup(self.x, self.y, "+1"); // Increase score LK.setScore(LK.getScore() + 5); scoreTxt.setText(LK.getScore()); return true; } return false; }; return self; }); // --- PlayerBullet Class --- var PlayerBullet = Container.expand(function () { var self = Container.call(this); // Attach bullet asset self.asset = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 48 + (storage.upgrades && storage.upgrades.fireRate ? storage.upgrades.fireRate * 2 : 0); // Defensive: set width/height for collision self.width = self.asset.width; self.height = self.asset.height; // Update (called every frame) self.update = function () { if (typeof self.lastY === "undefined") self.lastY = self.y; self.y -= self.speed; // Defensive: update lastY for good practices self.lastY = self.y; }; return self; }); // --- PlayerPlane Class --- var PlayerPlane = Container.expand(function () { var self = Container.call(this); // Default skin self.skin = storage.selectedSkin || "default"; // Attach player asset self.asset = self.attachAsset('playerPlane', { anchorX: 0.5, anchorY: 0.5 }); self.asset.tint = 0x888888; // Player stats self.maxHealth = 8 + (storage.upgrades && storage.upgrades.health ? storage.upgrades.health : 0); self.health = self.maxHealth; self.baseSpeed = 18; // Update skin color self.updateSkin = function () { var color = 0x888888; if (!Array.isArray(skinList)) skinList = []; for (var i = 0; i < skinList.length; i++) { if (skinList[i].id === self.skin) { color = skinList[i].color; break; } } self.asset.tint = color; }; // Take damage self.takeDamage = function (amount) { self.health -= amount; if (self.health < 0) self.health = 0; updateHealthBar(); LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } }; // Heal self.heal = function (amount) { self.health += amount; if (self.health > self.maxHealth) self.health = self.maxHealth; updateHealthBar(); LK.effects.flashObject(self, 0x44ff44, 200); }; // Shoot self.shoot = function () { // Fire a bullet from the nose of the plane var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - self.height / 2 - bullet.height / 2; playerBullets.push(bullet); game.addChild(bullet); }; // Update (called every frame) self.update = function () { // No-op for now (movement handled in game.update) }; // Initialize skin self.updateSkin(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2a }); /**** * Game Code ****/ // Music // Sounds // Coin icon // Health bar foreground // Health bar background // Enemy bullet (red) // Enemy: Green Tank // Enemy: Blue Speedster // Enemy: Red Attacker // Player bullet (yellow) // Player plane (default skin: gray) // --- Global Variables --- var player; var playerBullets = []; var enemies = []; var enemyBullets = []; var coinDrops = []; var healthDrops = []; 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; if (!Array.isArray(storage.unlockedSkins)) storage.unlockedSkins = ["default"]; if (!storage.selectedSkin) storage.selectedSkin = "default"; // --- GUI Elements --- // --- Start Screen State --- var gameState = "start"; // "start", "playing", "market" var startScreenContainer = new Container(); var marketScreenContainer = new Container(); // --- 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: 140, fill: "#fff" }); startBtnTxt.anchor.set(0.5, 0.5); startBtnTxt.x = startBtn.x; startBtnTxt.y = startBtn.y + 180; startScreenContainer.addChild(startBtnTxt); // --- Market Button --- var marketBtn = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); marketBtn.x = 2048 / 2; marketBtn.y = 1500; marketBtn.scaleX = 1.3; marketBtn.scaleY = 1.3; startScreenContainer.addChild(marketBtn); var marketBtnTxt = new Text2("Market", { size: 140, fill: 0xFFD700 }); marketBtnTxt.anchor.set(0.5, 0.5); marketBtnTxt.x = marketBtn.x; marketBtnTxt.y = marketBtn.y + 140; startScreenContainer.addChild(marketBtnTxt); // --- Add start screen to game --- game.addChild(startScreenContainer); // --- Market Screen (basic, see next block for content) --- marketScreenContainer.visible = false; game.addChild(marketScreenContainer); // --- 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(); // --- Market Skins Data --- // Ensure skinList is always defined as an array to prevent undefined errors var skinList = [{ id: "default", name: "Gri Uçak", price: 0, color: 0x888888 }, { id: "gold", name: "Altın Uçak", price: 30, color: 0xffd700 }, { id: "blue", name: "Mavi Uçak", price: 20, color: 0x2a6edb }]; if (!skinList) skinList = []; // --- Market UI --- function refreshMarketScreen() { // Remove all children while (marketScreenContainer.children.length) { marketScreenContainer.removeChild(marketScreenContainer.children[0]); } // Top right coin (moved from top left) var coinIconM = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); coinIconM.x = 2048 - 160; coinIconM.y = 120; marketScreenContainer.addChild(coinIconM); var coinTxtM = new Text2(currency + '', { size: 80, fill: 0xFFD700 }); coinTxtM.anchor.set(0, 0.5); coinTxtM.x = 2048 - 120; coinTxtM.y = 120; marketScreenContainer.addChild(coinTxtM); // Title var marketTitle = new Text2("Market", { size: 200, fill: 0xFFD700 }); marketTitle.anchor.set(0.5, 0.5); marketTitle.x = 2048 / 2; marketTitle.y = 350; marketScreenContainer.addChild(marketTitle); // Skins var y0 = 700; var x0 = 2048 / 2; var dx = 500; for (var i = 0; i < skinList.length; i++) { var skin = skinList[i]; var x = x0 + (i - 1) * dx; // Plane asset var skinAsset = LK.getAsset('playerPlane', { anchorX: 0.5, anchorY: 0.5 }); skinAsset.x = x; skinAsset.y = y0; skinAsset.tint = skin.color; skinAsset.scaleX = 1.1; skinAsset.scaleY = 1.1; marketScreenContainer.addChild(skinAsset); // Name var skinName = new Text2(skin.name, { size: 70, fill: "#fff" }); skinName.anchor.set(0.5, 0.5); skinName.x = x; skinName.y = y0 + 120; marketScreenContainer.addChild(skinName); // Button var btnTxt, btnColor; var unlocked = storage.unlockedSkins && storage.unlockedSkins.indexOf(skin.id) !== -1; var selected = storage.selectedSkin === skin.id; if (selected) { btnTxt = "Seçili"; btnColor = "#44ff44"; } else if (unlocked) { btnTxt = "Seç"; btnColor = "#fff"; } else { btnTxt = skin.price + " Coin"; btnColor = "#FFD700"; } var btn = new Text2(btnTxt, { size: 60, fill: btnColor }); btn.anchor.set(0.5, 0.5); btn.x = x; btn.y = y0 + 220; btn.interactive = true; btn.skinId = skin.id; btn.on('down', function (x, y, obj) { var sid = obj.skinId; var s = null; for (var j = 0; j < skinList.length; j++) { if (skinList[j].id === sid) s = skinList[j]; } if (!s) return; // Defensive: ensure unlockedSkins is always an array if (!Array.isArray(storage.unlockedSkins)) storage.unlockedSkins = ["default"]; var unlocked = storage.unlockedSkins.indexOf(s.id) !== -1; if (storage.selectedSkin === s.id) return; if (unlocked) { storage.selectedSkin = s.id; player.skin = s.id; player.updateSkin(); refreshMarketScreen(); } else if (currency >= s.price) { currency -= s.price; storage.currency = currency; // Only add if not already unlocked if (storage.unlockedSkins.indexOf(s.id) === -1) { storage.unlockedSkins.push(s.id); } storage.selectedSkin = s.id; player.skin = s.id; player.updateSkin(); // Update all coin displays after purchase coinTxt.setText(currency + ''); coinTxtBL.setText(currency + ''); coinTxtTL.setText(currency + ''); refreshMarketScreen(); } }); marketScreenContainer.addChild(btn); } // Back button var backBtn = new Text2("Geri", { size: 80, fill: "#fff" }); backBtn.anchor.set(0.5, 0.5); backBtn.x = 2048 / 2; backBtn.y = 2000; backBtn.interactive = true; backBtn.on('down', function (x, y, obj) { showStartScreen(); }); marketScreenContainer.addChild(backBtn); } // --- Show/Hide Screens --- function showStartScreen() { gameState = "start"; startScreenContainer.visible = true; marketScreenContainer.visible = false; setGameGuiVisible(false); player.visible = false; if (typeof coinTxtTL !== "undefined" && coinTxtTL) coinTxtTL.setText(currency + ''); } function showMarketScreen() { gameState = "market"; startScreenContainer.visible = false; marketScreenContainer.visible = true; setGameGuiVisible(false); player.visible = false; refreshMarketScreen(); } function startGame() { gameState = "playing"; startScreenContainer.visible = false; marketScreenContainer.visible = false; setGameGuiVisible(true); player.visible = true; // Reset player position and health player.x = 2048 / 2; player.y = 2732 - 350; 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(); }); marketBtn.interactive = true; marketBtn.on('down', function (x, y, obj) { showMarketScreen(); }); // --- 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 + ''); } if (typeof coinTxtTL !== "undefined") { coinTxtTL.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) if (r < 0.15) { enemy = new CoinEnemy(); } else if (r < 0.5) { enemy = new EnemyRed(); } else if (r < 0.8) { 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 if (LK.ticks % 5 === 0) { player.shoot(); } // Player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; b.update(); // Remove if off screen if (b.y < -50) { 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); } 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); } // Health drops: move, check pickup, remove if off screen for (var i = healthDrops.length - 1; i >= 0; i--) { var h = healthDrops[i]; h.update(); // Remove if off screen if (h.y > 2732 + 80) { h.destroy(); healthDrops.splice(i, 1); continue; } // Check pickup by player (only on the frame it starts intersecting) if (!h.lastWasIntersecting && h.intersects(player)) { player.heal(2); // Optional: show a green popup showScorePopup(h.x, h.y, "+Can"); h.destroy(); healthDrops.splice(i, 1); continue; } h.lastWasIntersecting = h.intersects(player); } // 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: none (endless), but could be added }; // --- 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. });
/****
* 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
****/
// --- CoinEnemy Class ---
var CoinEnemy = Container.expand(function () {
var self = Container.call(this);
// Attach coin asset (for visual, can be replaced with a unique enemy look)
self.asset = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Set size for collision
self.width = self.asset.width;
self.height = self.asset.height;
// Health (1 hit to kill)
self.health = 1;
// Speed (slower than normal enemies)
self.speed = 12;
// Update (move down)
self.update = function () {
if (typeof self.lastY === "undefined") self.lastY = self.y;
self.y += self.speed;
self.lastY = self.y;
};
// Take damage, return true if killed
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
// Drop a coin at this position
var coin = new CoinDrop();
coin.x = self.x;
coin.y = self.y;
coinDrops.push(coin);
game.addChild(coin);
// Show popup
showScorePopup(self.x, self.y, "+1");
// Increase score
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
return true;
}
return false;
};
return self;
});
// --- PlayerBullet Class ---
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
// Attach bullet asset
self.asset = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 48 + (storage.upgrades && storage.upgrades.fireRate ? storage.upgrades.fireRate * 2 : 0);
// Defensive: set width/height for collision
self.width = self.asset.width;
self.height = self.asset.height;
// Update (called every frame)
self.update = function () {
if (typeof self.lastY === "undefined") self.lastY = self.y;
self.y -= self.speed;
// Defensive: update lastY for good practices
self.lastY = self.y;
};
return self;
});
// --- PlayerPlane Class ---
var PlayerPlane = Container.expand(function () {
var self = Container.call(this);
// Default skin
self.skin = storage.selectedSkin || "default";
// Attach player asset
self.asset = self.attachAsset('playerPlane', {
anchorX: 0.5,
anchorY: 0.5
});
self.asset.tint = 0x888888;
// Player stats
self.maxHealth = 8 + (storage.upgrades && storage.upgrades.health ? storage.upgrades.health : 0);
self.health = self.maxHealth;
self.baseSpeed = 18;
// Update skin color
self.updateSkin = function () {
var color = 0x888888;
if (!Array.isArray(skinList)) skinList = [];
for (var i = 0; i < skinList.length; i++) {
if (skinList[i].id === self.skin) {
color = skinList[i].color;
break;
}
}
self.asset.tint = color;
};
// Take damage
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) self.health = 0;
updateHealthBar();
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
};
// Heal
self.heal = function (amount) {
self.health += amount;
if (self.health > self.maxHealth) self.health = self.maxHealth;
updateHealthBar();
LK.effects.flashObject(self, 0x44ff44, 200);
};
// Shoot
self.shoot = function () {
// Fire a bullet from the nose of the plane
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - self.height / 2 - bullet.height / 2;
playerBullets.push(bullet);
game.addChild(bullet);
};
// Update (called every frame)
self.update = function () {
// No-op for now (movement handled in game.update)
};
// Initialize skin
self.updateSkin();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2a
});
/****
* Game Code
****/
// Music
// Sounds
// Coin icon
// Health bar foreground
// Health bar background
// Enemy bullet (red)
// Enemy: Green Tank
// Enemy: Blue Speedster
// Enemy: Red Attacker
// Player bullet (yellow)
// Player plane (default skin: gray)
// --- Global Variables ---
var player;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var coinDrops = [];
var healthDrops = [];
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;
if (!Array.isArray(storage.unlockedSkins)) storage.unlockedSkins = ["default"];
if (!storage.selectedSkin) storage.selectedSkin = "default";
// --- GUI Elements ---
// --- Start Screen State ---
var gameState = "start"; // "start", "playing", "market"
var startScreenContainer = new Container();
var marketScreenContainer = new Container();
// --- 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: 140,
fill: "#fff"
});
startBtnTxt.anchor.set(0.5, 0.5);
startBtnTxt.x = startBtn.x;
startBtnTxt.y = startBtn.y + 180;
startScreenContainer.addChild(startBtnTxt);
// --- Market Button ---
var marketBtn = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
marketBtn.x = 2048 / 2;
marketBtn.y = 1500;
marketBtn.scaleX = 1.3;
marketBtn.scaleY = 1.3;
startScreenContainer.addChild(marketBtn);
var marketBtnTxt = new Text2("Market", {
size: 140,
fill: 0xFFD700
});
marketBtnTxt.anchor.set(0.5, 0.5);
marketBtnTxt.x = marketBtn.x;
marketBtnTxt.y = marketBtn.y + 140;
startScreenContainer.addChild(marketBtnTxt);
// --- Add start screen to game ---
game.addChild(startScreenContainer);
// --- Market Screen (basic, see next block for content) ---
marketScreenContainer.visible = false;
game.addChild(marketScreenContainer);
// --- 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();
// --- Market Skins Data ---
// Ensure skinList is always defined as an array to prevent undefined errors
var skinList = [{
id: "default",
name: "Gri Uçak",
price: 0,
color: 0x888888
}, {
id: "gold",
name: "Altın Uçak",
price: 30,
color: 0xffd700
}, {
id: "blue",
name: "Mavi Uçak",
price: 20,
color: 0x2a6edb
}];
if (!skinList) skinList = [];
// --- Market UI ---
function refreshMarketScreen() {
// Remove all children
while (marketScreenContainer.children.length) {
marketScreenContainer.removeChild(marketScreenContainer.children[0]);
}
// Top right coin (moved from top left)
var coinIconM = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coinIconM.x = 2048 - 160;
coinIconM.y = 120;
marketScreenContainer.addChild(coinIconM);
var coinTxtM = new Text2(currency + '', {
size: 80,
fill: 0xFFD700
});
coinTxtM.anchor.set(0, 0.5);
coinTxtM.x = 2048 - 120;
coinTxtM.y = 120;
marketScreenContainer.addChild(coinTxtM);
// Title
var marketTitle = new Text2("Market", {
size: 200,
fill: 0xFFD700
});
marketTitle.anchor.set(0.5, 0.5);
marketTitle.x = 2048 / 2;
marketTitle.y = 350;
marketScreenContainer.addChild(marketTitle);
// Skins
var y0 = 700;
var x0 = 2048 / 2;
var dx = 500;
for (var i = 0; i < skinList.length; i++) {
var skin = skinList[i];
var x = x0 + (i - 1) * dx;
// Plane asset
var skinAsset = LK.getAsset('playerPlane', {
anchorX: 0.5,
anchorY: 0.5
});
skinAsset.x = x;
skinAsset.y = y0;
skinAsset.tint = skin.color;
skinAsset.scaleX = 1.1;
skinAsset.scaleY = 1.1;
marketScreenContainer.addChild(skinAsset);
// Name
var skinName = new Text2(skin.name, {
size: 70,
fill: "#fff"
});
skinName.anchor.set(0.5, 0.5);
skinName.x = x;
skinName.y = y0 + 120;
marketScreenContainer.addChild(skinName);
// Button
var btnTxt, btnColor;
var unlocked = storage.unlockedSkins && storage.unlockedSkins.indexOf(skin.id) !== -1;
var selected = storage.selectedSkin === skin.id;
if (selected) {
btnTxt = "Seçili";
btnColor = "#44ff44";
} else if (unlocked) {
btnTxt = "Seç";
btnColor = "#fff";
} else {
btnTxt = skin.price + " Coin";
btnColor = "#FFD700";
}
var btn = new Text2(btnTxt, {
size: 60,
fill: btnColor
});
btn.anchor.set(0.5, 0.5);
btn.x = x;
btn.y = y0 + 220;
btn.interactive = true;
btn.skinId = skin.id;
btn.on('down', function (x, y, obj) {
var sid = obj.skinId;
var s = null;
for (var j = 0; j < skinList.length; j++) {
if (skinList[j].id === sid) s = skinList[j];
}
if (!s) return;
// Defensive: ensure unlockedSkins is always an array
if (!Array.isArray(storage.unlockedSkins)) storage.unlockedSkins = ["default"];
var unlocked = storage.unlockedSkins.indexOf(s.id) !== -1;
if (storage.selectedSkin === s.id) return;
if (unlocked) {
storage.selectedSkin = s.id;
player.skin = s.id;
player.updateSkin();
refreshMarketScreen();
} else if (currency >= s.price) {
currency -= s.price;
storage.currency = currency;
// Only add if not already unlocked
if (storage.unlockedSkins.indexOf(s.id) === -1) {
storage.unlockedSkins.push(s.id);
}
storage.selectedSkin = s.id;
player.skin = s.id;
player.updateSkin();
// Update all coin displays after purchase
coinTxt.setText(currency + '');
coinTxtBL.setText(currency + '');
coinTxtTL.setText(currency + '');
refreshMarketScreen();
}
});
marketScreenContainer.addChild(btn);
}
// Back button
var backBtn = new Text2("Geri", {
size: 80,
fill: "#fff"
});
backBtn.anchor.set(0.5, 0.5);
backBtn.x = 2048 / 2;
backBtn.y = 2000;
backBtn.interactive = true;
backBtn.on('down', function (x, y, obj) {
showStartScreen();
});
marketScreenContainer.addChild(backBtn);
}
// --- Show/Hide Screens ---
function showStartScreen() {
gameState = "start";
startScreenContainer.visible = true;
marketScreenContainer.visible = false;
setGameGuiVisible(false);
player.visible = false;
if (typeof coinTxtTL !== "undefined" && coinTxtTL) coinTxtTL.setText(currency + '');
}
function showMarketScreen() {
gameState = "market";
startScreenContainer.visible = false;
marketScreenContainer.visible = true;
setGameGuiVisible(false);
player.visible = false;
refreshMarketScreen();
}
function startGame() {
gameState = "playing";
startScreenContainer.visible = false;
marketScreenContainer.visible = false;
setGameGuiVisible(true);
player.visible = true;
// Reset player position and health
player.x = 2048 / 2;
player.y = 2732 - 350;
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();
});
marketBtn.interactive = true;
marketBtn.on('down', function (x, y, obj) {
showMarketScreen();
});
// --- 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 + '');
}
if (typeof coinTxtTL !== "undefined") {
coinTxtTL.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)
if (r < 0.15) {
enemy = new CoinEnemy();
} else if (r < 0.5) {
enemy = new EnemyRed();
} else if (r < 0.8) {
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
if (LK.ticks % 5 === 0) {
player.shoot();
}
// Player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
// Remove if off screen
if (b.y < -50) {
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);
}
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);
}
// Health drops: move, check pickup, remove if off screen
for (var i = healthDrops.length - 1; i >= 0; i--) {
var h = healthDrops[i];
h.update();
// Remove if off screen
if (h.y > 2732 + 80) {
h.destroy();
healthDrops.splice(i, 1);
continue;
}
// Check pickup by player (only on the frame it starts intersecting)
if (!h.lastWasIntersecting && h.intersects(player)) {
player.heal(2);
// Optional: show a green popup
showScorePopup(h.x, h.y, "+Can");
h.destroy();
healthDrops.splice(i, 1);
continue;
}
h.lastWasIntersecting = h.intersects(player);
}
// 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: none (endless), but could be added
};
// --- 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.
});
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