/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Coin (altın) kutusu
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGfx = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = coinGfx.width * 0.5;
self.update = function () {
// Hafifçe döndür
coinGfx.rotation += 0.12;
};
return self;
});
// Düşman karakteri (AI) - Enemy1: Kendini iyileştirme yeteneği
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemyGfx.width * 0.5;
self.type = 1;
self.speed = 3 + Math.random() * 2;
self.dir = Math.random() * Math.PI * 2;
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
self.targetX = 0;
self.targetY = 0;
self.maxHealth = 3 + Math.floor(Math.random() * 2); // 3-4 can
self.health = self.maxHealth;
// --- YENİ: Kendini iyileştirme özelliği ---
self.healCooldown = 180 + Math.floor(Math.random() * 120); // 3-5 saniyede bir
// --- KOMİK KONUŞMA BALONU ---
// Funny lines (ENGLISH + EMOJIS)
self._funnyLines = ["You can't catch me! 🏃♂️💨", "That tickles! 😂", "I'm about to explode! 💥", "Alien or comedian? 👽🤡", "Look, I'm dancing! 🕺", "Don't shoot, I'm friendly! ✌️", "Tea break time! 🍵", "Beep bop! Error! 🤖", "Are you a hero or a clown? 🦸♂️🤡", "Leveling up soon! ⏫", "Oops, wrong galaxy! 💫", "Pizza delivery! 🍕", "I want a burger! 🍔", "Insert coin to continue! 👾", "Dance battle, anyone? 💃", "Quack! Wrong sound? 🦆", "Say cheese! 🧀", "Rawr! I'm a tiny dino. 🦖", "Brain freeze! 🧠❄️", "Crab rave time! 🦀🎶", "Hoot hoot! Night shift. 🦉", "I floss daily. 🦷", "To the moon! 🚀", "Catch me if you can! 😜", "This is my serious face. 🥸"];
self._speechBubble = null;
self._speechTimer = 0;
self._showSpeech = function (text) {
// Eski balon varsa sil
if (self._speechBubble) {
self._speechBubble.destroy();
self._speechBubble = null;
}
var bubble = new Text2(text, {
size: 48,
fill: 0xffffff,
font: "Impact"
});
bubble.anchor.set(0.5, 1);
bubble.x = self.x;
bubble.y = self.y - self.radius - 60;
bubble.alpha = 1;
game.addChild(bubble);
self._speechBubble = bubble;
// Balonu 1.2 saniyede kaybolacak şekilde animasyonla
tween(bubble, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
if (bubble) bubble.visible = false;
if (self._speechBubble === bubble) self._speechBubble = null;
}
});
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffff00, 200);
// Komik konuşma: Hasar alınca %60 ihtimalle konuşsun
if (Math.random() < 0.6) {
var line = self._funnyLines[Math.floor(Math.random() * self._funnyLines.length)];
self._showSpeech(line);
}
if (self.health <= 0) {
// Destroy health bar if exists
if (self._healthBar) {
self._healthBar.destroy();
self._healthBar = null;
}
// Destroy visible health bar if exists
if (self._visHealthBar) {
self._visHealthBar.destroy();
self._visHealthBar = null;
self._visHealthBarBg = null;
self._visHealthBarFg = null;
}
self.destroy();
// Skor boost varsa 2 puan ver
if (player._superScoreBoost && player._scoreBoost > 0) {
score += 10 + (comboCount > 1 ? comboCount : 0);
} else if (player._scoreBoost && player._scoreBoost > 0) {
score += 2 + (comboCount > 1 ? comboCount : 0);
} else {
score += 1 + (comboCount > 1 ? comboCount : 0);
}
updateScoreAndLevel();
if (score > 0 && score % 10 === 0) {
increaseDifficulty();
}
// Remove from enemies array in main loop
self._shouldRemove = true;
}
};
self.update = function () {
if (self._frozen && self._frozen > 0) {
// Donmuşsa titret
self.x += Math.sin(self._frozen) * 2;
self.y += Math.cos(self._frozen) * 2;
return;
}
// --- YENİ: Kendini iyileştirme ---
if (self.healCooldown > 0) {
self.healCooldown--;
} else {
if (self.health < self.maxHealth) {
self.health++;
LK.effects.flashObject(self, 0x00ff00, 200);
}
self.healCooldown = 180 + Math.floor(Math.random() * 120);
}
// Basit AI: Oyuncuya doğru hareket et
var dx = player.x - self.x;
var dy = player.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 1) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Ateş etme
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shootCooldown = 90 + Math.floor(Math.random() * 60);
spawnEnemyBullet(self.x, self.y, player.x, player.y);
}
// --- KOMİK KONUŞMA: Rastgele aralıklarla konuşsun ---
// Her update'de sayaç azalt, 0 olunca konuş
if (self._speechTimer > 0) {
self._speechTimer--;
} else if (Math.random() < 0.01) {
// %1 ihtimalle her frame
var line = self._funnyLines[Math.floor(Math.random() * self._funnyLines.length)];
self._showSpeech(line);
self._speechTimer = 180 + Math.floor(Math.random() * 120); // 3-5 saniye bekle
}
// --- HEALTH BAR (rectangle) ---
// Create health bar if not exists
if (!self._visHealthBar) {
self._visHealthBar = new Container();
self._visHealthBarBg = new Container();
self._visHealthBarFg = new Container();
self._visHealthBar.addChild(self._visHealthBarBg);
self._visHealthBar.addChild(self._visHealthBarFg);
game.addChild(self._visHealthBar);
}
if (self._visHealthBar) {
// Position above enemy
self._visHealthBar.x = self.x;
self._visHealthBar.y = self.y - self.radius - 28;
// Health percent
var hp = Math.max(0, self.health) / self.maxHealth;
// Clamp width
var fgWidth = Math.max(24, 180 * hp);
self._visHealthBarFg.width = fgWidth;
// Color: green > yellow > red
if (hp > 0.6) {
self._visHealthBarFg.tint = 0x00ff00;
} else if (hp > 0.3) {
self._visHealthBarFg.tint = 0xffe100;
} else {
self._visHealthBarFg.tint = 0xff4444;
}
self._visHealthBar.visible = true;
}
// Konuşma balonunu takip ettir
if (self._speechBubble) {
self._speechBubble.x = self.x;
self._speechBubble.y = self.y - self.radius - 60;
}
};
return self;
});
// Düşman karakteri 2 (dairesel hareket, elips) - Enemy2: Kalkan oluşturma yeteneği
var Enemy2 = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy2', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemyGfx.width * 0.5;
self.type = 2;
self.angle = Math.random() * Math.PI * 2;
// Enemy2: Orbit around a random point in the arena, not the player
self.centerX = 200 + Math.random() * 1648;
self.centerY = 200 + Math.random() * 2332;
self.orbitRadius = 400 + Math.random() * 200;
self.speed = 0.012 + Math.random() * 0.008;
self.shootCooldown = 120 + Math.floor(Math.random() * 60);
self.maxHealth = 4 + Math.floor(Math.random() * 2); // 4-5 can
self.health = self.maxHealth;
// --- YENİ: Kalkan özelliği ---
self.shield = 0;
self.shieldCooldown = 240 + Math.floor(Math.random() * 120); // 4-6 saniyede bir
self.takeDamage = function (amount) {
if (self.shield > 0) {
self.shield--;
LK.effects.flashObject(self, 0x00ffff, 200);
return;
}
self.health -= amount;
LK.effects.flashObject(self, 0xffff00, 200);
if (self.health <= 0) {
// Destroy health bar if exists
if (self._healthBar) {
self._healthBar.destroy();
self._healthBar = null;
}
// Destroy visible health bar if exists
if (self._visHealthBar) {
self._visHealthBar.destroy();
self._visHealthBar = null;
self._visHealthBarBg = null;
self._visHealthBarFg = null;
}
self.destroy();
if (player._scoreBoost && player._scoreBoost > 0) {
score += 2 + (comboCount > 1 ? comboCount : 0);
} else {
score += 1 + (comboCount > 1 ? comboCount : 0);
}
updateScoreAndLevel();
if (score > 0 && score % 10 === 0) {
increaseDifficulty();
}
self._shouldRemove = true;
}
};
self.update = function () {
if (self._frozen && self._frozen > 0) {
self.x += Math.sin(self._frozen) * 2;
self.y += Math.cos(self._frozen) * 2;
return;
}
// --- YENİ: Kalkan oluşturma ---
if (self.shieldCooldown > 0) {
self.shieldCooldown--;
} else {
self.shield = 2; // 2 vuruşluk kalkan
self.shieldCooldown = 240 + Math.floor(Math.random() * 120);
LK.effects.flashObject(self, 0x00ffff, 200);
}
// Kalkan efekti için: kalkanı varsa hafif mavi tint
if (self.shield > 0 && enemyGfx) {
enemyGfx.alpha = 0.7;
} else if (enemyGfx) {
enemyGfx.alpha = 1.0;
}
self.angle += self.speed;
self.x = self.centerX + Math.cos(self.angle) * self.orbitRadius;
self.y = self.centerY + Math.sin(self.angle) * self.orbitRadius;
// Ateş etme
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shootCooldown = 120 + Math.floor(Math.random() * 60);
spawnEnemyBullet(self.x, self.y, player.x, player.y);
}
// --- HEALTH BAR (rectangle) ---
// Create health bar if not exists
if (!self._visHealthBar) {
self._visHealthBar = new Container();
self._visHealthBarBg = new Container();
self._visHealthBarFg = new Container();
self._visHealthBar.addChild(self._visHealthBarBg);
self._visHealthBar.addChild(self._visHealthBarFg);
game.addChild(self._visHealthBar);
}
if (self._visHealthBar) {
// Position above enemy
self._visHealthBar.x = self.x;
self._visHealthBar.y = self.y - self.radius - 28;
// Health percent
var hp = Math.max(0, self.health) / self.maxHealth;
// Clamp width
var fgWidth = Math.max(24, 180 * hp);
self._visHealthBarFg.width = fgWidth;
// Color: green > yellow > red
if (hp > 0.6) {
self._visHealthBarFg.tint = 0x00ff00;
} else if (hp > 0.3) {
self._visHealthBarFg.tint = 0xffe100;
} else {
self._visHealthBarFg.tint = 0xff4444;
}
self._visHealthBar.visible = true;
}
};
return self;
});
// Düşman karakteri 3 (rastgele zıplama, mor kutu) - Enemy3: Ölünce ikiye bölünme yeteneği
var Enemy3 = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy3', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemyGfx.width * 0.5;
self.type = 3;
self.jumpTimer = 60 + Math.floor(Math.random() * 60);
self.targetX = 200 + Math.random() * 1648;
self.targetY = 200 + Math.random() * 2332;
self.speed = 12 + Math.random() * 6;
self.shootCooldown = 100 + Math.floor(Math.random() * 60);
self.maxHealth = 2 + Math.floor(Math.random() * 2); // 2-3 can
self.health = self.maxHealth;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffff00, 200);
if (self.health <= 0) {
// Destroy health bar if exists
if (self._healthBar) {
self._healthBar.destroy();
self._healthBar = null;
}
// Destroy visible health bar if exists
if (self._visHealthBar) {
self._visHealthBar.destroy();
self._visHealthBar = null;
self._visHealthBarBg = null;
self._visHealthBarFg = null;
}
// Splitting on death removed
self.destroy();
if (player._scoreBoost && player._scoreBoost > 0) {
score += 2 + (comboCount > 1 ? comboCount : 0);
} else {
score += 1 + (comboCount > 1 ? comboCount : 0);
}
updateScoreAndLevel();
if (score > 0 && score % 10 === 0) {
increaseDifficulty();
}
self._shouldRemove = true;
}
};
self.update = function () {
if (self._frozen && self._frozen > 0) {
self.x += Math.sin(self._frozen) * 2;
self.y += Math.cos(self._frozen) * 2;
return;
}
self.jumpTimer--;
if (self.jumpTimer <= 0) {
self.targetX = 200 + Math.random() * 1648;
self.targetY = 200 + Math.random() * 2332;
self.jumpTimer = 60 + Math.floor(Math.random() * 60);
}
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 1) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Ateş etme
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shootCooldown = 100 + Math.floor(Math.random() * 60);
spawnEnemyBullet(self.x, self.y, player.x, player.y);
}
// --- HEALTH BAR (rectangle) ---
// Create health bar if not exists
if (!self._visHealthBar) {
self._visHealthBar = new Container();
self._visHealthBarBg = new Container();
self._visHealthBarFg = new Container();
self._visHealthBar.addChild(self._visHealthBarBg);
self._visHealthBar.addChild(self._visHealthBarFg);
game.addChild(self._visHealthBar);
}
if (self._visHealthBar) {
// Position above enemy
self._visHealthBar.x = self.x;
self._visHealthBar.y = self.y - self.radius - 28;
// Health percent
var hp = Math.max(0, self.health) / self.maxHealth;
// Clamp width
var fgWidth = Math.max(24, 180 * hp);
self._visHealthBarFg.width = fgWidth;
// Color: green > yellow > red
if (hp > 0.6) {
self._visHealthBarFg.tint = 0x00ff00;
} else if (hp > 0.3) {
self._visHealthBarFg.tint = 0xffe100;
} else {
self._visHealthBarFg.tint = 0xff4444;
}
self._visHealthBar.visible = true;
}
};
return self;
});
// Düşman mermisi
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletGfx.width * 0.5;
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Oyuncu karakteri
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGfx = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = playerGfx.width * 0.5;
self.shootCooldown = 0;
// Oyuncuya can ekle
self.maxHealth = typeof playerMaxHealth !== "undefined" ? playerMaxHealth : 5;
self.health = typeof playerHealth !== "undefined" ? playerHealth : self.maxHealth;
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
};
return self;
});
// Oyuncu mermisi
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletGfx.width * 0.5;
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Güçlendirici (PowerUp) kutusu
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerGfx = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = powerGfx.width * 0.5;
self.type = "power";
// Yeni powerup efektleri eklendi
var effects = ["rapid",
// Hızlı ateş (fire rate)
"triple",
// Üçlü atış
"shield",
// Kalkan
"heal",
// Can doldur
"wallBounce",
// Duvar sekme
"reflect",
// Düşman mermisi sektirme
"slow",
// Zaman yavaşlatma (tüm düşmanlar yavaşlar)
"magnet",
// Magnet (yakındaki coin/powerup çeker)
"randomizer",
// Randomizer (tüm düşmanların tipi değişir)
"superHeal",
// Süper can: max canı artır ve doldur
"freezeBullets",
// Düşman mermilerini dondur
"coinRain",
// Ekrana coin yağmuru
"enemyClear",
// Tüm düşmanları yok et
"scoreBoost" // Skor 2x (15s)
];
self.effect = effects[Math.floor(Math.random() * effects.length)];
self.update = function () {
// Hafifçe döndür
powerGfx.rotation += 0.08;
};
return self;
});
// PowerUpCombo: Birleşmiş poweruplar için özel kutu
var PowerUpCombo = Container.expand(function () {
var self = Container.call(this);
var powerGfx = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = powerGfx.width * 0.6;
self.type = "powerCombo";
self.effects = []; // ["rapid", "triple", ...]
self.update = function () {
// Hafifçe döndür ve renk değiştir (her efekt için farklı renkler)
powerGfx.rotation += 0.12;
// Renkleri birleştir: efekt sayısına göre tint değiştir
if (self.effects.indexOf("slow") !== -1 && self.effects.length === 1) {
powerGfx.tint = 0x66ccff; // Mavi (slow)
} else if (self.effects.indexOf("magnet") !== -1 && self.effects.length === 1) {
powerGfx.tint = 0xff00ff; // Magnet için mor
} else if (self.effects.indexOf("randomizer") !== -1 && self.effects.length === 1) {
powerGfx.tint = 0x00ffcc; // Randomizer için turkuaz
} else if (self.effects.length === 2) {
powerGfx.tint = 0xFFD700; // Altın
} else if (self.effects.length >= 3) {
powerGfx.tint = 0xFF44FF; // Pembe
} else {
powerGfx.tint = 0xFFFFFF;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0074D9
});
/****
* Game Code
****/
// Space background images (add your own image asset IDs as needed)
// --- SPACE BACKGROUND ---
// Global değişkenler
// Space backgrounds as assets
var spaceBackgrounds = [{
id: 'spacebg1',
width: 2048,
height: 2732,
assetId: '682e6b2ad10b0c0b481370a1'
}, {
id: 'spacebg2',
width: 2048,
height: 2732,
assetId: '682e6b3fd10b0c0b481370a2'
}, {
id: 'spacebg3',
width: 2048,
height: 2732,
assetId: '682e6b4ad10b0c0b481370a3'
}];
// Register background assets (engine will load them automatically)
for (var i = 0; i < spaceBackgrounds.length; i++) {}
// Pick a random background
var selectedBg = spaceBackgrounds[Math.floor(Math.random() * spaceBackgrounds.length)];
var bgSprite = LK.getAsset(selectedBg.id, {
anchorX: 0,
anchorY: 0
});
bgSprite.x = 0;
bgSprite.y = 0;
bgSprite.width = 2048;
bgSprite.height = 2732;
game.addChildAt(bgSprite, 0); // Add as the bottom-most layer
// Coin asset
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var powerUps = [];
var coins = []; // Coin objects
var coinCount = 0; // Collected coin count
var coinTxt = new Text2('₵ ' + coinCount, {
size: 70,
fill: 0xFFD700,
font: "Impact"
});
coinTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(coinTxt);
coinTxt.y = 340;
var powerActive = false;
var powerTimer = 0;
var dragNode = null;
var lastPlayerPos = {
x: 0,
y: 0
};
var score = 0;
var level = 1;
var gameTick = 0;
var spawnTimer = 0;
var isGameOver = false;
// Combo variables
var comboCount = 0;
var comboTimer = 0;
var maxComboTime = 120; // 2 seconds (120 frames)
var maxCombo = 0;
// Combo GUI
var comboTxt = new Text2('', {
size: 80,
fill: 0xFFFA00,
font: "Impact"
});
comboTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(comboTxt);
comboTxt.y = 260;
// Health bar variables
// Permanent max health and max attack upgrades RESET
storage.permMaxHealthUp = 0;
storage.permMaxAttackUp = 0;
// Permanent max health upgrade from storage
var permHealthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
var playerMaxHealth = 10 + permHealthUp;
var playerHealth = playerMaxHealth;
// Health bar GUI
var healthTxt = new Text2('Health: ' + playerHealth, {
size: 70,
fill: 0xFF4444
});
healthTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(healthTxt);
healthTxt.y = 180;
// --- HOW TO PLAY POPUP (before game starts) ---
var howToPlayTxt = new Text2("Nasıl Oynanır?\n\n" + "- Parmağınızı ekrana basılı tutup karakterinizi ARENADA sürükleyin.\n" + "- Düşmanlardan ve mermilerden kaçın, otomatik ateşle düşmanları yok edin!\n" + "- Güçlendiricileri (PowerUp) ve altınları toplayın.\n" + "- Kombo yaparak daha fazla puan kazanın.\n" + "- Sol üstte istatistiklerinizi takip edin.\n\n" + "Başlamak için ekrana dokunun!", {
size: 70,
fill: "#fff",
font: "Impact",
align: "center",
wordWrap: true,
wordWrapWidth: 1600
});
howToPlayTxt.anchor.set(0.5, 0.5);
howToPlayTxt.x = 2048 / 2;
howToPlayTxt.y = 2732 / 2;
howToPlayTxt.background = {
color: 0x222244,
alpha: 0.92,
padding: 60,
radius: 48
};
LK.gui.center.addChild(howToPlayTxt);
// Oyuncu dokununca başlat
var howToPlayActive = true;
game.down = function (x, y, obj) {
if (howToPlayActive) {
howToPlayActive = false;
howToPlayTxt.visible = false;
startGame();
} else {
// If player is tapped, start dragging
var px = player.x,
py = player.y;
var dx = x - px,
dy = y - py;
var dist = Math.sqrt(dx * dx + dy * dy);
// User-friendly: If tapped on player, start dragging, otherwise do nothing
if (dist < player.radius + 80) {
// wider area, easier drag
dragNode = player;
lastPlayerPos.x = x;
lastPlayerPos.y = y;
// When drag starts, don't fire, prevent accidental fire
// Drag threshold: set a flag to check if drag distance exceeds a threshold before firing
dragNode._dragStarted = false;
dragNode._dragStartX = x;
dragNode._dragStartY = y;
dragNode._dragStartTime = Date.now();
} else {
// (Removed: tap-to-shoot code is now gone)
}
}
};
// --- OYUNU BAŞLAT ---
function startGame() {
// Oyun değişkenlerini sıfırla
isInMainMenu = false; // Oyun başlarken menüden çık
score = 0;
level = 1;
// Apply permanent max health upgrade from storage
var permHealthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
playerMaxHealth = 10 + permHealthUp;
playerHealth = playerMaxHealth;
enemies = [];
playerBullets = [];
enemyBullets = [];
powerUps = [];
coins = [];
powerActive = false;
powerTimer = 0;
comboCount = 0;
comboTimer = 0;
maxCombo = 0;
isGameOver = false;
gameTick = 0;
spawnTimer = 0;
dragNode = null;
lastPlayerPos = {
x: 0,
y: 0
};
// Apply permanent max attack upgrade from storage
var permAttackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
if (typeof player !== "undefined") {
player._permAttackUp = permAttackUp;
}
// Ultra power effect text clear
if (typeof setUltraPowerEffectText === "function") setUltraPowerEffectText('');
if (typeof currentUltraPowerEffect !== "undefined") currentUltraPowerEffect = "";
// GUI güncelle
updateScoreAndLevel();
updateStatsPanel();
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + (typeof storage.coins === "number" ? storage.coins : 0));
if (typeof player !== "undefined") {
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
}
// Oyuncu konumunu sıfırla
if (typeof player !== "undefined") {
player.x = 2048 / 2;
player.y = 2732 / 2;
}
}
// Play background music (loops by default)
LK.playMusic('musicId');
// PowerUp oluşturucu
function spawnPowerUp() {
var p = new PowerUp();
// Güvenli alan içinde rastgele konum
p.x = 200 + Math.random() * 1648;
p.y = 200 + Math.random() * 2332;
powerUps.push(p);
game.addChild(p);
}
// Coin oluşturucu
function spawnCoin(x, y) {
var c = new Coin();
// Eğer x, y verilmişse oraya koy, yoksa rastgele
if (typeof x === "number" && typeof y === "number") {
c.x = x;
c.y = y;
} else {
c.x = 200 + Math.random() * 1648;
c.y = 200 + Math.random() * 2332;
}
coins.push(c);
game.addChild(c);
}
// Score and level display
var scoreTxt = new Text2('Score: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: "#fff"
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 100;
// Eğlenceli: Arena event popup
var eventPopupTxt = new Text2('', {
size: 70,
fill: 0xFFFA00,
font: "Impact"
});
eventPopupTxt.anchor.set(0.5, 0.5);
eventPopupTxt.visible = false;
LK.gui.center.addChild(eventPopupTxt);
// Arena event popup function (already in English, nothing to change)
function showArenaEventPopup(msg) {
eventPopupTxt.setText(msg);
eventPopupTxt.visible = true;
eventPopupTxt.alpha = 1;
tween(eventPopupTxt, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
eventPopupTxt.visible = false;
}
});
}
// Oyuncu oluştur
player = new Player();
game.addChild(player);
player.x = 2048 / 2;
player.y = 2732 / 2;
// Apply permanent max attack upgrade from storage on initial load
var permAttackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
player._permAttackUp = permAttackUp;
// Düşman oluşturucu
function spawnEnemy() {
var t = Math.random();
var e;
if (t < 0.4) {
e = new Enemy();
} else if (t < 0.7) {
e = new Enemy2();
} else {
e = new Enemy3();
}
// --- FUNNY SPEECH BUBBLE ON SPAWN (with emojis) ---
var funnySpawnLines = ["👽 Boo! Did I scare you?", "😂 I'm too cute to shoot!", "🍕 Pizza time! Wait, no pizza?", "🦄 I'm a unicorn in disguise!", "💩 Oops, wrong galaxy!", "🤡 Who invited the clown?", "🕺 Dance battle, anyone?", "🐸 Ribbit! Oh wait, I'm not a frog.", "🚀 To the moon! ...or not.", "😜 Catch me if you can!", "🥸 This is my serious face.", "🧀 Say cheese!", "🦖 Rawr! I'm a tiny dino.", "👾 Insert coin to continue!", "🦆 Quack! Wrong sound?", "🍔 I want a burger!", "🧠 Brain freeze!", "🦷 I floss daily.", "🦀 Crab rave time!", "🦉 Hoot hoot! Night shift."];
if (typeof e._showSpeech === "function") {
var spawnLine = funnySpawnLines[Math.floor(Math.random() * funnySpawnLines.length)];
e._showSpeech(spawnLine);
}
// Enemies get stronger: health increases with level and score
if (typeof e.maxHealth !== "undefined") {
// Her 3 level'da +1 can, her 20 skor'da +1 can
var extraHealth = Math.floor(level / 3) + Math.floor(score / 20);
e.maxHealth += extraHealth;
e.health = e.maxHealth;
}
// Randomly spawn from edge
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// top
e.x = 200 + Math.random() * 1648;
e.y = -100;
} else if (edge === 1) {
// right
e.x = 2148;
e.y = 200 + Math.random() * 2332;
} else if (edge === 2) {
// bottom
e.x = 200 + Math.random() * 1648;
e.y = 2832;
} else {
// left
e.x = -100;
e.y = 200 + Math.random() * 2332;
}
enemies.push(e);
game.addChild(e);
}
// Düşman mermisi oluşturucu
function spawnEnemyBullet(sx, sy, tx, ty) {
var b = new EnemyBullet();
b.x = sx;
b.y = sy;
var dx = tx - sx;
var dy = ty - sy;
var dist = Math.sqrt(dx * dx + dy * dy);
var speed = 9 + level * 1; // Düşman mermisi hızı azaltıldı
b.vx = dx / dist * speed;
b.vy = dy / dist * speed;
enemyBullets.push(b);
game.addChild(b);
}
// Oyuncu mermisi oluşturucu
function spawnPlayerBullet(sx, sy, tx, ty) {
var b = new PlayerBullet();
b.x = sx;
b.y = sy;
var dx = tx - sx;
var dy = ty - sy;
var dist = Math.sqrt(dx * dx + dy * dy);
var speed = 32;
b.vx = dx / dist * speed;
b.vy = dy / dist * speed;
playerBullets.push(b);
game.addChild(b);
LK.getSound('shoot').play();
}
// Skor ve seviye güncelle
function updateScoreAndLevel() {
if (typeof scoreTxt !== "undefined" && scoreTxt && typeof scoreTxt.setText === "function") {
if (scoreTxt._lastScore !== score) {
scoreTxt.setText('Score: ' + score);
scoreTxt._lastScore = score;
}
}
if (typeof levelTxt !== "undefined" && levelTxt && typeof levelTxt.setText === "function") {
if (levelTxt._lastLevel !== level) {
levelTxt.setText('Level: ' + level);
levelTxt._lastLevel = level;
}
}
if (typeof healthTxt !== "undefined" && healthTxt && typeof healthTxt.setText === "function") {
if (healthTxt._lastHealth !== playerHealth) {
healthTxt.setText('Health: ' + playerHealth);
healthTxt._lastHealth = playerHealth;
}
}
updateComboText();
}
// Kombo GUI güncelle
function updateComboText() {
if (comboCount > 1) {
if (comboTxt._lastCombo !== comboCount) {
comboTxt.setText("COMBO x" + comboCount + "!");
comboTxt.visible = true;
comboTxt.alpha = 1;
comboTxt._lastCombo = comboCount;
}
} else {
if (comboTxt.visible) {
comboTxt.visible = false;
comboTxt._lastCombo = 0;
}
}
}
// Oyun zorluğunu artır
function increaseDifficulty() {
level++;
updateScoreAndLevel();
}
// Oyun bitti
function gameOver() {
if (isGameOver) return;
isGameOver = true;
// --- STATISTICS: Update high score and max combo at game over ---
if (score > storage.highScore) {
storage.highScore = score;
}
if (maxCombo > storage.maxCombo) {
storage.maxCombo = maxCombo;
}
updateStatsPanel();
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('hit').play();
LK.showGameOver();
}
// Oyun kazandı
function youWin() {
showArenaEventPopup("YOU WIN! 🎉");
LK.effects.flashScreen(0x00ffcc, 1000);
LK.showYouWin();
}
// Sürükleme ve ateş etme
function handleMove(x, y, obj) {
if (dragNode) {
// Apply movement delta
var dx = x - lastPlayerPos.x;
var dy = y - lastPlayerPos.y;
dragNode.x += dx;
dragNode.y += dy;
// User-friendly: Prevent player from going out of bounds
var minX = dragNode.radius + 20;
var maxX = 2048 - dragNode.radius - 20;
var minY = dragNode.radius + 20;
var maxY = 2732 - dragNode.radius - 20;
if (dragNode.x < minX) dragNode.x = minX;
if (dragNode.x > maxX) dragNode.x = maxX;
if (dragNode.y < minY) dragNode.y = minY;
if (dragNode.y > maxY) dragNode.y = maxY;
lastPlayerPos.x = x;
lastPlayerPos.y = y;
}
}
// Out of bounds check
function isOutOfBounds(obj) {
return obj.x < -200 || obj.x > 2248 || obj.y < -200 || obj.y > 2932;
}
// Oyun ana döngüsü
game.update = function () {
if (isGameOver) return;
gameTick++;
// Fun: Random arena events (e.g. meteor shower, bonus rain, enemy freeze)
// Every 15 seconds, a random event may trigger
if (gameTick % 900 === 0 && gameTick > 0) {
var eventType = Math.floor(Math.random() * 3);
if (eventType === 0) {
// Meteor shower: 10 fast bullets fall from the top
for (var m = 0; m < 10; m++) {
var b = new EnemyBullet();
b.x = 200 + Math.random() * 1648;
b.y = -80 - m * 60;
b.vx = 0;
b.vy = 32 + Math.random() * 8;
enemyBullets.push(b);
game.addChild(b);
}
// Short effect
LK.effects.flashScreen(0xffa500, 400);
showArenaEventPopup("Meteor Shower!");
} else if (eventType === 1) {
// Bonus rain: 5 powerUps drop at once
for (var p = 0; p < 5; p++) {
var pu = new PowerUp();
pu.x = 200 + Math.random() * 1648;
pu.y = 200 + Math.random() * 2332;
powerUps.push(pu);
game.addChild(pu);
}
LK.effects.flashScreen(0x00ffcc, 400);
showArenaEventPopup("Bonus Rain!");
} else if (eventType === 2) {
// Enemies freeze for 3 seconds
for (var i = 0; i < enemies.length; i++) {
enemies[i]._frozen = 180; // 3 seconds
}
LK.effects.flashScreen(0x66ccff, 400);
showArenaEventPopup("Enemies Frozen!");
}
}
// Düşmanları dondurma efekti uygula
for (var i = 0; i < enemies.length; i++) {
if (enemies[i]._frozen && enemies[i]._frozen > 0) {
enemies[i]._frozen--;
continue; // update çağrılmasın, düşman hareket etmesin
}
}
// Oyuncu update
player.update();
// Oyuncu canını playerHealth ile senkronize et
if (typeof player.health !== "undefined" && typeof playerHealth !== "undefined" && player.health !== playerHealth) {
player.health = playerHealth;
}
if (typeof player.maxHealth !== "undefined" && typeof playerMaxHealth !== "undefined" && player.maxHealth !== playerMaxHealth) {
player.maxHealth = playerMaxHealth;
}
// --- Attack Speed Bonus: Stacks with powerups ---
if (typeof player._attackSpeedBonus === "undefined") player._attackSpeedBonus = 0;
// Otomatik ateş etme (her 10 frame'de bir, rapid fire veya attack speed bonus varsa daha hızlı)
var baseShootInterval = 10;
var rapidFireInterval = powerActive ? 4 : baseShootInterval;
var attackSpeedInterval = Math.max(2, rapidFireInterval - player._attackSpeedBonus * 2);
var shootInterval = attackSpeedInterval;
if (!isGameOver && gameTick % shootInterval === 0 && enemies.length > 0) {
// En yakın düşmanı bul
var minDist = Infinity;
var targetEnemy = null;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
var dx = e.x - player.x;
var dy = e.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDist) {
minDist = dist;
targetEnemy = e;
}
}
if (targetEnemy) {
// --- Otomatik nişan geliştirme: Düşmanın hareketini tahmin et ---
// Düşmanın bir sonraki pozisyonunu tahmin etmek için basit linear prediction
var bulletSpeed = 32;
var ex = targetEnemy.x;
var ey = targetEnemy.y;
var evx = 0,
evy = 0;
// Tahmini hız: son pozisyonları varsa kullan
if (typeof targetEnemy._lastX === "number" && typeof targetEnemy._lastY === "number") {
evx = targetEnemy.x - targetEnemy._lastX;
evy = targetEnemy.y - targetEnemy._lastY;
}
// Hedefe olan mesafe
var dx = ex - player.x;
var dy = ey - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Zaman tahmini (kaç frame sonra mermi ulaşır)
var t = dist / bulletSpeed;
// Tahmini hedef pozisyonu
var predictedX = ex + evx * t;
var predictedY = ey + evy * t;
// Triple shot powerup varsa üçlü mermi ateşle
if (player._tripleShot && player._tripleShot > 0) {
for (var s = -1; s <= 1; s++) {
var angle = Math.atan2(predictedY - player.y, predictedX - player.x) + s * 0.18;
var tx = player.x + Math.cos(angle) * 1000;
var ty = player.y + Math.sin(angle) * 1000;
spawnPlayerBullet(player.x, player.y, tx, ty);
}
} else {
spawnPlayerBullet(player.x, player.y, predictedX, predictedY);
}
}
}
// Düşman update
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
// Skip update if enemy is destroyed or out of bounds
if (!e || typeof e.destroyed !== "undefined" && e.destroyed) {
if (e && e._healthBar) {
e._healthBar.destroy();
}
enemies.splice(i, 1);
continue;
}
if (isOutOfBounds(e)) {
if (e._healthBar) {
e._healthBar.destroy();
}
e.destroy();
enemies.splice(i, 1);
continue;
}
// --- Otomatik nişan için: Son pozisyonu kaydet ---
e._lastX = typeof e.x === "number" ? e.x : 0;
e._lastY = typeof e.y === "number" ? e.y : 0;
if (typeof e.update === "function") e.update();
// Can barı çizimi (her düşmanın üstünde) - optimize: sadece health değiştiyse güncelle
if (!e._healthBar) {
e._healthBar = new Text2('', {
size: 64,
fill: 0xFF4444,
font: "Impact"
});
e._healthBar.anchor.set(0.5, 1);
game.addChild(e._healthBar);
}
if (typeof e.health !== "undefined" && typeof e.maxHealth !== "undefined") {
if (e._healthBar._lastHealth !== e.health || e._healthBar._lastMaxHealth !== e.maxHealth) {
e._healthBar.setText("♥ " + e.health + "/" + e.maxHealth);
e._healthBar._lastHealth = e.health;
e._healthBar._lastMaxHealth = e.maxHealth;
}
e._healthBar.x = e.x;
e._healthBar.y = e.y - e.radius - 18;
e._healthBar.visible = true;
} else {
e._healthBar.visible = false;
}
// Çarpışma: oyuncu & düşman
if (player.intersects(e)) {
if (player._shield && player._shield > 0) {
player._shield--;
LK.effects.flashObject(player, 0x00ffff, 400);
if (player._shield === 0) {
showArenaEventPopup("Shield Broken!");
} else {
showArenaEventPopup("Shield: " + player._shield + " hits left!");
}
} else {
playerHealth--;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
LK.effects.flashObject(player, 0xff4444, 400);
LK.getSound('hit').play();
if (playerHealth <= 0) {
gameOver();
return;
}
}
// Düşmanı yok et, can azalınca
if (typeof e.takeDamage === "function") {
e.takeDamage(e.health); // Tüm canı gitmeli
if (e._shouldRemove) {
if (e._healthBar) {
e._healthBar.destroy();
}
// COIN: Düşman öldüğünde coin spawn et
var baseCoinChance = 0.7;
var extraChance = Math.min(comboCount * 0.10, 0.5);
if (Math.random() < baseCoinChance + extraChance) {
spawnCoin(e.x, e.y);
}
// --- PowerUp drop şansı: %20 + kombo başına %4, max %40 ---
var basePowerUpChance = 0.20;
var extraPowerUpChance = Math.min(comboCount * 0.04, 0.20);
if (Math.random() < basePowerUpChance + extraPowerUpChance) {
spawnPowerUp();
if (powerUps.length > 0) {
var pu = powerUps[powerUps.length - 1];
pu.x = e.x;
pu.y = e.y;
}
}
enemies.splice(i, 1);
// KOMBO: Düşman öldürdüyse kombo başlat
if (typeof e._killedByPlayer === "undefined" || e._killedByPlayer) {
comboCount++;
comboTimer = maxComboTime;
if (comboCount > maxCombo) maxCombo = comboCount;
if (comboCount > storage.maxCombo) {
storage.maxCombo = comboCount;
updateStatsPanel();
}
storage.totalEnemiesKilled = (typeof storage.totalEnemiesKilled === "number" ? storage.totalEnemiesKilled : 0) + 1;
updateStatsPanel();
updateComboText();
}
continue;
}
} else {
e.destroy();
if (e._healthBar) {
e._healthBar.destroy();
}
// COIN: Düşman öldüğünde coin spawn et
var baseCoinChance = 0.7;
var extraChance = Math.min(comboCount * 0.10, 0.5);
if (Math.random() < baseCoinChance + extraChance) {
spawnCoin(e.x, e.y);
}
// --- PowerUp drop şansı: %20 + kombo başına %4, max %40 ---
var basePowerUpChance = 0.20;
var extraPowerUpChance = Math.min(comboCount * 0.04, 0.20);
if (Math.random() < basePowerUpChance + extraPowerUpChance) {
spawnPowerUp();
if (powerUps.length > 0) {
var pu = powerUps[powerUps.length - 1];
pu.x = e.x;
pu.y = e.y;
}
}
enemies.splice(i, 1);
comboCount++;
comboTimer = maxComboTime;
if (comboCount > maxCombo) maxCombo = comboCount;
if (comboCount > storage.maxCombo) {
storage.maxCombo = comboCount;
updateStatsPanel();
}
storage.totalEnemiesKilled = (typeof storage.totalEnemiesKilled === "number" ? storage.totalEnemiesKilled : 0) + 1;
updateStatsPanel();
updateComboText();
continue;
}
}
}
// Oyuncu mermisi update
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
// Skip update if bullet is destroyed or out of bounds
if (!b || typeof b.destroyed !== "undefined" && b.destroyed) {
playerBullets.splice(i, 1);
continue;
}
if (isOutOfBounds(b)) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
if (typeof b.update === "function") b.update();
var hit = false;
// Düşmanlara çarpma
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
LK.getSound('hit').play();
if (typeof e.takeDamage === "function") {
e._killedByPlayer = true;
var permAttackUp = typeof player._permAttackUp === "number" ? player._permAttackUp : 0;
var bulletDamage = 2 + permAttackUp;
e.takeDamage(bulletDamage);
if (e._shouldRemove) {
enemies.splice(j, 1);
}
}
hit = true;
break;
}
}
// WALL BOUNCE: Eğer aktifse, mermi kenara çarptıysa sekmeli
var wallBounceActive = player._wallBounce && player._wallBounce > 0;
if (!hit && wallBounceActive) {
var bounced = false;
if (b.x < b.radius + 10 && b.vx < 0) {
b.x = b.radius + 10;
b.vx *= -1;
bounced = true;
}
if (b.x > 2048 - b.radius - 10 && b.vx > 0) {
b.x = 2048 - b.radius - 10;
b.vx *= -1;
bounced = true;
}
if (b.y < b.radius + 10 && b.vy < 0) {
b.y = b.radius + 10;
b.vy *= -1;
bounced = true;
}
if (b.y > 2732 - b.radius - 10 && b.vy > 0) {
b.y = 2732 - b.radius - 10;
b.vy *= -1;
bounced = true;
}
// Eğer sekmediyse ve hala out of bounds ise yok et
if (!bounced && isOutOfBounds(b)) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
if (hit) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
} else {
if (hit || isOutOfBounds(b)) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
}
}
// Düşman mermisi update
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var b = enemyBullets[i];
// Skip update if bullet is destroyed or out of bounds
if (!b || typeof b.destroyed !== "undefined" && b.destroyed) {
enemyBullets.splice(i, 1);
continue;
}
if (isOutOfBounds(b)) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
if (typeof b.update === "function") b.update();
// Oyuncuya çarpma
var reflectActive = player._reflect && player._reflect > 0;
if (b.intersects(player)) {
if (reflectActive) {
// Reflect: Düşman mermisi oyuncuya çarptığında geri sektir
var newB = new PlayerBullet();
newB.x = b.x;
newB.y = b.y;
var mag = Math.sqrt(b.vx * b.vx + b.vy * b.vy);
if (mag === 0) mag = 1;
newB.vx = -b.vx / mag * 32;
newB.vy = -b.vy / mag * 32;
playerBullets.push(newB);
game.addChild(newB);
LK.effects.flashObject(player, 0x00ffcc, 200);
showArenaEventPopup("Reflected!");
b.destroy();
enemyBullets.splice(i, 1);
continue;
} else if (player._shield && player._shield > 0) {
player._shield--;
LK.effects.flashObject(player, 0x00ffff, 400);
if (player._shield === 0) {
showArenaEventPopup("Shield Broken!");
} else {
showArenaEventPopup("Shield: " + player._shield + " hits left!");
}
} else {
playerHealth--;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
LK.effects.flashObject(player, 0xff4444, 400);
LK.getSound('hit').play();
if (playerHealth <= 0) {
b.destroy();
enemyBullets.splice(i, 1);
gameOver();
return;
}
}
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
if (isOutOfBounds(b)) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
}
// KOMBO zamanlayıcı: Kombo süresi dolarsa sıfırla
if (comboCount > 0) {
comboTimer--;
if (comboTimer <= 0) {
// Show fun popup for max combo if it was a big combo
if (comboCount >= 5) {
showArenaEventPopup("AWESOME COMBO x" + comboCount + "!");
LK.effects.flashScreen(0xffe100, 400);
} else if (comboCount >= 3) {
showArenaEventPopup("Combo x" + comboCount + "!");
}
comboCount = 0;
updateComboText();
}
}
// Fun popup: Level up
if (typeof lastLevel === "undefined") {
lastLevel = level;
}
if (level > lastLevel) {
showArenaEventPopup("LEVEL UP! Level " + level);
LK.effects.flashScreen(0x00ff00, 400);
lastLevel = level;
}
// Fun popup: Coin milestone
if (typeof lastCoinMilestone === "undefined") {
lastCoinMilestone = 0;
}
if (coinCount >= lastCoinMilestone + 10) {
showArenaEventPopup("Coin Collector! ₵" + coinCount);
LK.effects.flashScreen(0xffd700, 300);
lastCoinMilestone = coinCount - coinCount % 10;
}
// PowerUp update ve çarpışma
// --- PowerUp birleşme ve combo mekaniği ---
for (var i = powerUps.length - 1; i >= 0; i--) {
var p = powerUps[i];
// Skip update if powerup is destroyed or out of bounds
if (!p || typeof p.destroyed !== "undefined" && p.destroyed) {
powerUps.splice(i, 1);
continue;
}
if (isOutOfBounds(p)) {
p.destroy();
powerUps.splice(i, 1);
continue;
}
p.update();
// Magnet veya Super Magnet aktifse, powerupları çek
var magnetActive = player._magnet && player._magnet > 0;
var superMagnetActive = player._superMagnetShot && player._superMagnetShot > 0;
if (magnetActive || superMagnetActive) {
var distToPlayer = Math.sqrt((p.x - player.x) * (p.x - player.x) + (p.y - player.y) * (p.y - player.y));
var pullRadius = superMagnetActive ? 800 : 400;
if (distToPlayer < pullRadius) {
// PowerUp oyuncuya doğru çekilsin
var pullSpeed = superMagnetActive ? 60 : 30;
var dx = player.x - p.x;
var dy = player.y - p.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 1) {
p.x += dx / d * pullSpeed;
p.y += dy / d * pullSpeed;
}
}
}
// PowerUp-PowerUp çarpışması: Birleşme
for (var j = i - 1; j >= 0; j--) {
var p2 = powerUps[j];
if (p !== p2 && p.intersects(p2)) {
// İki powerup birleşirse: PowerUpCombo oluştur
var combo = new PowerUpCombo();
combo.x = (p.x + p2.x) / 2;
combo.y = (p.y + p2.y) / 2;
combo.effects = [];
// Farklı efektleri ekle (tekrar yok)
if (p.effect && combo.effects.indexOf(p.effect) === -1) combo.effects.push(p.effect);
if (p2.effect && combo.effects.indexOf(p2.effect) === -1) combo.effects.push(p2.effect);
// Eğer p veya p2 zaten combo ise, efektlerini ekle
if (p.effects && Array.isArray(p.effects)) {
for (var ce = 0; ce < p.effects.length; ce++) {
if (combo.effects.indexOf(p.effects[ce]) === -1) combo.effects.push(p.effects[ce]);
}
}
if (p2.effects && Array.isArray(p2.effects)) {
for (var ce2 = 0; ce2 < p2.effects.length; ce2++) {
if (combo.effects.indexOf(p2.effects[ce2]) === -1) combo.effects.push(p2.effects[ce2]);
}
}
// Sınır: En fazla 3 efektli combo
if (combo.effects.length > 3) combo.effects = combo.effects.slice(0, 3);
powerUps.splice(i, 1);
powerUps.splice(j, 1);
p.destroy();
p2.destroy();
powerUps.push(combo);
game.addChild(combo);
// Combo birleşme popup
showArenaEventPopup("PowerUp Combo!");
break;
}
}
// Oyuncu ile çarpışma
if (player.intersects(p)) {
// PowerUp veya PowerUpCombo alındı
var effectsToApply = [];
if (p.effect) {
effectsToApply = [p.effect];
} else if (p.effects && Array.isArray(p.effects)) {
effectsToApply = p.effects.slice();
}
var popupMsg = [];
var comboRapid = false,
comboMagnet = false;
// --- PowerUp efektlerini uygula ---
for (var ef = 0; ef < effectsToApply.length; ef++) {
var effect = effectsToApply[ef];
if (effect === "rapid") {
// --- Attack Speed Bonus: Stackable ---
if (typeof player._attackSpeedBonus !== "number") player._attackSpeedBonus = 0;
player._attackSpeedBonus += 1;
powerActive = true;
powerTimer = 600;
popupMsg.push("RAPID FIRE! (10s)");
comboRapid = true;
} else if (effect === "triple") {
player._tripleShot = 600;
popupMsg.push("TRIPLE SHOT! (10s)");
} else if (effect === "shield") {
player._shield = 5;
popupMsg.push("Shield (5 hits)!");
} else if (effect === "heal") {
playerHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg.push("Full Health!");
} else if (effect === "wallBounce") {
player._wallBounce = 600;
popupMsg.push("WALL BOUNCE! (10s)");
} else if (effect === "reflect") {
player._reflect = 600;
popupMsg.push("REFLECT ENEMY BULLETS! (10s)");
} else if (effect === "slow") {
// Zaman yavaşlatma: tüm düşmanlar yavaşlar
for (var si = 0; si < enemies.length; si++) {
enemies[si]._frozen = 180; // 3 saniye yavaşlat
}
popupMsg.push("TIME SLOW! (3s)");
LK.effects.flashScreen(0x66ccff, 400);
} else if (effect === "magnet") {
// Magnet: yakındaki coin ve powerupları çek
comboMagnet = true;
popupMsg.push("MAGNET! (5s)");
player._magnet = 300; // 5 saniye
} else if (effect === "randomizer") {
// Randomizer: tüm düşmanların tipi değişir
for (var ri = 0; ri < enemies.length; ri++) {
var e = enemies[ri];
var t = Math.random();
var newE;
if (t < 0.4) newE = new Enemy();else if (t < 0.7) newE = new Enemy2();else newE = new Enemy3();
newE.x = e.x;
newE.y = e.y;
newE.maxHealth = e.maxHealth;
newE.health = e.health;
newE._frozen = e._frozen;
newE._healthBar = e._healthBar;
newE._visHealthBar = e._visHealthBar;
newE._visHealthBarBg = e._visHealthBarBg;
newE._visHealthBarFg = e._visHealthBarFg;
enemies[ri].destroy();
enemies[ri] = newE;
game.addChild(newE);
}
popupMsg.push("RANDOMIZER! (All enemies changed)");
LK.effects.flashScreen(0x00ffcc, 400);
} else if (effect === "superHeal") {
// Süper can: hem canı doldur hem max canı 2 artır
playerMaxHealth += 2;
playerHealth = playerMaxHealth;
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg.push("SUPER HEAL! (+2 Max Health)");
} else if (effect === "freezeBullets") {
// Freeze all enemy bullets for 3 seconds
for (var bi = 0; bi < enemyBullets.length; bi++) {
enemyBullets[bi]._frozen = 180;
}
popupMsg.push("FREEZE ENEMY BULLETS! (3s)");
LK.effects.flashScreen(0x00eaff, 400);
} else if (effect === "coinRain") {
// Spawn 10 coins at random locations
for (var ci = 0; ci < 10; ci++) {
spawnCoin();
}
popupMsg.push("COIN RAIN!");
LK.effects.flashScreen(0xffd700, 400);
} else if (effect === "enemyClear") {
// Destroy all enemies on screen
for (var ei = enemies.length - 1; ei >= 0; ei--) {
if (enemies[ei]._healthBar) enemies[ei]._healthBar.destroy();
if (enemies[ei]._visHealthBar) enemies[ei]._visHealthBar.destroy();
enemies[ei].destroy();
enemies.splice(ei, 1);
}
popupMsg.push("ENEMY CLEAR!");
LK.effects.flashScreen(0xff4444, 600);
} else if (effect === "scoreBoost") {
// 2x skor için 15 saniye
player._scoreBoost = 900;
popupMsg.push("SCORE BOOST! (15s)");
}
}
// --- PowerUp Kombinasyonları: Rapid + Magnet = Süper Çekim Ateşi ---
if (comboRapid && comboMagnet) {
player._superMagnetShot = 600; // 10 saniye süper çekim ateşi
popupMsg.push("SUPER MAGNET SHOT! (10s)");
LK.effects.flashScreen(0xff00ff, 600);
}
// --- PowerUp efektleri bitti ---
LK.effects.flashObject(player, 0x00ffcc, 400);
showArenaEventPopup("PowerUp: " + popupMsg.join(" + "));
p.destroy();
powerUps.splice(i, 1);
} else if (isOutOfBounds(p)) {
p.destroy();
powerUps.splice(i, 1);
}
}
// Coin update ve toplama
for (var i = coins.length - 1; i >= 0; i--) {
var c = coins[i];
// Skip update if coin is destroyed or out of bounds
if (!c || typeof c.destroyed !== "undefined" && c.destroyed) {
coins.splice(i, 1);
continue;
}
if (isOutOfBounds(c)) {
c.destroy();
coins.splice(i, 1);
continue;
}
c.update();
// Magnet veya Super Magnet aktifse, coinleri çek
var magnetActive = player._magnet && player._magnet > 0;
var superMagnetActive = player._superMagnetShot && player._superMagnetShot > 0;
if (magnetActive || superMagnetActive) {
var distToPlayer = Math.sqrt((c.x - player.x) * (c.x - player.x) + (c.y - player.y) * (c.y - player.y));
var pullRadius = superMagnetActive ? 800 : 400;
if (distToPlayer < pullRadius) {
// Coin oyuncuya doğru çekilsin
var pullSpeed = superMagnetActive ? 60 : 30;
var dx = player.x - c.x;
var dy = player.y - c.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 1) {
c.x += dx / d * pullSpeed;
c.y += dy / d * pullSpeed;
}
}
}
if (player.intersects(c)) {
coinCount++;
coinTxt.setText('₵ ' + coinCount);
// COIN: Save permanently
storage.coins = coinCount;
LK.effects.flashObject(player, 0xFFD700, 200);
// Fun popup: First coin
if (coinCount === 1) {
showArenaEventPopup("First Coin Collected!");
LK.effects.flashScreen(0xffd700, 300);
}
c.destroy();
coins.splice(i, 1);
} else if (isOutOfBounds(c)) {
c.destroy();
coins.splice(i, 1);
}
}
// PowerUp etkisi süresi
if (powerActive) {
powerTimer--;
if (powerTimer <= 0) {
powerActive = false;
// --- Attack Speed Bonus: Remove one stack when rapid fire ends ---
if (typeof player._attackSpeedBonus === "number" && player._attackSpeedBonus > 0) {
player._attackSpeedBonus -= 1;
if (player._attackSpeedBonus < 0) player._attackSpeedBonus = 0;
}
}
}
// Triple shot süresi azalt
if (player._tripleShot && player._tripleShot > 0) {
player._tripleShot--;
if (player._tripleShot <= 0) player._tripleShot = 0;
}
// Wall bounce süresi azalt
if (player._wallBounce && player._wallBounce > 0) {
player._wallBounce--;
if (player._wallBounce <= 0) player._wallBounce = 0;
}
// Reflect süresi azalt
if (player._reflect && player._reflect > 0) {
player._reflect--;
if (player._reflect <= 0) player._reflect = 0;
}
// Magnet süresi azalt
if (player._magnet && player._magnet > 0) {
player._magnet--;
if (player._magnet <= 0) player._magnet = 0;
}
// Super Magnet Shot süresi azalt
if (player._superMagnetShot && player._superMagnetShot > 0) {
player._superMagnetShot--;
if (player._superMagnetShot <= 0) player._superMagnetShot = 0;
}
// Score Boost süresi azalt
if (player._scoreBoost && player._scoreBoost > 0) {
player._scoreBoost--;
if (player._scoreBoost <= 0) player._scoreBoost = 0;
}
// Freeze enemy bullets süresi azalt
for (var bi = 0; bi < enemyBullets.length; bi++) {
if (enemyBullets[bi]._frozen && enemyBullets[bi]._frozen > 0) {
enemyBullets[bi]._frozen--;
// Dondurulmuşsa hareket etmesin
enemyBullets[bi].vx = 0;
enemyBullets[bi].vy = 0;
}
}
// PowerUp spawn (her 6 saniyede bir)
if (gameTick % 360 === 0) {
spawnPowerUp();
}
// COIN: Sık sık rastgele coin spawn et (her 60 frame'de bir, %60 olasılıkla)
if (gameTick % 60 === 0) {
if (Math.random() < 0.6) {
spawnCoin();
}
}
// Düşman spawn
// --- Düşmanlar çok çıksın: skor arttıkça daha sık spawn ---
// spawnInterval: skor arttıkça daha hızlı (min 8 frame)
var spawnInterval = Math.max(60 - level * 2 - Math.floor(score / 10), 8);
// Aynı anda birden fazla düşman spawn: skor arttıkça daha fazla
var enemySpawnCount = 1 + Math.floor(score / 30);
if (gameTick % spawnInterval === 0) {
for (var s = 0; s < enemySpawnCount; s++) {
spawnEnemy();
}
}
};
// Sürükleme başlat
game.down = function (x, y, obj) {
// If player is tapped, start dragging
var px = player.x,
py = player.y;
var dx = x - px,
dy = y - py;
var dist = Math.sqrt(dx * dx + dy * dy);
// User-friendly: If tapped on player, start dragging, otherwise do nothing
if (dist < player.radius + 80) {
// wider area, easier drag
dragNode = player;
lastPlayerPos.x = x;
lastPlayerPos.y = y;
// When drag starts, don't fire, prevent accidental fire
// Drag threshold: set a flag to check if drag distance exceeds a threshold before firing
dragNode._dragStarted = false;
dragNode._dragStartX = x;
dragNode._dragStartY = y;
dragNode._dragStartTime = Date.now();
} else {
// (Removed: tap-to-shoot code is now gone)
}
};
// Sürükleme bırak
game.up = function (x, y, obj) {
if (dragNode && typeof dragNode._dragStarted !== "undefined") {
// If drag didn't start and released quickly, fire (tap-to-shoot)
var dragDx = x - dragNode._dragStartX;
var dragDy = y - dragNode._dragStartY;
var dragDist = Math.sqrt(dragDx * dragDx + dragDy * dragDy);
var dragTime = Date.now() - (dragNode._dragStartTime || 0);
if (!dragNode._dragStarted && dragDist < 24 && dragTime < 200) {
spawnPlayerBullet(player.x, player.y, x, y);
LK.getSound('shoot').play();
}
dragNode._dragStarted = false;
dragNode._dragStartX = 0;
dragNode._dragStartY = 0;
dragNode._dragStartTime = 0;
}
dragNode = null;
// User-friendly: Update last position when drag is released
lastPlayerPos.x = 0;
lastPlayerPos.y = 0;
};
// Sürükleme hareketi: Oyuncu mouse ile birlikte hareket etsin
game.move = function (x, y, obj) {
// Oyuncu mouse ile birlikte hareket etsin
if (player) {
// Kullanıcı dostu: Oyuncunun ekran dışına çıkmasını engelle
var minX = player.radius + 20;
var maxX = 2048 - player.radius - 20;
var minY = player.radius + 20;
var maxY = 2732 - player.radius - 20;
player.x = x;
player.y = y;
if (player.x < minX) player.x = minX;
if (player.x > maxX) player.x = maxX;
if (player.y < minY) player.y = minY;
if (player.y > maxY) player.y = maxY;
}
};
// At game start, reset score, level, and health
score = 0;
level = 1;
playerHealth = playerMaxHealth;
// --- STATISTICS: Persistent High Score, Max Combo, Total Enemies Killed ---
storage.highScore = typeof storage.highScore === "number" ? storage.highScore : 0;
storage.maxCombo = typeof storage.maxCombo === "number" ? storage.maxCombo : 0;
storage.totalEnemiesKilled = typeof storage.totalEnemiesKilled === "number" ? storage.totalEnemiesKilled : 0;
// COIN: Load persistent coin count
coinCount = typeof storage.coins === "number" ? storage.coins : 0;
if (typeof coinTxt !== "undefined" && coinTxt._lastCoinCount !== coinCount) {
coinTxt.setText('₵ ' + coinCount);
coinTxt._lastCoinCount = coinCount;
}
if (typeof player !== "undefined") {
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
}
// --- STATISTICS GUI ---
// Oyuncuya istatistikleri gösteren panel (sol üstte, büyük ve kolay okunur, menü ikonundan uzak)
var statsPanel = new Container();
LK.gui.topLeft.addChild(statsPanel);
// Sol üstte, menü ikonundan uzak durmak için 110px sağa ve 10px aşağıya kaydır
statsPanel.x = 110;
statsPanel.y = 10;
// High Score
var statsHighScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 48,
fill: 0xFFD700,
font: "Impact"
});
statsHighScoreTxt.anchor.set(0, 0);
statsHighScoreTxt.x = 0;
statsHighScoreTxt.y = 0;
statsPanel.addChild(statsHighScoreTxt);
// Max Combo
var statsMaxComboTxt = new Text2('Max Combo: ' + storage.maxCombo, {
size: 48,
fill: 0xFFFA00,
font: "Impact"
});
statsMaxComboTxt.anchor.set(0, 0);
statsMaxComboTxt.x = 0;
statsMaxComboTxt.y = 60;
statsPanel.addChild(statsMaxComboTxt);
// Total Enemies Killed
var statsEnemiesKilledTxt = new Text2('Enemies Killed: ' + storage.totalEnemiesKilled, {
size: 48,
fill: 0xFF4444,
font: "Impact"
});
statsEnemiesKilledTxt.anchor.set(0, 0);
statsEnemiesKilledTxt.x = 0;
statsEnemiesKilledTxt.y = 120;
statsPanel.addChild(statsEnemiesKilledTxt);
// Paneli güncelleyen fonksiyon
function updateStatsPanel() {
if (typeof statsHighScoreTxt !== "undefined") statsHighScoreTxt.setText('High Score: ' + storage.highScore);
if (typeof statsMaxComboTxt !== "undefined") statsMaxComboTxt.setText('Max Combo: ' + storage.maxCombo);
if (typeof statsEnemiesKilledTxt !== "undefined") statsEnemiesKilledTxt.setText('Enemies Killed: ' + storage.totalEnemiesKilled);
}
updateStatsPanel();
// --- NEW: Random PowerUp Shop Button ---
// Spend 30 coins to get a random powerup effect
var randomPowerBtn = new Text2('Random PowerUp (30₵)', {
size: 60,
fill: 0x00BFFF,
// Bright blue for high visibility
font: "Impact"
});
randomPowerBtn.anchor.set(0.5, 0);
LK.gui.top.addChild(randomPowerBtn);
randomPowerBtn.y = 420;
randomPowerBtn.interactive = true;
randomPowerBtn.buttonMode = true;
randomPowerBtn.visible = true;
randomPowerBtn.down = function (x, y, obj) {
if (coinCount >= 30) {
coinCount -= 30;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Pick a random effect
var effects = ["rapid", "triple", "heal", "wallBounce", "reflect", "shield", "slow", "magnet", "superHeal", "freezeBullets", "coinRain", "enemyClear", "scoreBoost"];
var effect = effects[Math.floor(Math.random() * effects.length)];
var popupMsg = "";
if (effect === "rapid") {
// --- Attack Speed Bonus: Stackable ---
if (typeof player._attackSpeedBonus !== "number") player._attackSpeedBonus = 0;
player._attackSpeedBonus += 1;
powerActive = true;
powerTimer = 600;
popupMsg = "RAPID FIRE! (10s)";
} else if (effect === "triple") {
player._tripleShot = 600;
popupMsg = "TRIPLE SHOT! (10s)";
} else if (effect === "heal") {
playerHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg = "Full Health!";
} else if (effect === "wallBounce") {
player._wallBounce = 600;
popupMsg = "WALL BOUNCE! (10s)";
} else if (effect === "reflect") {
player._reflect = 600;
popupMsg = "REFLECT ENEMY BULLETS! (10s)";
} else if (effect === "shield") {
player._shield = 5;
popupMsg = "Shield (5 hits)!";
} else if (effect === "slow") {
for (var si = 0; si < enemies.length; si++) {
enemies[si]._frozen = 180;
}
popupMsg = "TIME SLOW! (3s)";
LK.effects.flashScreen(0x66ccff, 400);
} else if (effect === "magnet") {
player._magnet = 300;
popupMsg = "MAGNET! (5s)";
} else if (effect === "superHeal") {
playerMaxHealth += 2;
playerHealth = playerMaxHealth;
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg = "SUPER HEAL! (+2 Max Health)";
} else if (effect === "freezeBullets") {
for (var bi = 0; bi < enemyBullets.length; bi++) {
enemyBullets[bi]._frozen = 180;
}
popupMsg = "FREEZE ENEMY BULLETS! (3s)";
LK.effects.flashScreen(0x00eaff, 400);
} else if (effect === "coinRain") {
for (var ci = 0; ci < 10; ci++) {
spawnCoin();
}
popupMsg = "COIN RAIN!";
LK.effects.flashScreen(0xffd700, 400);
} else if (effect === "enemyClear") {
for (var ei = enemies.length - 1; ei >= 0; ei--) {
if (enemies[ei]._healthBar) enemies[ei]._healthBar.destroy();
if (enemies[ei]._visHealthBar) enemies[ei]._visHealthBar.destroy();
enemies[ei].destroy();
enemies.splice(ei, 1);
}
popupMsg = "ENEMY CLEAR!";
LK.effects.flashScreen(0xff4444, 600);
} else if (effect === "scoreBoost") {
player._scoreBoost = 900;
popupMsg = "SCORE BOOST! (15s)";
}
LK.effects.flashObject(player, 0xFFD700, 400); // Coin color flash
showArenaEventPopup("PowerUp: " + popupMsg);
} else {
showArenaEventPopup("Not enough coins!");
}
};
// --- NEW: Random Permanent Ultra Power Button (red) ---
var ultraPowerBtn = new Text2('Random ULTRA Power (100₵)', {
size: 60,
fill: 0xFF2222,
// Red
font: "Impact"
});
ultraPowerBtn.anchor.set(0.5, 0);
LK.gui.top.addChild(ultraPowerBtn);
ultraPowerBtn.y = randomPowerBtn.y + 90;
ultraPowerBtn.interactive = true;
ultraPowerBtn.buttonMode = true;
ultraPowerBtn.visible = true;
// --- NEW: Permanent Upgrade Shop (bottom left) ---
var permUpgradeBtn = new Text2('+1 Max Health (250₵)', {
size: 60,
fill: 0x00ff88,
font: "Impact"
});
permUpgradeBtn.anchor.set(0, 1); // bottom left
LK.gui.bottomLeft.addChild(permUpgradeBtn);
permUpgradeBtn.y = 0;
permUpgradeBtn.x = 0;
permUpgradeBtn.interactive = true;
permUpgradeBtn.buttonMode = true;
permUpgradeBtn.visible = true;
// --- NEW: Permanent Max Attack Upgrade Button (bottom right, above health) ---
var permAttackUpgradeBtn = new Text2('+1 Max Attack (250₵)', {
size: 60,
fill: 0xff8800,
font: "Impact"
});
permAttackUpgradeBtn.anchor.set(1, 1);
LK.gui.bottomRight.addChild(permAttackUpgradeBtn);
permAttackUpgradeBtn.y = permUpgradeBtn.y - 90;
permAttackUpgradeBtn.x = 0;
permAttackUpgradeBtn.interactive = true;
permAttackUpgradeBtn.buttonMode = true;
permAttackUpgradeBtn.visible = true;
// Show current permanent upgrades (bottom left, above button)
var permUpgradeInfoTxt = new Text2('', {
size: 48,
fill: 0xffffff,
font: "Impact"
});
permUpgradeInfoTxt.anchor.set(0, 1); // bottom left
LK.gui.bottomLeft.addChild(permUpgradeInfoTxt);
permUpgradeInfoTxt.y = permUpgradeBtn.y + 80;
permUpgradeInfoTxt.x = 0;
// Show current permanent attack upgrades (bottom right, above attack button)
var permAttackUpgradeInfoTxt = new Text2('', {
size: 48,
fill: 0xff8800,
font: "Impact"
});
permAttackUpgradeInfoTxt.anchor.set(1, 1);
LK.gui.bottomRight.addChild(permAttackUpgradeInfoTxt);
permAttackUpgradeInfoTxt.y = permAttackUpgradeBtn.y + 80;
permAttackUpgradeInfoTxt.x = 0;
// Helper to update permanent upgrade info
function updatePermUpgradeInfo() {
var healthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
if (healthUp > 0) {
// If maxed (let's say 10 is max), show MAXED and use green color, add background
if (healthUp >= 10) {
permUpgradeInfoTxt.setText("Max Health +" + healthUp + " (MAXED, permanent)");
permUpgradeInfoTxt.fill = 0x00ff00;
permUpgradeInfoTxt.size = 36;
permUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.95,
padding: 18,
radius: 18
};
} else {
permUpgradeInfoTxt.setText("Max Health +" + healthUp + " (permanent)");
permUpgradeInfoTxt.fill = 0xffffff;
permUpgradeInfoTxt.size = 36;
permUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.8,
padding: 12,
radius: 12
};
}
permUpgradeInfoTxt.visible = true;
} else {
permUpgradeInfoTxt.setText("");
permUpgradeInfoTxt.visible = false;
permUpgradeInfoTxt.background = undefined;
}
var attackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
if (attackUp > 0) {
// If maxed (let's say 10 is max), show MAXED and use orange color, add background
if (attackUp >= 10) {
permAttackUpgradeInfoTxt.setText("Max Attack +" + attackUp + " (MAXED, permanent)");
permAttackUpgradeInfoTxt.fill = 0xff8800;
permAttackUpgradeInfoTxt.size = 36;
permAttackUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.95,
padding: 18,
radius: 18
};
} else {
permAttackUpgradeInfoTxt.setText("Max Attack +" + attackUp + " (permanent)");
permAttackUpgradeInfoTxt.fill = 0xff8800;
permAttackUpgradeInfoTxt.size = 36;
permAttackUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.8,
padding: 12,
radius: 12
};
}
permAttackUpgradeInfoTxt.visible = true;
} else {
permAttackUpgradeInfoTxt.setText("");
permAttackUpgradeInfoTxt.visible = false;
permAttackUpgradeInfoTxt.background = undefined;
}
}
updatePermUpgradeInfo();
permUpgradeBtn.down = function (x, y, obj) {
// Always update coinCount from storage before checking
coinCount = typeof storage.coins === "number" ? storage.coins : coinCount;
var healthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
if (coinCount >= 250) {
coinCount -= 250;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Increase permanent max health
healthUp++;
storage.permMaxHealthUp = healthUp;
updatePermUpgradeInfo();
LK.effects.flashScreen(0x00ff88, 400);
// Apply immediately to player
playerMaxHealth = 10 + healthUp;
playerHealth = playerMaxHealth;
if (typeof player !== "undefined") {
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
}
updateScoreAndLevel();
} else {
showArenaEventPopup("Not enough coins!");
}
};
// Permanent Max Attack Upgrade Button logic
permAttackUpgradeBtn.down = function (x, y, obj) {
coinCount = typeof storage.coins === "number" ? storage.coins : coinCount;
var attackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
if (coinCount >= 250) {
coinCount -= 250;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Increase permanent max attack
attackUp++;
storage.permMaxAttackUp = attackUp;
updatePermUpgradeInfo();
LK.effects.flashScreen(0xff8800, 400);
// Apply immediately to player (if you want, e.g. set player._permAttackUp = attackUp)
if (typeof player !== "undefined") {
player._permAttackUp = attackUp;
}
} else {
showArenaEventPopup("Not enough coins!");
}
};
// --- ULTRA POWER EFFECT TEXT (top-right, red, bold) ---
var ultraPowerEffectTxt = new Text2('', {
size: 60,
fill: 0xFF2222,
font: "Impact",
fontWeight: "bold"
});
ultraPowerEffectTxt.anchor.set(1, 0); // right-top
LK.gui.topRight.addChild(ultraPowerEffectTxt);
ultraPowerEffectTxt.y = 0;
ultraPowerEffectTxt.x = 0; // LK.gui.topRight is already at the right edge
// Helper to set ultra power effect text
var ultraPowerEffectTimeout = null;
function setUltraPowerEffectText(txt) {
if (typeof ultraPowerEffectTxt !== "undefined" && ultraPowerEffectTxt && typeof ultraPowerEffectTxt.setText === "function") {
ultraPowerEffectTxt.setText(txt || '');
ultraPowerEffectTxt.visible = !!txt;
// Hide after 2.5 seconds if text is set
if (ultraPowerEffectTimeout) {
LK.clearTimeout(ultraPowerEffectTimeout);
ultraPowerEffectTimeout = null;
}
if (txt) {
ultraPowerEffectTimeout = LK.setTimeout(function () {
ultraPowerEffectTxt.setText('');
ultraPowerEffectTxt.visible = false;
ultraPowerEffectTimeout = null;
}, 5000);
}
}
}
// On game start, clear ultra power effect text
setUltraPowerEffectText('');
// Track the current ultra power effect
var currentUltraPowerEffect = "";
// Update the text when ultra power is bought
ultraPowerBtn.down = function (x, y, obj) {
// Always update coinCount from storage before checking
coinCount = typeof storage.coins === "number" ? storage.coins : coinCount;
if (coinCount >= 100) {
coinCount -= 100;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Pick a random ultra-strong permanent effect
var ultraEffects = ["superScoreBoost", "permaTriple", "permaRapid", "permaWallBounce", "permaReflect"];
var effect = ultraEffects[Math.floor(Math.random() * ultraEffects.length)];
var popupMsg = "";
var effectLabel = "";
if (effect === "superScoreBoost") {
player._superScoreBoost = true;
player._scoreBoost = 1;
popupMsg = "PERMANENT: 10x Score!";
effectLabel = "10x Score!";
} else if (effect === "permaTriple") {
player._tripleShot = 999999;
popupMsg = "PERMANENT: Triple Shot!";
effectLabel = "Triple Shot!";
} else if (effect === "permaRapid") {
// --- Attack Speed Bonus: Permanent ---
if (typeof player._attackSpeedBonus !== "number") player._attackSpeedBonus = 0;
player._attackSpeedBonus += 5; // Permanent big bonus
powerActive = true;
powerTimer = 999999;
popupMsg = "PERMANENT: Rapid Fire!";
effectLabel = "Rapid Fire!";
} else if (effect === "permaWallBounce") {
player._wallBounce = 999999;
popupMsg = "PERMANENT: Wall Bounce!";
effectLabel = "Wall Bounce!";
} else if (effect === "permaReflect") {
player._reflect = 999999;
popupMsg = "PERMANENT: Reflect!";
effectLabel = "Reflect!";
}
LK.effects.flashObject(player, 0xFF2222, 600);
showArenaEventPopup("ULTRA Power: " + popupMsg);
// Show effect label at top-right
currentUltraPowerEffect = effectLabel;
setUltraPowerEffectText(effectLabel);
} else {
showArenaEventPopup("Not enough coins!");
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Coin (altın) kutusu
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGfx = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = coinGfx.width * 0.5;
self.update = function () {
// Hafifçe döndür
coinGfx.rotation += 0.12;
};
return self;
});
// Düşman karakteri (AI) - Enemy1: Kendini iyileştirme yeteneği
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemyGfx.width * 0.5;
self.type = 1;
self.speed = 3 + Math.random() * 2;
self.dir = Math.random() * Math.PI * 2;
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
self.targetX = 0;
self.targetY = 0;
self.maxHealth = 3 + Math.floor(Math.random() * 2); // 3-4 can
self.health = self.maxHealth;
// --- YENİ: Kendini iyileştirme özelliği ---
self.healCooldown = 180 + Math.floor(Math.random() * 120); // 3-5 saniyede bir
// --- KOMİK KONUŞMA BALONU ---
// Funny lines (ENGLISH + EMOJIS)
self._funnyLines = ["You can't catch me! 🏃♂️💨", "That tickles! 😂", "I'm about to explode! 💥", "Alien or comedian? 👽🤡", "Look, I'm dancing! 🕺", "Don't shoot, I'm friendly! ✌️", "Tea break time! 🍵", "Beep bop! Error! 🤖", "Are you a hero or a clown? 🦸♂️🤡", "Leveling up soon! ⏫", "Oops, wrong galaxy! 💫", "Pizza delivery! 🍕", "I want a burger! 🍔", "Insert coin to continue! 👾", "Dance battle, anyone? 💃", "Quack! Wrong sound? 🦆", "Say cheese! 🧀", "Rawr! I'm a tiny dino. 🦖", "Brain freeze! 🧠❄️", "Crab rave time! 🦀🎶", "Hoot hoot! Night shift. 🦉", "I floss daily. 🦷", "To the moon! 🚀", "Catch me if you can! 😜", "This is my serious face. 🥸"];
self._speechBubble = null;
self._speechTimer = 0;
self._showSpeech = function (text) {
// Eski balon varsa sil
if (self._speechBubble) {
self._speechBubble.destroy();
self._speechBubble = null;
}
var bubble = new Text2(text, {
size: 48,
fill: 0xffffff,
font: "Impact"
});
bubble.anchor.set(0.5, 1);
bubble.x = self.x;
bubble.y = self.y - self.radius - 60;
bubble.alpha = 1;
game.addChild(bubble);
self._speechBubble = bubble;
// Balonu 1.2 saniyede kaybolacak şekilde animasyonla
tween(bubble, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
if (bubble) bubble.visible = false;
if (self._speechBubble === bubble) self._speechBubble = null;
}
});
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffff00, 200);
// Komik konuşma: Hasar alınca %60 ihtimalle konuşsun
if (Math.random() < 0.6) {
var line = self._funnyLines[Math.floor(Math.random() * self._funnyLines.length)];
self._showSpeech(line);
}
if (self.health <= 0) {
// Destroy health bar if exists
if (self._healthBar) {
self._healthBar.destroy();
self._healthBar = null;
}
// Destroy visible health bar if exists
if (self._visHealthBar) {
self._visHealthBar.destroy();
self._visHealthBar = null;
self._visHealthBarBg = null;
self._visHealthBarFg = null;
}
self.destroy();
// Skor boost varsa 2 puan ver
if (player._superScoreBoost && player._scoreBoost > 0) {
score += 10 + (comboCount > 1 ? comboCount : 0);
} else if (player._scoreBoost && player._scoreBoost > 0) {
score += 2 + (comboCount > 1 ? comboCount : 0);
} else {
score += 1 + (comboCount > 1 ? comboCount : 0);
}
updateScoreAndLevel();
if (score > 0 && score % 10 === 0) {
increaseDifficulty();
}
// Remove from enemies array in main loop
self._shouldRemove = true;
}
};
self.update = function () {
if (self._frozen && self._frozen > 0) {
// Donmuşsa titret
self.x += Math.sin(self._frozen) * 2;
self.y += Math.cos(self._frozen) * 2;
return;
}
// --- YENİ: Kendini iyileştirme ---
if (self.healCooldown > 0) {
self.healCooldown--;
} else {
if (self.health < self.maxHealth) {
self.health++;
LK.effects.flashObject(self, 0x00ff00, 200);
}
self.healCooldown = 180 + Math.floor(Math.random() * 120);
}
// Basit AI: Oyuncuya doğru hareket et
var dx = player.x - self.x;
var dy = player.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 1) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Ateş etme
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shootCooldown = 90 + Math.floor(Math.random() * 60);
spawnEnemyBullet(self.x, self.y, player.x, player.y);
}
// --- KOMİK KONUŞMA: Rastgele aralıklarla konuşsun ---
// Her update'de sayaç azalt, 0 olunca konuş
if (self._speechTimer > 0) {
self._speechTimer--;
} else if (Math.random() < 0.01) {
// %1 ihtimalle her frame
var line = self._funnyLines[Math.floor(Math.random() * self._funnyLines.length)];
self._showSpeech(line);
self._speechTimer = 180 + Math.floor(Math.random() * 120); // 3-5 saniye bekle
}
// --- HEALTH BAR (rectangle) ---
// Create health bar if not exists
if (!self._visHealthBar) {
self._visHealthBar = new Container();
self._visHealthBarBg = new Container();
self._visHealthBarFg = new Container();
self._visHealthBar.addChild(self._visHealthBarBg);
self._visHealthBar.addChild(self._visHealthBarFg);
game.addChild(self._visHealthBar);
}
if (self._visHealthBar) {
// Position above enemy
self._visHealthBar.x = self.x;
self._visHealthBar.y = self.y - self.radius - 28;
// Health percent
var hp = Math.max(0, self.health) / self.maxHealth;
// Clamp width
var fgWidth = Math.max(24, 180 * hp);
self._visHealthBarFg.width = fgWidth;
// Color: green > yellow > red
if (hp > 0.6) {
self._visHealthBarFg.tint = 0x00ff00;
} else if (hp > 0.3) {
self._visHealthBarFg.tint = 0xffe100;
} else {
self._visHealthBarFg.tint = 0xff4444;
}
self._visHealthBar.visible = true;
}
// Konuşma balonunu takip ettir
if (self._speechBubble) {
self._speechBubble.x = self.x;
self._speechBubble.y = self.y - self.radius - 60;
}
};
return self;
});
// Düşman karakteri 2 (dairesel hareket, elips) - Enemy2: Kalkan oluşturma yeteneği
var Enemy2 = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy2', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemyGfx.width * 0.5;
self.type = 2;
self.angle = Math.random() * Math.PI * 2;
// Enemy2: Orbit around a random point in the arena, not the player
self.centerX = 200 + Math.random() * 1648;
self.centerY = 200 + Math.random() * 2332;
self.orbitRadius = 400 + Math.random() * 200;
self.speed = 0.012 + Math.random() * 0.008;
self.shootCooldown = 120 + Math.floor(Math.random() * 60);
self.maxHealth = 4 + Math.floor(Math.random() * 2); // 4-5 can
self.health = self.maxHealth;
// --- YENİ: Kalkan özelliği ---
self.shield = 0;
self.shieldCooldown = 240 + Math.floor(Math.random() * 120); // 4-6 saniyede bir
self.takeDamage = function (amount) {
if (self.shield > 0) {
self.shield--;
LK.effects.flashObject(self, 0x00ffff, 200);
return;
}
self.health -= amount;
LK.effects.flashObject(self, 0xffff00, 200);
if (self.health <= 0) {
// Destroy health bar if exists
if (self._healthBar) {
self._healthBar.destroy();
self._healthBar = null;
}
// Destroy visible health bar if exists
if (self._visHealthBar) {
self._visHealthBar.destroy();
self._visHealthBar = null;
self._visHealthBarBg = null;
self._visHealthBarFg = null;
}
self.destroy();
if (player._scoreBoost && player._scoreBoost > 0) {
score += 2 + (comboCount > 1 ? comboCount : 0);
} else {
score += 1 + (comboCount > 1 ? comboCount : 0);
}
updateScoreAndLevel();
if (score > 0 && score % 10 === 0) {
increaseDifficulty();
}
self._shouldRemove = true;
}
};
self.update = function () {
if (self._frozen && self._frozen > 0) {
self.x += Math.sin(self._frozen) * 2;
self.y += Math.cos(self._frozen) * 2;
return;
}
// --- YENİ: Kalkan oluşturma ---
if (self.shieldCooldown > 0) {
self.shieldCooldown--;
} else {
self.shield = 2; // 2 vuruşluk kalkan
self.shieldCooldown = 240 + Math.floor(Math.random() * 120);
LK.effects.flashObject(self, 0x00ffff, 200);
}
// Kalkan efekti için: kalkanı varsa hafif mavi tint
if (self.shield > 0 && enemyGfx) {
enemyGfx.alpha = 0.7;
} else if (enemyGfx) {
enemyGfx.alpha = 1.0;
}
self.angle += self.speed;
self.x = self.centerX + Math.cos(self.angle) * self.orbitRadius;
self.y = self.centerY + Math.sin(self.angle) * self.orbitRadius;
// Ateş etme
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shootCooldown = 120 + Math.floor(Math.random() * 60);
spawnEnemyBullet(self.x, self.y, player.x, player.y);
}
// --- HEALTH BAR (rectangle) ---
// Create health bar if not exists
if (!self._visHealthBar) {
self._visHealthBar = new Container();
self._visHealthBarBg = new Container();
self._visHealthBarFg = new Container();
self._visHealthBar.addChild(self._visHealthBarBg);
self._visHealthBar.addChild(self._visHealthBarFg);
game.addChild(self._visHealthBar);
}
if (self._visHealthBar) {
// Position above enemy
self._visHealthBar.x = self.x;
self._visHealthBar.y = self.y - self.radius - 28;
// Health percent
var hp = Math.max(0, self.health) / self.maxHealth;
// Clamp width
var fgWidth = Math.max(24, 180 * hp);
self._visHealthBarFg.width = fgWidth;
// Color: green > yellow > red
if (hp > 0.6) {
self._visHealthBarFg.tint = 0x00ff00;
} else if (hp > 0.3) {
self._visHealthBarFg.tint = 0xffe100;
} else {
self._visHealthBarFg.tint = 0xff4444;
}
self._visHealthBar.visible = true;
}
};
return self;
});
// Düşman karakteri 3 (rastgele zıplama, mor kutu) - Enemy3: Ölünce ikiye bölünme yeteneği
var Enemy3 = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy3', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemyGfx.width * 0.5;
self.type = 3;
self.jumpTimer = 60 + Math.floor(Math.random() * 60);
self.targetX = 200 + Math.random() * 1648;
self.targetY = 200 + Math.random() * 2332;
self.speed = 12 + Math.random() * 6;
self.shootCooldown = 100 + Math.floor(Math.random() * 60);
self.maxHealth = 2 + Math.floor(Math.random() * 2); // 2-3 can
self.health = self.maxHealth;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffff00, 200);
if (self.health <= 0) {
// Destroy health bar if exists
if (self._healthBar) {
self._healthBar.destroy();
self._healthBar = null;
}
// Destroy visible health bar if exists
if (self._visHealthBar) {
self._visHealthBar.destroy();
self._visHealthBar = null;
self._visHealthBarBg = null;
self._visHealthBarFg = null;
}
// Splitting on death removed
self.destroy();
if (player._scoreBoost && player._scoreBoost > 0) {
score += 2 + (comboCount > 1 ? comboCount : 0);
} else {
score += 1 + (comboCount > 1 ? comboCount : 0);
}
updateScoreAndLevel();
if (score > 0 && score % 10 === 0) {
increaseDifficulty();
}
self._shouldRemove = true;
}
};
self.update = function () {
if (self._frozen && self._frozen > 0) {
self.x += Math.sin(self._frozen) * 2;
self.y += Math.cos(self._frozen) * 2;
return;
}
self.jumpTimer--;
if (self.jumpTimer <= 0) {
self.targetX = 200 + Math.random() * 1648;
self.targetY = 200 + Math.random() * 2332;
self.jumpTimer = 60 + Math.floor(Math.random() * 60);
}
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 1) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Ateş etme
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shootCooldown = 100 + Math.floor(Math.random() * 60);
spawnEnemyBullet(self.x, self.y, player.x, player.y);
}
// --- HEALTH BAR (rectangle) ---
// Create health bar if not exists
if (!self._visHealthBar) {
self._visHealthBar = new Container();
self._visHealthBarBg = new Container();
self._visHealthBarFg = new Container();
self._visHealthBar.addChild(self._visHealthBarBg);
self._visHealthBar.addChild(self._visHealthBarFg);
game.addChild(self._visHealthBar);
}
if (self._visHealthBar) {
// Position above enemy
self._visHealthBar.x = self.x;
self._visHealthBar.y = self.y - self.radius - 28;
// Health percent
var hp = Math.max(0, self.health) / self.maxHealth;
// Clamp width
var fgWidth = Math.max(24, 180 * hp);
self._visHealthBarFg.width = fgWidth;
// Color: green > yellow > red
if (hp > 0.6) {
self._visHealthBarFg.tint = 0x00ff00;
} else if (hp > 0.3) {
self._visHealthBarFg.tint = 0xffe100;
} else {
self._visHealthBarFg.tint = 0xff4444;
}
self._visHealthBar.visible = true;
}
};
return self;
});
// Düşman mermisi
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletGfx.width * 0.5;
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Oyuncu karakteri
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGfx = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = playerGfx.width * 0.5;
self.shootCooldown = 0;
// Oyuncuya can ekle
self.maxHealth = typeof playerMaxHealth !== "undefined" ? playerMaxHealth : 5;
self.health = typeof playerHealth !== "undefined" ? playerHealth : self.maxHealth;
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
};
return self;
});
// Oyuncu mermisi
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletGfx.width * 0.5;
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Güçlendirici (PowerUp) kutusu
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerGfx = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = powerGfx.width * 0.5;
self.type = "power";
// Yeni powerup efektleri eklendi
var effects = ["rapid",
// Hızlı ateş (fire rate)
"triple",
// Üçlü atış
"shield",
// Kalkan
"heal",
// Can doldur
"wallBounce",
// Duvar sekme
"reflect",
// Düşman mermisi sektirme
"slow",
// Zaman yavaşlatma (tüm düşmanlar yavaşlar)
"magnet",
// Magnet (yakındaki coin/powerup çeker)
"randomizer",
// Randomizer (tüm düşmanların tipi değişir)
"superHeal",
// Süper can: max canı artır ve doldur
"freezeBullets",
// Düşman mermilerini dondur
"coinRain",
// Ekrana coin yağmuru
"enemyClear",
// Tüm düşmanları yok et
"scoreBoost" // Skor 2x (15s)
];
self.effect = effects[Math.floor(Math.random() * effects.length)];
self.update = function () {
// Hafifçe döndür
powerGfx.rotation += 0.08;
};
return self;
});
// PowerUpCombo: Birleşmiş poweruplar için özel kutu
var PowerUpCombo = Container.expand(function () {
var self = Container.call(this);
var powerGfx = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = powerGfx.width * 0.6;
self.type = "powerCombo";
self.effects = []; // ["rapid", "triple", ...]
self.update = function () {
// Hafifçe döndür ve renk değiştir (her efekt için farklı renkler)
powerGfx.rotation += 0.12;
// Renkleri birleştir: efekt sayısına göre tint değiştir
if (self.effects.indexOf("slow") !== -1 && self.effects.length === 1) {
powerGfx.tint = 0x66ccff; // Mavi (slow)
} else if (self.effects.indexOf("magnet") !== -1 && self.effects.length === 1) {
powerGfx.tint = 0xff00ff; // Magnet için mor
} else if (self.effects.indexOf("randomizer") !== -1 && self.effects.length === 1) {
powerGfx.tint = 0x00ffcc; // Randomizer için turkuaz
} else if (self.effects.length === 2) {
powerGfx.tint = 0xFFD700; // Altın
} else if (self.effects.length >= 3) {
powerGfx.tint = 0xFF44FF; // Pembe
} else {
powerGfx.tint = 0xFFFFFF;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0074D9
});
/****
* Game Code
****/
// Space background images (add your own image asset IDs as needed)
// --- SPACE BACKGROUND ---
// Global değişkenler
// Space backgrounds as assets
var spaceBackgrounds = [{
id: 'spacebg1',
width: 2048,
height: 2732,
assetId: '682e6b2ad10b0c0b481370a1'
}, {
id: 'spacebg2',
width: 2048,
height: 2732,
assetId: '682e6b3fd10b0c0b481370a2'
}, {
id: 'spacebg3',
width: 2048,
height: 2732,
assetId: '682e6b4ad10b0c0b481370a3'
}];
// Register background assets (engine will load them automatically)
for (var i = 0; i < spaceBackgrounds.length; i++) {}
// Pick a random background
var selectedBg = spaceBackgrounds[Math.floor(Math.random() * spaceBackgrounds.length)];
var bgSprite = LK.getAsset(selectedBg.id, {
anchorX: 0,
anchorY: 0
});
bgSprite.x = 0;
bgSprite.y = 0;
bgSprite.width = 2048;
bgSprite.height = 2732;
game.addChildAt(bgSprite, 0); // Add as the bottom-most layer
// Coin asset
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var powerUps = [];
var coins = []; // Coin objects
var coinCount = 0; // Collected coin count
var coinTxt = new Text2('₵ ' + coinCount, {
size: 70,
fill: 0xFFD700,
font: "Impact"
});
coinTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(coinTxt);
coinTxt.y = 340;
var powerActive = false;
var powerTimer = 0;
var dragNode = null;
var lastPlayerPos = {
x: 0,
y: 0
};
var score = 0;
var level = 1;
var gameTick = 0;
var spawnTimer = 0;
var isGameOver = false;
// Combo variables
var comboCount = 0;
var comboTimer = 0;
var maxComboTime = 120; // 2 seconds (120 frames)
var maxCombo = 0;
// Combo GUI
var comboTxt = new Text2('', {
size: 80,
fill: 0xFFFA00,
font: "Impact"
});
comboTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(comboTxt);
comboTxt.y = 260;
// Health bar variables
// Permanent max health and max attack upgrades RESET
storage.permMaxHealthUp = 0;
storage.permMaxAttackUp = 0;
// Permanent max health upgrade from storage
var permHealthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
var playerMaxHealth = 10 + permHealthUp;
var playerHealth = playerMaxHealth;
// Health bar GUI
var healthTxt = new Text2('Health: ' + playerHealth, {
size: 70,
fill: 0xFF4444
});
healthTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(healthTxt);
healthTxt.y = 180;
// --- HOW TO PLAY POPUP (before game starts) ---
var howToPlayTxt = new Text2("Nasıl Oynanır?\n\n" + "- Parmağınızı ekrana basılı tutup karakterinizi ARENADA sürükleyin.\n" + "- Düşmanlardan ve mermilerden kaçın, otomatik ateşle düşmanları yok edin!\n" + "- Güçlendiricileri (PowerUp) ve altınları toplayın.\n" + "- Kombo yaparak daha fazla puan kazanın.\n" + "- Sol üstte istatistiklerinizi takip edin.\n\n" + "Başlamak için ekrana dokunun!", {
size: 70,
fill: "#fff",
font: "Impact",
align: "center",
wordWrap: true,
wordWrapWidth: 1600
});
howToPlayTxt.anchor.set(0.5, 0.5);
howToPlayTxt.x = 2048 / 2;
howToPlayTxt.y = 2732 / 2;
howToPlayTxt.background = {
color: 0x222244,
alpha: 0.92,
padding: 60,
radius: 48
};
LK.gui.center.addChild(howToPlayTxt);
// Oyuncu dokununca başlat
var howToPlayActive = true;
game.down = function (x, y, obj) {
if (howToPlayActive) {
howToPlayActive = false;
howToPlayTxt.visible = false;
startGame();
} else {
// If player is tapped, start dragging
var px = player.x,
py = player.y;
var dx = x - px,
dy = y - py;
var dist = Math.sqrt(dx * dx + dy * dy);
// User-friendly: If tapped on player, start dragging, otherwise do nothing
if (dist < player.radius + 80) {
// wider area, easier drag
dragNode = player;
lastPlayerPos.x = x;
lastPlayerPos.y = y;
// When drag starts, don't fire, prevent accidental fire
// Drag threshold: set a flag to check if drag distance exceeds a threshold before firing
dragNode._dragStarted = false;
dragNode._dragStartX = x;
dragNode._dragStartY = y;
dragNode._dragStartTime = Date.now();
} else {
// (Removed: tap-to-shoot code is now gone)
}
}
};
// --- OYUNU BAŞLAT ---
function startGame() {
// Oyun değişkenlerini sıfırla
isInMainMenu = false; // Oyun başlarken menüden çık
score = 0;
level = 1;
// Apply permanent max health upgrade from storage
var permHealthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
playerMaxHealth = 10 + permHealthUp;
playerHealth = playerMaxHealth;
enemies = [];
playerBullets = [];
enemyBullets = [];
powerUps = [];
coins = [];
powerActive = false;
powerTimer = 0;
comboCount = 0;
comboTimer = 0;
maxCombo = 0;
isGameOver = false;
gameTick = 0;
spawnTimer = 0;
dragNode = null;
lastPlayerPos = {
x: 0,
y: 0
};
// Apply permanent max attack upgrade from storage
var permAttackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
if (typeof player !== "undefined") {
player._permAttackUp = permAttackUp;
}
// Ultra power effect text clear
if (typeof setUltraPowerEffectText === "function") setUltraPowerEffectText('');
if (typeof currentUltraPowerEffect !== "undefined") currentUltraPowerEffect = "";
// GUI güncelle
updateScoreAndLevel();
updateStatsPanel();
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + (typeof storage.coins === "number" ? storage.coins : 0));
if (typeof player !== "undefined") {
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
}
// Oyuncu konumunu sıfırla
if (typeof player !== "undefined") {
player.x = 2048 / 2;
player.y = 2732 / 2;
}
}
// Play background music (loops by default)
LK.playMusic('musicId');
// PowerUp oluşturucu
function spawnPowerUp() {
var p = new PowerUp();
// Güvenli alan içinde rastgele konum
p.x = 200 + Math.random() * 1648;
p.y = 200 + Math.random() * 2332;
powerUps.push(p);
game.addChild(p);
}
// Coin oluşturucu
function spawnCoin(x, y) {
var c = new Coin();
// Eğer x, y verilmişse oraya koy, yoksa rastgele
if (typeof x === "number" && typeof y === "number") {
c.x = x;
c.y = y;
} else {
c.x = 200 + Math.random() * 1648;
c.y = 200 + Math.random() * 2332;
}
coins.push(c);
game.addChild(c);
}
// Score and level display
var scoreTxt = new Text2('Score: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: "#fff"
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 100;
// Eğlenceli: Arena event popup
var eventPopupTxt = new Text2('', {
size: 70,
fill: 0xFFFA00,
font: "Impact"
});
eventPopupTxt.anchor.set(0.5, 0.5);
eventPopupTxt.visible = false;
LK.gui.center.addChild(eventPopupTxt);
// Arena event popup function (already in English, nothing to change)
function showArenaEventPopup(msg) {
eventPopupTxt.setText(msg);
eventPopupTxt.visible = true;
eventPopupTxt.alpha = 1;
tween(eventPopupTxt, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
eventPopupTxt.visible = false;
}
});
}
// Oyuncu oluştur
player = new Player();
game.addChild(player);
player.x = 2048 / 2;
player.y = 2732 / 2;
// Apply permanent max attack upgrade from storage on initial load
var permAttackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
player._permAttackUp = permAttackUp;
// Düşman oluşturucu
function spawnEnemy() {
var t = Math.random();
var e;
if (t < 0.4) {
e = new Enemy();
} else if (t < 0.7) {
e = new Enemy2();
} else {
e = new Enemy3();
}
// --- FUNNY SPEECH BUBBLE ON SPAWN (with emojis) ---
var funnySpawnLines = ["👽 Boo! Did I scare you?", "😂 I'm too cute to shoot!", "🍕 Pizza time! Wait, no pizza?", "🦄 I'm a unicorn in disguise!", "💩 Oops, wrong galaxy!", "🤡 Who invited the clown?", "🕺 Dance battle, anyone?", "🐸 Ribbit! Oh wait, I'm not a frog.", "🚀 To the moon! ...or not.", "😜 Catch me if you can!", "🥸 This is my serious face.", "🧀 Say cheese!", "🦖 Rawr! I'm a tiny dino.", "👾 Insert coin to continue!", "🦆 Quack! Wrong sound?", "🍔 I want a burger!", "🧠 Brain freeze!", "🦷 I floss daily.", "🦀 Crab rave time!", "🦉 Hoot hoot! Night shift."];
if (typeof e._showSpeech === "function") {
var spawnLine = funnySpawnLines[Math.floor(Math.random() * funnySpawnLines.length)];
e._showSpeech(spawnLine);
}
// Enemies get stronger: health increases with level and score
if (typeof e.maxHealth !== "undefined") {
// Her 3 level'da +1 can, her 20 skor'da +1 can
var extraHealth = Math.floor(level / 3) + Math.floor(score / 20);
e.maxHealth += extraHealth;
e.health = e.maxHealth;
}
// Randomly spawn from edge
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// top
e.x = 200 + Math.random() * 1648;
e.y = -100;
} else if (edge === 1) {
// right
e.x = 2148;
e.y = 200 + Math.random() * 2332;
} else if (edge === 2) {
// bottom
e.x = 200 + Math.random() * 1648;
e.y = 2832;
} else {
// left
e.x = -100;
e.y = 200 + Math.random() * 2332;
}
enemies.push(e);
game.addChild(e);
}
// Düşman mermisi oluşturucu
function spawnEnemyBullet(sx, sy, tx, ty) {
var b = new EnemyBullet();
b.x = sx;
b.y = sy;
var dx = tx - sx;
var dy = ty - sy;
var dist = Math.sqrt(dx * dx + dy * dy);
var speed = 9 + level * 1; // Düşman mermisi hızı azaltıldı
b.vx = dx / dist * speed;
b.vy = dy / dist * speed;
enemyBullets.push(b);
game.addChild(b);
}
// Oyuncu mermisi oluşturucu
function spawnPlayerBullet(sx, sy, tx, ty) {
var b = new PlayerBullet();
b.x = sx;
b.y = sy;
var dx = tx - sx;
var dy = ty - sy;
var dist = Math.sqrt(dx * dx + dy * dy);
var speed = 32;
b.vx = dx / dist * speed;
b.vy = dy / dist * speed;
playerBullets.push(b);
game.addChild(b);
LK.getSound('shoot').play();
}
// Skor ve seviye güncelle
function updateScoreAndLevel() {
if (typeof scoreTxt !== "undefined" && scoreTxt && typeof scoreTxt.setText === "function") {
if (scoreTxt._lastScore !== score) {
scoreTxt.setText('Score: ' + score);
scoreTxt._lastScore = score;
}
}
if (typeof levelTxt !== "undefined" && levelTxt && typeof levelTxt.setText === "function") {
if (levelTxt._lastLevel !== level) {
levelTxt.setText('Level: ' + level);
levelTxt._lastLevel = level;
}
}
if (typeof healthTxt !== "undefined" && healthTxt && typeof healthTxt.setText === "function") {
if (healthTxt._lastHealth !== playerHealth) {
healthTxt.setText('Health: ' + playerHealth);
healthTxt._lastHealth = playerHealth;
}
}
updateComboText();
}
// Kombo GUI güncelle
function updateComboText() {
if (comboCount > 1) {
if (comboTxt._lastCombo !== comboCount) {
comboTxt.setText("COMBO x" + comboCount + "!");
comboTxt.visible = true;
comboTxt.alpha = 1;
comboTxt._lastCombo = comboCount;
}
} else {
if (comboTxt.visible) {
comboTxt.visible = false;
comboTxt._lastCombo = 0;
}
}
}
// Oyun zorluğunu artır
function increaseDifficulty() {
level++;
updateScoreAndLevel();
}
// Oyun bitti
function gameOver() {
if (isGameOver) return;
isGameOver = true;
// --- STATISTICS: Update high score and max combo at game over ---
if (score > storage.highScore) {
storage.highScore = score;
}
if (maxCombo > storage.maxCombo) {
storage.maxCombo = maxCombo;
}
updateStatsPanel();
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('hit').play();
LK.showGameOver();
}
// Oyun kazandı
function youWin() {
showArenaEventPopup("YOU WIN! 🎉");
LK.effects.flashScreen(0x00ffcc, 1000);
LK.showYouWin();
}
// Sürükleme ve ateş etme
function handleMove(x, y, obj) {
if (dragNode) {
// Apply movement delta
var dx = x - lastPlayerPos.x;
var dy = y - lastPlayerPos.y;
dragNode.x += dx;
dragNode.y += dy;
// User-friendly: Prevent player from going out of bounds
var minX = dragNode.radius + 20;
var maxX = 2048 - dragNode.radius - 20;
var minY = dragNode.radius + 20;
var maxY = 2732 - dragNode.radius - 20;
if (dragNode.x < minX) dragNode.x = minX;
if (dragNode.x > maxX) dragNode.x = maxX;
if (dragNode.y < minY) dragNode.y = minY;
if (dragNode.y > maxY) dragNode.y = maxY;
lastPlayerPos.x = x;
lastPlayerPos.y = y;
}
}
// Out of bounds check
function isOutOfBounds(obj) {
return obj.x < -200 || obj.x > 2248 || obj.y < -200 || obj.y > 2932;
}
// Oyun ana döngüsü
game.update = function () {
if (isGameOver) return;
gameTick++;
// Fun: Random arena events (e.g. meteor shower, bonus rain, enemy freeze)
// Every 15 seconds, a random event may trigger
if (gameTick % 900 === 0 && gameTick > 0) {
var eventType = Math.floor(Math.random() * 3);
if (eventType === 0) {
// Meteor shower: 10 fast bullets fall from the top
for (var m = 0; m < 10; m++) {
var b = new EnemyBullet();
b.x = 200 + Math.random() * 1648;
b.y = -80 - m * 60;
b.vx = 0;
b.vy = 32 + Math.random() * 8;
enemyBullets.push(b);
game.addChild(b);
}
// Short effect
LK.effects.flashScreen(0xffa500, 400);
showArenaEventPopup("Meteor Shower!");
} else if (eventType === 1) {
// Bonus rain: 5 powerUps drop at once
for (var p = 0; p < 5; p++) {
var pu = new PowerUp();
pu.x = 200 + Math.random() * 1648;
pu.y = 200 + Math.random() * 2332;
powerUps.push(pu);
game.addChild(pu);
}
LK.effects.flashScreen(0x00ffcc, 400);
showArenaEventPopup("Bonus Rain!");
} else if (eventType === 2) {
// Enemies freeze for 3 seconds
for (var i = 0; i < enemies.length; i++) {
enemies[i]._frozen = 180; // 3 seconds
}
LK.effects.flashScreen(0x66ccff, 400);
showArenaEventPopup("Enemies Frozen!");
}
}
// Düşmanları dondurma efekti uygula
for (var i = 0; i < enemies.length; i++) {
if (enemies[i]._frozen && enemies[i]._frozen > 0) {
enemies[i]._frozen--;
continue; // update çağrılmasın, düşman hareket etmesin
}
}
// Oyuncu update
player.update();
// Oyuncu canını playerHealth ile senkronize et
if (typeof player.health !== "undefined" && typeof playerHealth !== "undefined" && player.health !== playerHealth) {
player.health = playerHealth;
}
if (typeof player.maxHealth !== "undefined" && typeof playerMaxHealth !== "undefined" && player.maxHealth !== playerMaxHealth) {
player.maxHealth = playerMaxHealth;
}
// --- Attack Speed Bonus: Stacks with powerups ---
if (typeof player._attackSpeedBonus === "undefined") player._attackSpeedBonus = 0;
// Otomatik ateş etme (her 10 frame'de bir, rapid fire veya attack speed bonus varsa daha hızlı)
var baseShootInterval = 10;
var rapidFireInterval = powerActive ? 4 : baseShootInterval;
var attackSpeedInterval = Math.max(2, rapidFireInterval - player._attackSpeedBonus * 2);
var shootInterval = attackSpeedInterval;
if (!isGameOver && gameTick % shootInterval === 0 && enemies.length > 0) {
// En yakın düşmanı bul
var minDist = Infinity;
var targetEnemy = null;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
var dx = e.x - player.x;
var dy = e.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDist) {
minDist = dist;
targetEnemy = e;
}
}
if (targetEnemy) {
// --- Otomatik nişan geliştirme: Düşmanın hareketini tahmin et ---
// Düşmanın bir sonraki pozisyonunu tahmin etmek için basit linear prediction
var bulletSpeed = 32;
var ex = targetEnemy.x;
var ey = targetEnemy.y;
var evx = 0,
evy = 0;
// Tahmini hız: son pozisyonları varsa kullan
if (typeof targetEnemy._lastX === "number" && typeof targetEnemy._lastY === "number") {
evx = targetEnemy.x - targetEnemy._lastX;
evy = targetEnemy.y - targetEnemy._lastY;
}
// Hedefe olan mesafe
var dx = ex - player.x;
var dy = ey - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Zaman tahmini (kaç frame sonra mermi ulaşır)
var t = dist / bulletSpeed;
// Tahmini hedef pozisyonu
var predictedX = ex + evx * t;
var predictedY = ey + evy * t;
// Triple shot powerup varsa üçlü mermi ateşle
if (player._tripleShot && player._tripleShot > 0) {
for (var s = -1; s <= 1; s++) {
var angle = Math.atan2(predictedY - player.y, predictedX - player.x) + s * 0.18;
var tx = player.x + Math.cos(angle) * 1000;
var ty = player.y + Math.sin(angle) * 1000;
spawnPlayerBullet(player.x, player.y, tx, ty);
}
} else {
spawnPlayerBullet(player.x, player.y, predictedX, predictedY);
}
}
}
// Düşman update
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
// Skip update if enemy is destroyed or out of bounds
if (!e || typeof e.destroyed !== "undefined" && e.destroyed) {
if (e && e._healthBar) {
e._healthBar.destroy();
}
enemies.splice(i, 1);
continue;
}
if (isOutOfBounds(e)) {
if (e._healthBar) {
e._healthBar.destroy();
}
e.destroy();
enemies.splice(i, 1);
continue;
}
// --- Otomatik nişan için: Son pozisyonu kaydet ---
e._lastX = typeof e.x === "number" ? e.x : 0;
e._lastY = typeof e.y === "number" ? e.y : 0;
if (typeof e.update === "function") e.update();
// Can barı çizimi (her düşmanın üstünde) - optimize: sadece health değiştiyse güncelle
if (!e._healthBar) {
e._healthBar = new Text2('', {
size: 64,
fill: 0xFF4444,
font: "Impact"
});
e._healthBar.anchor.set(0.5, 1);
game.addChild(e._healthBar);
}
if (typeof e.health !== "undefined" && typeof e.maxHealth !== "undefined") {
if (e._healthBar._lastHealth !== e.health || e._healthBar._lastMaxHealth !== e.maxHealth) {
e._healthBar.setText("♥ " + e.health + "/" + e.maxHealth);
e._healthBar._lastHealth = e.health;
e._healthBar._lastMaxHealth = e.maxHealth;
}
e._healthBar.x = e.x;
e._healthBar.y = e.y - e.radius - 18;
e._healthBar.visible = true;
} else {
e._healthBar.visible = false;
}
// Çarpışma: oyuncu & düşman
if (player.intersects(e)) {
if (player._shield && player._shield > 0) {
player._shield--;
LK.effects.flashObject(player, 0x00ffff, 400);
if (player._shield === 0) {
showArenaEventPopup("Shield Broken!");
} else {
showArenaEventPopup("Shield: " + player._shield + " hits left!");
}
} else {
playerHealth--;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
LK.effects.flashObject(player, 0xff4444, 400);
LK.getSound('hit').play();
if (playerHealth <= 0) {
gameOver();
return;
}
}
// Düşmanı yok et, can azalınca
if (typeof e.takeDamage === "function") {
e.takeDamage(e.health); // Tüm canı gitmeli
if (e._shouldRemove) {
if (e._healthBar) {
e._healthBar.destroy();
}
// COIN: Düşman öldüğünde coin spawn et
var baseCoinChance = 0.7;
var extraChance = Math.min(comboCount * 0.10, 0.5);
if (Math.random() < baseCoinChance + extraChance) {
spawnCoin(e.x, e.y);
}
// --- PowerUp drop şansı: %20 + kombo başına %4, max %40 ---
var basePowerUpChance = 0.20;
var extraPowerUpChance = Math.min(comboCount * 0.04, 0.20);
if (Math.random() < basePowerUpChance + extraPowerUpChance) {
spawnPowerUp();
if (powerUps.length > 0) {
var pu = powerUps[powerUps.length - 1];
pu.x = e.x;
pu.y = e.y;
}
}
enemies.splice(i, 1);
// KOMBO: Düşman öldürdüyse kombo başlat
if (typeof e._killedByPlayer === "undefined" || e._killedByPlayer) {
comboCount++;
comboTimer = maxComboTime;
if (comboCount > maxCombo) maxCombo = comboCount;
if (comboCount > storage.maxCombo) {
storage.maxCombo = comboCount;
updateStatsPanel();
}
storage.totalEnemiesKilled = (typeof storage.totalEnemiesKilled === "number" ? storage.totalEnemiesKilled : 0) + 1;
updateStatsPanel();
updateComboText();
}
continue;
}
} else {
e.destroy();
if (e._healthBar) {
e._healthBar.destroy();
}
// COIN: Düşman öldüğünde coin spawn et
var baseCoinChance = 0.7;
var extraChance = Math.min(comboCount * 0.10, 0.5);
if (Math.random() < baseCoinChance + extraChance) {
spawnCoin(e.x, e.y);
}
// --- PowerUp drop şansı: %20 + kombo başına %4, max %40 ---
var basePowerUpChance = 0.20;
var extraPowerUpChance = Math.min(comboCount * 0.04, 0.20);
if (Math.random() < basePowerUpChance + extraPowerUpChance) {
spawnPowerUp();
if (powerUps.length > 0) {
var pu = powerUps[powerUps.length - 1];
pu.x = e.x;
pu.y = e.y;
}
}
enemies.splice(i, 1);
comboCount++;
comboTimer = maxComboTime;
if (comboCount > maxCombo) maxCombo = comboCount;
if (comboCount > storage.maxCombo) {
storage.maxCombo = comboCount;
updateStatsPanel();
}
storage.totalEnemiesKilled = (typeof storage.totalEnemiesKilled === "number" ? storage.totalEnemiesKilled : 0) + 1;
updateStatsPanel();
updateComboText();
continue;
}
}
}
// Oyuncu mermisi update
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
// Skip update if bullet is destroyed or out of bounds
if (!b || typeof b.destroyed !== "undefined" && b.destroyed) {
playerBullets.splice(i, 1);
continue;
}
if (isOutOfBounds(b)) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
if (typeof b.update === "function") b.update();
var hit = false;
// Düşmanlara çarpma
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
LK.getSound('hit').play();
if (typeof e.takeDamage === "function") {
e._killedByPlayer = true;
var permAttackUp = typeof player._permAttackUp === "number" ? player._permAttackUp : 0;
var bulletDamage = 2 + permAttackUp;
e.takeDamage(bulletDamage);
if (e._shouldRemove) {
enemies.splice(j, 1);
}
}
hit = true;
break;
}
}
// WALL BOUNCE: Eğer aktifse, mermi kenara çarptıysa sekmeli
var wallBounceActive = player._wallBounce && player._wallBounce > 0;
if (!hit && wallBounceActive) {
var bounced = false;
if (b.x < b.radius + 10 && b.vx < 0) {
b.x = b.radius + 10;
b.vx *= -1;
bounced = true;
}
if (b.x > 2048 - b.radius - 10 && b.vx > 0) {
b.x = 2048 - b.radius - 10;
b.vx *= -1;
bounced = true;
}
if (b.y < b.radius + 10 && b.vy < 0) {
b.y = b.radius + 10;
b.vy *= -1;
bounced = true;
}
if (b.y > 2732 - b.radius - 10 && b.vy > 0) {
b.y = 2732 - b.radius - 10;
b.vy *= -1;
bounced = true;
}
// Eğer sekmediyse ve hala out of bounds ise yok et
if (!bounced && isOutOfBounds(b)) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
if (hit) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
} else {
if (hit || isOutOfBounds(b)) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
}
}
// Düşman mermisi update
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var b = enemyBullets[i];
// Skip update if bullet is destroyed or out of bounds
if (!b || typeof b.destroyed !== "undefined" && b.destroyed) {
enemyBullets.splice(i, 1);
continue;
}
if (isOutOfBounds(b)) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
if (typeof b.update === "function") b.update();
// Oyuncuya çarpma
var reflectActive = player._reflect && player._reflect > 0;
if (b.intersects(player)) {
if (reflectActive) {
// Reflect: Düşman mermisi oyuncuya çarptığında geri sektir
var newB = new PlayerBullet();
newB.x = b.x;
newB.y = b.y;
var mag = Math.sqrt(b.vx * b.vx + b.vy * b.vy);
if (mag === 0) mag = 1;
newB.vx = -b.vx / mag * 32;
newB.vy = -b.vy / mag * 32;
playerBullets.push(newB);
game.addChild(newB);
LK.effects.flashObject(player, 0x00ffcc, 200);
showArenaEventPopup("Reflected!");
b.destroy();
enemyBullets.splice(i, 1);
continue;
} else if (player._shield && player._shield > 0) {
player._shield--;
LK.effects.flashObject(player, 0x00ffff, 400);
if (player._shield === 0) {
showArenaEventPopup("Shield Broken!");
} else {
showArenaEventPopup("Shield: " + player._shield + " hits left!");
}
} else {
playerHealth--;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
LK.effects.flashObject(player, 0xff4444, 400);
LK.getSound('hit').play();
if (playerHealth <= 0) {
b.destroy();
enemyBullets.splice(i, 1);
gameOver();
return;
}
}
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
if (isOutOfBounds(b)) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
}
// KOMBO zamanlayıcı: Kombo süresi dolarsa sıfırla
if (comboCount > 0) {
comboTimer--;
if (comboTimer <= 0) {
// Show fun popup for max combo if it was a big combo
if (comboCount >= 5) {
showArenaEventPopup("AWESOME COMBO x" + comboCount + "!");
LK.effects.flashScreen(0xffe100, 400);
} else if (comboCount >= 3) {
showArenaEventPopup("Combo x" + comboCount + "!");
}
comboCount = 0;
updateComboText();
}
}
// Fun popup: Level up
if (typeof lastLevel === "undefined") {
lastLevel = level;
}
if (level > lastLevel) {
showArenaEventPopup("LEVEL UP! Level " + level);
LK.effects.flashScreen(0x00ff00, 400);
lastLevel = level;
}
// Fun popup: Coin milestone
if (typeof lastCoinMilestone === "undefined") {
lastCoinMilestone = 0;
}
if (coinCount >= lastCoinMilestone + 10) {
showArenaEventPopup("Coin Collector! ₵" + coinCount);
LK.effects.flashScreen(0xffd700, 300);
lastCoinMilestone = coinCount - coinCount % 10;
}
// PowerUp update ve çarpışma
// --- PowerUp birleşme ve combo mekaniği ---
for (var i = powerUps.length - 1; i >= 0; i--) {
var p = powerUps[i];
// Skip update if powerup is destroyed or out of bounds
if (!p || typeof p.destroyed !== "undefined" && p.destroyed) {
powerUps.splice(i, 1);
continue;
}
if (isOutOfBounds(p)) {
p.destroy();
powerUps.splice(i, 1);
continue;
}
p.update();
// Magnet veya Super Magnet aktifse, powerupları çek
var magnetActive = player._magnet && player._magnet > 0;
var superMagnetActive = player._superMagnetShot && player._superMagnetShot > 0;
if (magnetActive || superMagnetActive) {
var distToPlayer = Math.sqrt((p.x - player.x) * (p.x - player.x) + (p.y - player.y) * (p.y - player.y));
var pullRadius = superMagnetActive ? 800 : 400;
if (distToPlayer < pullRadius) {
// PowerUp oyuncuya doğru çekilsin
var pullSpeed = superMagnetActive ? 60 : 30;
var dx = player.x - p.x;
var dy = player.y - p.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 1) {
p.x += dx / d * pullSpeed;
p.y += dy / d * pullSpeed;
}
}
}
// PowerUp-PowerUp çarpışması: Birleşme
for (var j = i - 1; j >= 0; j--) {
var p2 = powerUps[j];
if (p !== p2 && p.intersects(p2)) {
// İki powerup birleşirse: PowerUpCombo oluştur
var combo = new PowerUpCombo();
combo.x = (p.x + p2.x) / 2;
combo.y = (p.y + p2.y) / 2;
combo.effects = [];
// Farklı efektleri ekle (tekrar yok)
if (p.effect && combo.effects.indexOf(p.effect) === -1) combo.effects.push(p.effect);
if (p2.effect && combo.effects.indexOf(p2.effect) === -1) combo.effects.push(p2.effect);
// Eğer p veya p2 zaten combo ise, efektlerini ekle
if (p.effects && Array.isArray(p.effects)) {
for (var ce = 0; ce < p.effects.length; ce++) {
if (combo.effects.indexOf(p.effects[ce]) === -1) combo.effects.push(p.effects[ce]);
}
}
if (p2.effects && Array.isArray(p2.effects)) {
for (var ce2 = 0; ce2 < p2.effects.length; ce2++) {
if (combo.effects.indexOf(p2.effects[ce2]) === -1) combo.effects.push(p2.effects[ce2]);
}
}
// Sınır: En fazla 3 efektli combo
if (combo.effects.length > 3) combo.effects = combo.effects.slice(0, 3);
powerUps.splice(i, 1);
powerUps.splice(j, 1);
p.destroy();
p2.destroy();
powerUps.push(combo);
game.addChild(combo);
// Combo birleşme popup
showArenaEventPopup("PowerUp Combo!");
break;
}
}
// Oyuncu ile çarpışma
if (player.intersects(p)) {
// PowerUp veya PowerUpCombo alındı
var effectsToApply = [];
if (p.effect) {
effectsToApply = [p.effect];
} else if (p.effects && Array.isArray(p.effects)) {
effectsToApply = p.effects.slice();
}
var popupMsg = [];
var comboRapid = false,
comboMagnet = false;
// --- PowerUp efektlerini uygula ---
for (var ef = 0; ef < effectsToApply.length; ef++) {
var effect = effectsToApply[ef];
if (effect === "rapid") {
// --- Attack Speed Bonus: Stackable ---
if (typeof player._attackSpeedBonus !== "number") player._attackSpeedBonus = 0;
player._attackSpeedBonus += 1;
powerActive = true;
powerTimer = 600;
popupMsg.push("RAPID FIRE! (10s)");
comboRapid = true;
} else if (effect === "triple") {
player._tripleShot = 600;
popupMsg.push("TRIPLE SHOT! (10s)");
} else if (effect === "shield") {
player._shield = 5;
popupMsg.push("Shield (5 hits)!");
} else if (effect === "heal") {
playerHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg.push("Full Health!");
} else if (effect === "wallBounce") {
player._wallBounce = 600;
popupMsg.push("WALL BOUNCE! (10s)");
} else if (effect === "reflect") {
player._reflect = 600;
popupMsg.push("REFLECT ENEMY BULLETS! (10s)");
} else if (effect === "slow") {
// Zaman yavaşlatma: tüm düşmanlar yavaşlar
for (var si = 0; si < enemies.length; si++) {
enemies[si]._frozen = 180; // 3 saniye yavaşlat
}
popupMsg.push("TIME SLOW! (3s)");
LK.effects.flashScreen(0x66ccff, 400);
} else if (effect === "magnet") {
// Magnet: yakındaki coin ve powerupları çek
comboMagnet = true;
popupMsg.push("MAGNET! (5s)");
player._magnet = 300; // 5 saniye
} else if (effect === "randomizer") {
// Randomizer: tüm düşmanların tipi değişir
for (var ri = 0; ri < enemies.length; ri++) {
var e = enemies[ri];
var t = Math.random();
var newE;
if (t < 0.4) newE = new Enemy();else if (t < 0.7) newE = new Enemy2();else newE = new Enemy3();
newE.x = e.x;
newE.y = e.y;
newE.maxHealth = e.maxHealth;
newE.health = e.health;
newE._frozen = e._frozen;
newE._healthBar = e._healthBar;
newE._visHealthBar = e._visHealthBar;
newE._visHealthBarBg = e._visHealthBarBg;
newE._visHealthBarFg = e._visHealthBarFg;
enemies[ri].destroy();
enemies[ri] = newE;
game.addChild(newE);
}
popupMsg.push("RANDOMIZER! (All enemies changed)");
LK.effects.flashScreen(0x00ffcc, 400);
} else if (effect === "superHeal") {
// Süper can: hem canı doldur hem max canı 2 artır
playerMaxHealth += 2;
playerHealth = playerMaxHealth;
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg.push("SUPER HEAL! (+2 Max Health)");
} else if (effect === "freezeBullets") {
// Freeze all enemy bullets for 3 seconds
for (var bi = 0; bi < enemyBullets.length; bi++) {
enemyBullets[bi]._frozen = 180;
}
popupMsg.push("FREEZE ENEMY BULLETS! (3s)");
LK.effects.flashScreen(0x00eaff, 400);
} else if (effect === "coinRain") {
// Spawn 10 coins at random locations
for (var ci = 0; ci < 10; ci++) {
spawnCoin();
}
popupMsg.push("COIN RAIN!");
LK.effects.flashScreen(0xffd700, 400);
} else if (effect === "enemyClear") {
// Destroy all enemies on screen
for (var ei = enemies.length - 1; ei >= 0; ei--) {
if (enemies[ei]._healthBar) enemies[ei]._healthBar.destroy();
if (enemies[ei]._visHealthBar) enemies[ei]._visHealthBar.destroy();
enemies[ei].destroy();
enemies.splice(ei, 1);
}
popupMsg.push("ENEMY CLEAR!");
LK.effects.flashScreen(0xff4444, 600);
} else if (effect === "scoreBoost") {
// 2x skor için 15 saniye
player._scoreBoost = 900;
popupMsg.push("SCORE BOOST! (15s)");
}
}
// --- PowerUp Kombinasyonları: Rapid + Magnet = Süper Çekim Ateşi ---
if (comboRapid && comboMagnet) {
player._superMagnetShot = 600; // 10 saniye süper çekim ateşi
popupMsg.push("SUPER MAGNET SHOT! (10s)");
LK.effects.flashScreen(0xff00ff, 600);
}
// --- PowerUp efektleri bitti ---
LK.effects.flashObject(player, 0x00ffcc, 400);
showArenaEventPopup("PowerUp: " + popupMsg.join(" + "));
p.destroy();
powerUps.splice(i, 1);
} else if (isOutOfBounds(p)) {
p.destroy();
powerUps.splice(i, 1);
}
}
// Coin update ve toplama
for (var i = coins.length - 1; i >= 0; i--) {
var c = coins[i];
// Skip update if coin is destroyed or out of bounds
if (!c || typeof c.destroyed !== "undefined" && c.destroyed) {
coins.splice(i, 1);
continue;
}
if (isOutOfBounds(c)) {
c.destroy();
coins.splice(i, 1);
continue;
}
c.update();
// Magnet veya Super Magnet aktifse, coinleri çek
var magnetActive = player._magnet && player._magnet > 0;
var superMagnetActive = player._superMagnetShot && player._superMagnetShot > 0;
if (magnetActive || superMagnetActive) {
var distToPlayer = Math.sqrt((c.x - player.x) * (c.x - player.x) + (c.y - player.y) * (c.y - player.y));
var pullRadius = superMagnetActive ? 800 : 400;
if (distToPlayer < pullRadius) {
// Coin oyuncuya doğru çekilsin
var pullSpeed = superMagnetActive ? 60 : 30;
var dx = player.x - c.x;
var dy = player.y - c.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > 1) {
c.x += dx / d * pullSpeed;
c.y += dy / d * pullSpeed;
}
}
}
if (player.intersects(c)) {
coinCount++;
coinTxt.setText('₵ ' + coinCount);
// COIN: Save permanently
storage.coins = coinCount;
LK.effects.flashObject(player, 0xFFD700, 200);
// Fun popup: First coin
if (coinCount === 1) {
showArenaEventPopup("First Coin Collected!");
LK.effects.flashScreen(0xffd700, 300);
}
c.destroy();
coins.splice(i, 1);
} else if (isOutOfBounds(c)) {
c.destroy();
coins.splice(i, 1);
}
}
// PowerUp etkisi süresi
if (powerActive) {
powerTimer--;
if (powerTimer <= 0) {
powerActive = false;
// --- Attack Speed Bonus: Remove one stack when rapid fire ends ---
if (typeof player._attackSpeedBonus === "number" && player._attackSpeedBonus > 0) {
player._attackSpeedBonus -= 1;
if (player._attackSpeedBonus < 0) player._attackSpeedBonus = 0;
}
}
}
// Triple shot süresi azalt
if (player._tripleShot && player._tripleShot > 0) {
player._tripleShot--;
if (player._tripleShot <= 0) player._tripleShot = 0;
}
// Wall bounce süresi azalt
if (player._wallBounce && player._wallBounce > 0) {
player._wallBounce--;
if (player._wallBounce <= 0) player._wallBounce = 0;
}
// Reflect süresi azalt
if (player._reflect && player._reflect > 0) {
player._reflect--;
if (player._reflect <= 0) player._reflect = 0;
}
// Magnet süresi azalt
if (player._magnet && player._magnet > 0) {
player._magnet--;
if (player._magnet <= 0) player._magnet = 0;
}
// Super Magnet Shot süresi azalt
if (player._superMagnetShot && player._superMagnetShot > 0) {
player._superMagnetShot--;
if (player._superMagnetShot <= 0) player._superMagnetShot = 0;
}
// Score Boost süresi azalt
if (player._scoreBoost && player._scoreBoost > 0) {
player._scoreBoost--;
if (player._scoreBoost <= 0) player._scoreBoost = 0;
}
// Freeze enemy bullets süresi azalt
for (var bi = 0; bi < enemyBullets.length; bi++) {
if (enemyBullets[bi]._frozen && enemyBullets[bi]._frozen > 0) {
enemyBullets[bi]._frozen--;
// Dondurulmuşsa hareket etmesin
enemyBullets[bi].vx = 0;
enemyBullets[bi].vy = 0;
}
}
// PowerUp spawn (her 6 saniyede bir)
if (gameTick % 360 === 0) {
spawnPowerUp();
}
// COIN: Sık sık rastgele coin spawn et (her 60 frame'de bir, %60 olasılıkla)
if (gameTick % 60 === 0) {
if (Math.random() < 0.6) {
spawnCoin();
}
}
// Düşman spawn
// --- Düşmanlar çok çıksın: skor arttıkça daha sık spawn ---
// spawnInterval: skor arttıkça daha hızlı (min 8 frame)
var spawnInterval = Math.max(60 - level * 2 - Math.floor(score / 10), 8);
// Aynı anda birden fazla düşman spawn: skor arttıkça daha fazla
var enemySpawnCount = 1 + Math.floor(score / 30);
if (gameTick % spawnInterval === 0) {
for (var s = 0; s < enemySpawnCount; s++) {
spawnEnemy();
}
}
};
// Sürükleme başlat
game.down = function (x, y, obj) {
// If player is tapped, start dragging
var px = player.x,
py = player.y;
var dx = x - px,
dy = y - py;
var dist = Math.sqrt(dx * dx + dy * dy);
// User-friendly: If tapped on player, start dragging, otherwise do nothing
if (dist < player.radius + 80) {
// wider area, easier drag
dragNode = player;
lastPlayerPos.x = x;
lastPlayerPos.y = y;
// When drag starts, don't fire, prevent accidental fire
// Drag threshold: set a flag to check if drag distance exceeds a threshold before firing
dragNode._dragStarted = false;
dragNode._dragStartX = x;
dragNode._dragStartY = y;
dragNode._dragStartTime = Date.now();
} else {
// (Removed: tap-to-shoot code is now gone)
}
};
// Sürükleme bırak
game.up = function (x, y, obj) {
if (dragNode && typeof dragNode._dragStarted !== "undefined") {
// If drag didn't start and released quickly, fire (tap-to-shoot)
var dragDx = x - dragNode._dragStartX;
var dragDy = y - dragNode._dragStartY;
var dragDist = Math.sqrt(dragDx * dragDx + dragDy * dragDy);
var dragTime = Date.now() - (dragNode._dragStartTime || 0);
if (!dragNode._dragStarted && dragDist < 24 && dragTime < 200) {
spawnPlayerBullet(player.x, player.y, x, y);
LK.getSound('shoot').play();
}
dragNode._dragStarted = false;
dragNode._dragStartX = 0;
dragNode._dragStartY = 0;
dragNode._dragStartTime = 0;
}
dragNode = null;
// User-friendly: Update last position when drag is released
lastPlayerPos.x = 0;
lastPlayerPos.y = 0;
};
// Sürükleme hareketi: Oyuncu mouse ile birlikte hareket etsin
game.move = function (x, y, obj) {
// Oyuncu mouse ile birlikte hareket etsin
if (player) {
// Kullanıcı dostu: Oyuncunun ekran dışına çıkmasını engelle
var minX = player.radius + 20;
var maxX = 2048 - player.radius - 20;
var minY = player.radius + 20;
var maxY = 2732 - player.radius - 20;
player.x = x;
player.y = y;
if (player.x < minX) player.x = minX;
if (player.x > maxX) player.x = maxX;
if (player.y < minY) player.y = minY;
if (player.y > maxY) player.y = maxY;
}
};
// At game start, reset score, level, and health
score = 0;
level = 1;
playerHealth = playerMaxHealth;
// --- STATISTICS: Persistent High Score, Max Combo, Total Enemies Killed ---
storage.highScore = typeof storage.highScore === "number" ? storage.highScore : 0;
storage.maxCombo = typeof storage.maxCombo === "number" ? storage.maxCombo : 0;
storage.totalEnemiesKilled = typeof storage.totalEnemiesKilled === "number" ? storage.totalEnemiesKilled : 0;
// COIN: Load persistent coin count
coinCount = typeof storage.coins === "number" ? storage.coins : 0;
if (typeof coinTxt !== "undefined" && coinTxt._lastCoinCount !== coinCount) {
coinTxt.setText('₵ ' + coinCount);
coinTxt._lastCoinCount = coinCount;
}
if (typeof player !== "undefined") {
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
}
// --- STATISTICS GUI ---
// Oyuncuya istatistikleri gösteren panel (sol üstte, büyük ve kolay okunur, menü ikonundan uzak)
var statsPanel = new Container();
LK.gui.topLeft.addChild(statsPanel);
// Sol üstte, menü ikonundan uzak durmak için 110px sağa ve 10px aşağıya kaydır
statsPanel.x = 110;
statsPanel.y = 10;
// High Score
var statsHighScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 48,
fill: 0xFFD700,
font: "Impact"
});
statsHighScoreTxt.anchor.set(0, 0);
statsHighScoreTxt.x = 0;
statsHighScoreTxt.y = 0;
statsPanel.addChild(statsHighScoreTxt);
// Max Combo
var statsMaxComboTxt = new Text2('Max Combo: ' + storage.maxCombo, {
size: 48,
fill: 0xFFFA00,
font: "Impact"
});
statsMaxComboTxt.anchor.set(0, 0);
statsMaxComboTxt.x = 0;
statsMaxComboTxt.y = 60;
statsPanel.addChild(statsMaxComboTxt);
// Total Enemies Killed
var statsEnemiesKilledTxt = new Text2('Enemies Killed: ' + storage.totalEnemiesKilled, {
size: 48,
fill: 0xFF4444,
font: "Impact"
});
statsEnemiesKilledTxt.anchor.set(0, 0);
statsEnemiesKilledTxt.x = 0;
statsEnemiesKilledTxt.y = 120;
statsPanel.addChild(statsEnemiesKilledTxt);
// Paneli güncelleyen fonksiyon
function updateStatsPanel() {
if (typeof statsHighScoreTxt !== "undefined") statsHighScoreTxt.setText('High Score: ' + storage.highScore);
if (typeof statsMaxComboTxt !== "undefined") statsMaxComboTxt.setText('Max Combo: ' + storage.maxCombo);
if (typeof statsEnemiesKilledTxt !== "undefined") statsEnemiesKilledTxt.setText('Enemies Killed: ' + storage.totalEnemiesKilled);
}
updateStatsPanel();
// --- NEW: Random PowerUp Shop Button ---
// Spend 30 coins to get a random powerup effect
var randomPowerBtn = new Text2('Random PowerUp (30₵)', {
size: 60,
fill: 0x00BFFF,
// Bright blue for high visibility
font: "Impact"
});
randomPowerBtn.anchor.set(0.5, 0);
LK.gui.top.addChild(randomPowerBtn);
randomPowerBtn.y = 420;
randomPowerBtn.interactive = true;
randomPowerBtn.buttonMode = true;
randomPowerBtn.visible = true;
randomPowerBtn.down = function (x, y, obj) {
if (coinCount >= 30) {
coinCount -= 30;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Pick a random effect
var effects = ["rapid", "triple", "heal", "wallBounce", "reflect", "shield", "slow", "magnet", "superHeal", "freezeBullets", "coinRain", "enemyClear", "scoreBoost"];
var effect = effects[Math.floor(Math.random() * effects.length)];
var popupMsg = "";
if (effect === "rapid") {
// --- Attack Speed Bonus: Stackable ---
if (typeof player._attackSpeedBonus !== "number") player._attackSpeedBonus = 0;
player._attackSpeedBonus += 1;
powerActive = true;
powerTimer = 600;
popupMsg = "RAPID FIRE! (10s)";
} else if (effect === "triple") {
player._tripleShot = 600;
popupMsg = "TRIPLE SHOT! (10s)";
} else if (effect === "heal") {
playerHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg = "Full Health!";
} else if (effect === "wallBounce") {
player._wallBounce = 600;
popupMsg = "WALL BOUNCE! (10s)";
} else if (effect === "reflect") {
player._reflect = 600;
popupMsg = "REFLECT ENEMY BULLETS! (10s)";
} else if (effect === "shield") {
player._shield = 5;
popupMsg = "Shield (5 hits)!";
} else if (effect === "slow") {
for (var si = 0; si < enemies.length; si++) {
enemies[si]._frozen = 180;
}
popupMsg = "TIME SLOW! (3s)";
LK.effects.flashScreen(0x66ccff, 400);
} else if (effect === "magnet") {
player._magnet = 300;
popupMsg = "MAGNET! (5s)";
} else if (effect === "superHeal") {
playerMaxHealth += 2;
playerHealth = playerMaxHealth;
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
updateScoreAndLevel();
popupMsg = "SUPER HEAL! (+2 Max Health)";
} else if (effect === "freezeBullets") {
for (var bi = 0; bi < enemyBullets.length; bi++) {
enemyBullets[bi]._frozen = 180;
}
popupMsg = "FREEZE ENEMY BULLETS! (3s)";
LK.effects.flashScreen(0x00eaff, 400);
} else if (effect === "coinRain") {
for (var ci = 0; ci < 10; ci++) {
spawnCoin();
}
popupMsg = "COIN RAIN!";
LK.effects.flashScreen(0xffd700, 400);
} else if (effect === "enemyClear") {
for (var ei = enemies.length - 1; ei >= 0; ei--) {
if (enemies[ei]._healthBar) enemies[ei]._healthBar.destroy();
if (enemies[ei]._visHealthBar) enemies[ei]._visHealthBar.destroy();
enemies[ei].destroy();
enemies.splice(ei, 1);
}
popupMsg = "ENEMY CLEAR!";
LK.effects.flashScreen(0xff4444, 600);
} else if (effect === "scoreBoost") {
player._scoreBoost = 900;
popupMsg = "SCORE BOOST! (15s)";
}
LK.effects.flashObject(player, 0xFFD700, 400); // Coin color flash
showArenaEventPopup("PowerUp: " + popupMsg);
} else {
showArenaEventPopup("Not enough coins!");
}
};
// --- NEW: Random Permanent Ultra Power Button (red) ---
var ultraPowerBtn = new Text2('Random ULTRA Power (100₵)', {
size: 60,
fill: 0xFF2222,
// Red
font: "Impact"
});
ultraPowerBtn.anchor.set(0.5, 0);
LK.gui.top.addChild(ultraPowerBtn);
ultraPowerBtn.y = randomPowerBtn.y + 90;
ultraPowerBtn.interactive = true;
ultraPowerBtn.buttonMode = true;
ultraPowerBtn.visible = true;
// --- NEW: Permanent Upgrade Shop (bottom left) ---
var permUpgradeBtn = new Text2('+1 Max Health (250₵)', {
size: 60,
fill: 0x00ff88,
font: "Impact"
});
permUpgradeBtn.anchor.set(0, 1); // bottom left
LK.gui.bottomLeft.addChild(permUpgradeBtn);
permUpgradeBtn.y = 0;
permUpgradeBtn.x = 0;
permUpgradeBtn.interactive = true;
permUpgradeBtn.buttonMode = true;
permUpgradeBtn.visible = true;
// --- NEW: Permanent Max Attack Upgrade Button (bottom right, above health) ---
var permAttackUpgradeBtn = new Text2('+1 Max Attack (250₵)', {
size: 60,
fill: 0xff8800,
font: "Impact"
});
permAttackUpgradeBtn.anchor.set(1, 1);
LK.gui.bottomRight.addChild(permAttackUpgradeBtn);
permAttackUpgradeBtn.y = permUpgradeBtn.y - 90;
permAttackUpgradeBtn.x = 0;
permAttackUpgradeBtn.interactive = true;
permAttackUpgradeBtn.buttonMode = true;
permAttackUpgradeBtn.visible = true;
// Show current permanent upgrades (bottom left, above button)
var permUpgradeInfoTxt = new Text2('', {
size: 48,
fill: 0xffffff,
font: "Impact"
});
permUpgradeInfoTxt.anchor.set(0, 1); // bottom left
LK.gui.bottomLeft.addChild(permUpgradeInfoTxt);
permUpgradeInfoTxt.y = permUpgradeBtn.y + 80;
permUpgradeInfoTxt.x = 0;
// Show current permanent attack upgrades (bottom right, above attack button)
var permAttackUpgradeInfoTxt = new Text2('', {
size: 48,
fill: 0xff8800,
font: "Impact"
});
permAttackUpgradeInfoTxt.anchor.set(1, 1);
LK.gui.bottomRight.addChild(permAttackUpgradeInfoTxt);
permAttackUpgradeInfoTxt.y = permAttackUpgradeBtn.y + 80;
permAttackUpgradeInfoTxt.x = 0;
// Helper to update permanent upgrade info
function updatePermUpgradeInfo() {
var healthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
if (healthUp > 0) {
// If maxed (let's say 10 is max), show MAXED and use green color, add background
if (healthUp >= 10) {
permUpgradeInfoTxt.setText("Max Health +" + healthUp + " (MAXED, permanent)");
permUpgradeInfoTxt.fill = 0x00ff00;
permUpgradeInfoTxt.size = 36;
permUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.95,
padding: 18,
radius: 18
};
} else {
permUpgradeInfoTxt.setText("Max Health +" + healthUp + " (permanent)");
permUpgradeInfoTxt.fill = 0xffffff;
permUpgradeInfoTxt.size = 36;
permUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.8,
padding: 12,
radius: 12
};
}
permUpgradeInfoTxt.visible = true;
} else {
permUpgradeInfoTxt.setText("");
permUpgradeInfoTxt.visible = false;
permUpgradeInfoTxt.background = undefined;
}
var attackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
if (attackUp > 0) {
// If maxed (let's say 10 is max), show MAXED and use orange color, add background
if (attackUp >= 10) {
permAttackUpgradeInfoTxt.setText("Max Attack +" + attackUp + " (MAXED, permanent)");
permAttackUpgradeInfoTxt.fill = 0xff8800;
permAttackUpgradeInfoTxt.size = 36;
permAttackUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.95,
padding: 18,
radius: 18
};
} else {
permAttackUpgradeInfoTxt.setText("Max Attack +" + attackUp + " (permanent)");
permAttackUpgradeInfoTxt.fill = 0xff8800;
permAttackUpgradeInfoTxt.size = 36;
permAttackUpgradeInfoTxt.background = {
color: 0x222222,
alpha: 0.8,
padding: 12,
radius: 12
};
}
permAttackUpgradeInfoTxt.visible = true;
} else {
permAttackUpgradeInfoTxt.setText("");
permAttackUpgradeInfoTxt.visible = false;
permAttackUpgradeInfoTxt.background = undefined;
}
}
updatePermUpgradeInfo();
permUpgradeBtn.down = function (x, y, obj) {
// Always update coinCount from storage before checking
coinCount = typeof storage.coins === "number" ? storage.coins : coinCount;
var healthUp = typeof storage.permMaxHealthUp === "number" ? storage.permMaxHealthUp : 0;
if (coinCount >= 250) {
coinCount -= 250;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Increase permanent max health
healthUp++;
storage.permMaxHealthUp = healthUp;
updatePermUpgradeInfo();
LK.effects.flashScreen(0x00ff88, 400);
// Apply immediately to player
playerMaxHealth = 10 + healthUp;
playerHealth = playerMaxHealth;
if (typeof player !== "undefined") {
if (typeof player.maxHealth !== "undefined") player.maxHealth = playerMaxHealth;
if (typeof player.health !== "undefined") player.health = playerHealth;
}
updateScoreAndLevel();
} else {
showArenaEventPopup("Not enough coins!");
}
};
// Permanent Max Attack Upgrade Button logic
permAttackUpgradeBtn.down = function (x, y, obj) {
coinCount = typeof storage.coins === "number" ? storage.coins : coinCount;
var attackUp = typeof storage.permMaxAttackUp === "number" ? storage.permMaxAttackUp : 0;
if (coinCount >= 250) {
coinCount -= 250;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Increase permanent max attack
attackUp++;
storage.permMaxAttackUp = attackUp;
updatePermUpgradeInfo();
LK.effects.flashScreen(0xff8800, 400);
// Apply immediately to player (if you want, e.g. set player._permAttackUp = attackUp)
if (typeof player !== "undefined") {
player._permAttackUp = attackUp;
}
} else {
showArenaEventPopup("Not enough coins!");
}
};
// --- ULTRA POWER EFFECT TEXT (top-right, red, bold) ---
var ultraPowerEffectTxt = new Text2('', {
size: 60,
fill: 0xFF2222,
font: "Impact",
fontWeight: "bold"
});
ultraPowerEffectTxt.anchor.set(1, 0); // right-top
LK.gui.topRight.addChild(ultraPowerEffectTxt);
ultraPowerEffectTxt.y = 0;
ultraPowerEffectTxt.x = 0; // LK.gui.topRight is already at the right edge
// Helper to set ultra power effect text
var ultraPowerEffectTimeout = null;
function setUltraPowerEffectText(txt) {
if (typeof ultraPowerEffectTxt !== "undefined" && ultraPowerEffectTxt && typeof ultraPowerEffectTxt.setText === "function") {
ultraPowerEffectTxt.setText(txt || '');
ultraPowerEffectTxt.visible = !!txt;
// Hide after 2.5 seconds if text is set
if (ultraPowerEffectTimeout) {
LK.clearTimeout(ultraPowerEffectTimeout);
ultraPowerEffectTimeout = null;
}
if (txt) {
ultraPowerEffectTimeout = LK.setTimeout(function () {
ultraPowerEffectTxt.setText('');
ultraPowerEffectTxt.visible = false;
ultraPowerEffectTimeout = null;
}, 5000);
}
}
}
// On game start, clear ultra power effect text
setUltraPowerEffectText('');
// Track the current ultra power effect
var currentUltraPowerEffect = "";
// Update the text when ultra power is bought
ultraPowerBtn.down = function (x, y, obj) {
// Always update coinCount from storage before checking
coinCount = typeof storage.coins === "number" ? storage.coins : coinCount;
if (coinCount >= 100) {
coinCount -= 100;
storage.coins = coinCount;
if (typeof coinTxt !== "undefined") coinTxt.setText('₵ ' + coinCount);
// Pick a random ultra-strong permanent effect
var ultraEffects = ["superScoreBoost", "permaTriple", "permaRapid", "permaWallBounce", "permaReflect"];
var effect = ultraEffects[Math.floor(Math.random() * ultraEffects.length)];
var popupMsg = "";
var effectLabel = "";
if (effect === "superScoreBoost") {
player._superScoreBoost = true;
player._scoreBoost = 1;
popupMsg = "PERMANENT: 10x Score!";
effectLabel = "10x Score!";
} else if (effect === "permaTriple") {
player._tripleShot = 999999;
popupMsg = "PERMANENT: Triple Shot!";
effectLabel = "Triple Shot!";
} else if (effect === "permaRapid") {
// --- Attack Speed Bonus: Permanent ---
if (typeof player._attackSpeedBonus !== "number") player._attackSpeedBonus = 0;
player._attackSpeedBonus += 5; // Permanent big bonus
powerActive = true;
powerTimer = 999999;
popupMsg = "PERMANENT: Rapid Fire!";
effectLabel = "Rapid Fire!";
} else if (effect === "permaWallBounce") {
player._wallBounce = 999999;
popupMsg = "PERMANENT: Wall Bounce!";
effectLabel = "Wall Bounce!";
} else if (effect === "permaReflect") {
player._reflect = 999999;
popupMsg = "PERMANENT: Reflect!";
effectLabel = "Reflect!";
}
LK.effects.flashObject(player, 0xFF2222, 600);
showArenaEventPopup("ULTRA Power: " + popupMsg);
// Show effect label at top-right
currentUltraPowerEffect = effectLabel;
setUltraPowerEffectText(effectLabel);
} else {
showArenaEventPopup("Not enough coins!");
}
};
powerup. In-Game asset. 2d. High contrast. No shadows
green robot enemy. In-Game asset. 2d. High contrast. No shadows
purple robot enemy. In-Game asset. 2d. High contrast. No shadows
robot ammo. In-Game asset. 2d. High contrast. No shadows
coin. In-Game asset. 2d. High contrast. No shadows
robot ammo very red very big. In-Game asset. 2d. High contrast. No shadows
2d space bg. In-Game asset. 2d. High contrast. No shadows