/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Boss var Boss = Container.expand(function () { var self = Container.call(this); var boss = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.maxHp = 10; self.hp = 10; self.shootCooldown = 0; self.patternTick = 0; self.patternType = 0; self.moveDir = 1; self.moveSpeed = 6; self.update = function () { // Boss movement: horizontal oscillation self.x += self.moveDir * self.moveSpeed; if (self.x < 320) { self.x = 320; self.moveDir = 1; } if (self.x > 2048 - 320) { self.x = 2048 - 320; self.moveDir = -1; } self.patternTick++; }; return self; }); // Boss bullet var BossBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('bossBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speedY = 18; self.speedX = 0; self.update = function () { self.x += self.speedX; self.y += self.speedY; }; return self; }); // Heart var Heart = Container.expand(function () { var self = Container.call(this); var heart = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); self.speedY = 12; self.update = function () { self.y += self.speedY; }; return self; }); // Player var Player = Container.expand(function () { var self = Container.call(this); var player = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.cooldown = 0; return self; }); // Player bullet var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); // Calculate direction toward last tap var dx = lastTapX - player.x; var dy = lastTapY - (player.y - 100); var mag = Math.sqrt(dx * dx + dy * dy); // Defensive: if mag is 0, shoot straight up if (mag === 0) { dx = 0; dy = -1; mag = 1; } var speed = 36; self.speedX = dx / mag * speed; self.speedY = dy / mag * speed; self.update = function () { self.x += self.speedX; self.y += self.speedY; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181a1b }); /**** * Game Code ****/ // Game state variables // Player bullet // Boss bullet // Player // Boss // Boss HP bar // Boss HP bar background // Sound effects // Music var currentLevel = 1; var maxLevel = 30; var player, boss; var playerBullets = []; var bossBullets = []; var canShoot = true; var bossHpBar, bossHpBarBg, bossHpText; var scoreText, levelText; var isGameOver = false; var isYouWin = false; var lastPlayerHit = false; var lastBossHit = false; var playerInvulnTicks = 0; // Hearts var hearts = []; var heartSpawnTimer = null; // Store last tap position for bullet direction var lastTapX = 2048 / 2; var lastTapY = 600; // --- Start Menu Overlay --- var startMenuOverlay = new Container(); var startMenuBg = LK.getAsset('bossHpBarBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, width: 1200, height: 900 }); startMenuBg.alpha = 0.92; startMenuOverlay.addChild(startMenuBg); var startTitle = new Text2('BOSS SAVAŞI', { size: 180, fill: 0xFFE066 }); startTitle.anchor.set(0.5, 0.5); startTitle.x = 2048 / 2; startTitle.y = 2732 / 2 - 220; startMenuOverlay.addChild(startTitle); var startDesc = new Text2('10 zorlu bossu yen!\nHer seviyede güçlen!', { size: 80, fill: 0xffffff }); startDesc.anchor.set(0.5, 0.5); startDesc.x = 2048 / 2; startDesc.y = 2732 / 2 - 40; startMenuOverlay.addChild(startDesc); var startBtn = LK.getAsset('bossHpBar', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 + 220, width: 600, height: 140 }); startBtn.alpha = 0.98; startMenuOverlay.addChild(startBtn); var startBtnText = new Text2('BAŞLA', { size: 110, fill: 0xffffff }); startBtnText.anchor.set(0.5, 0.5); startBtnText.x = 2048 / 2; startBtnText.y = 2732 / 2 + 220; startMenuOverlay.addChild(startBtnText); game.addChild(startMenuOverlay); var gameStarted = false; // Start menu tap handler startBtn.down = function (x, y, obj) { if (!gameStarted) { startMenuOverlay.visible = false; gameStarted = true; } }; // Prevent game from starting until menu is dismissed // Boss damage per level: first boss 10, +2 per level function getBossDamage(level) { return 10 + (level - 1) * 2; } // Start music LK.playMusic('bossMusic'); // --- UI --- scoreText = new Text2('Score: 0', { size: 90, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); levelText = new Text2('Level 1', { size: 70, fill: 0xFFE066 }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); levelText.y = 110; // Boss HP bar bossHpBarBg = LK.getAsset('bossHpBarBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 320 }); bossHpBar = LK.getAsset('bossHpBar', { anchorX: 0, anchorY: 0.5, x: 2048 / 2 - 400, y: 320 }); bossHpText = new Text2('', { size: 60, fill: 0xFFFFFF }); bossHpText.anchor.set(0.5, 0.5); bossHpText.x = 2048 / 2; bossHpText.y = 320; game.addChild(bossHpBarBg); game.addChild(bossHpBar); game.addChild(bossHpText); // --- Player --- player = new Player(); player.x = 2048 / 2; player.y = 2732 - 320; player.hp = 100; game.addChild(player); // Player HP UI var playerHpText = new Text2('HP: 100 / 100', { size: 80, fill: 0x4ec3ff }); playerHpText.anchor.set(0.5, 1); LK.gui.bottom.addChild(playerHpText); playerHpText.y = -40; // --- Boss --- var bossShootTimer = null; function spawnBoss(level) { if (boss) { boss.destroy(); } boss = new Boss(); // Boss HP increases 50x each level boss.maxHp = 10 * Math.pow(50, level - 1); boss.hp = boss.maxHp; boss.x = 2048 / 2; boss.y = 600; boss.moveSpeed = 6 + Math.floor(level / 2); boss.patternType = (level - 1) % 3; boss.shootCooldown = 0; boss.patternTick = 0; game.addChild(boss); boss._vulnerable = true; updateBossHpBar(); // Clear any previous boss shoot timer if (bossShootTimer !== null) { LK.clearInterval(bossShootTimer); bossShootTimer = null; } // Set up boss shooting every 2 seconds (2000ms), but fire more bullets as level increases bossShootTimer = LK.setInterval(function () { if (!isGameOver && !isYouWin && boss) { // Number of bullets increases with level (minimum 1, max 10) var numBullets = Math.min(1 + Math.floor((currentLevel - 1) / 1), 10); var spread = 120 + 40 * (numBullets - 1); for (var i = 0; i < numBullets; i++) { var bullet = new BossBullet(); // Spread bullets horizontally if (numBullets === 1) { bullet.x = boss.x; } else { bullet.x = boss.x - spread / 2 + spread / (numBullets - 1) * i; } bullet.y = boss.y + 120; bullet.speedY = 18 + currentLevel * 1.5; bullet.speedX = 0; bossBullets.push(bullet); game.addChild(bullet); } LK.getSound('bossShoot').play(); } }, 2000); } spawnBoss(currentLevel); // --- Helper functions --- function updateBossHpBar() { var hpRatio = boss.hp / boss.maxHp; bossHpBar.width = 800 * hpRatio; bossHpText.setText('Boss HP: ' + boss.hp + ' / ' + boss.maxHp); } function resetGameState() { // Remove all bullets for (var i = 0; i < playerBullets.length; i++) { playerBullets[i].destroy(); } for (var i = 0; i < bossBullets.length; i++) { bossBullets[i].destroy(); } playerBullets = []; bossBullets = []; player.x = 2048 / 2; player.y = 2732 - 320; player.hp = 100; playerHpText.setText('HP: 100 / 100'); playerInvulnTicks = 0; lastPlayerHit = false; lastBossHit = false; isGameOver = false; isYouWin = false; canShoot = true; LK.setScore(0); scoreText.setText('Score: 0'); currentLevel = 1; levelText.setText('Level 1'); // Remove all hearts for (var i = 0; i < hearts.length; i++) { hearts[i].destroy(); } hearts = []; // Clear heart spawn timer if exists if (typeof heartSpawnTimer !== "undefined" && heartSpawnTimer !== null) { LK.clearInterval(heartSpawnTimer); heartSpawnTimer = null; } // Clear boss shoot timer if exists if (typeof bossShootTimer !== "undefined" && bossShootTimer !== null) { LK.clearInterval(bossShootTimer); bossShootTimer = null; } spawnBoss(currentLevel); // Start heart spawn timer (every 7-12 seconds, random) heartSpawnTimer = LK.setInterval(function () { if (!isGameOver && !isYouWin) { // 80% chance to spawn a heart if (Math.random() < 0.8) { var heart = new Heart(); heart.x = 200 + Math.random() * (2048 - 400); heart.y = -80; hearts.push(heart); game.addChild(heart); } } }, 7000 + Math.floor(Math.random() * 5000)); } // --- Shooting --- var isShooting = false; var shootInterval = null; function shootPlayerBullet() { if (!canShoot || isGameOver || isYouWin) return; if (player.cooldown > 0) return; var bullet = new PlayerBullet(); bullet.x = player.x; bullet.y = player.y - 100; playerBullets.push(bullet); game.addChild(bullet); player.cooldown = 10; LK.getSound('playerShoot').play(); } function shootBossBullets() { if (!boss) return; var pattern = boss.patternType; var tick = boss.patternTick; var level = currentLevel; // Patterns: 0 = straight, 1 = spread, 2 = aimed if (pattern === 0) { // Straight down, faster at higher levels if (tick % Math.max(40 - level * 2, 12) === 0) { var bullet = new BossBullet(); bullet.x = boss.x; bullet.y = boss.y + 120; bullet.speedY = 18 + level * 1.5; bullet.speedX = 0; bossBullets.push(bullet); game.addChild(bullet); LK.getSound('bossShoot').play(); } } else if (pattern === 1) { // Spread: 3 bullets if (tick % Math.max(60 - level * 2, 18) === 0) { for (var i = -1; i <= 1; i++) { var bullet = new BossBullet(); bullet.x = boss.x; bullet.y = boss.y + 120; bullet.speedY = 16 + level * 1.2; bullet.speedX = i * (6 + level * 0.7); bossBullets.push(bullet); game.addChild(bullet); } LK.getSound('bossShoot').play(); } } else if (pattern === 2) { // Aimed at player if (tick % Math.max(50 - level * 2, 14) === 0) { var dx = player.x - boss.x; var dy = player.y - boss.y; var mag = Math.sqrt(dx * dx + dy * dy); var speed = 20 + level * 1.5; var bullet = new BossBullet(); bullet.x = boss.x; bullet.y = boss.y + 120; bullet.speedX = dx / mag * speed; bullet.speedY = dy / mag * speed; bossBullets.push(bullet); game.addChild(bullet); LK.getSound('bossShoot').play(); } } } // --- Game events --- // Tap anywhere to shoot game.down = function (x, y, obj) { // Store tap position for bullet direction lastTapX = x; lastTapY = y; shootPlayerBullet(); }; // No drag/move for player (player is stationary) // --- Main update loop --- game.update = function () { // Block gameplay until start menu is dismissed if (!gameStarted) return; if (isGameOver || isYouWin) return; // Player cooldown if (player.cooldown > 0) player.cooldown--; // Player invulnerability after hit if (playerInvulnTicks > 0) { playerInvulnTicks--; if (playerInvulnTicks % 6 < 3) { player.alpha = 0.4; } else { player.alpha = 1; } } else { player.alpha = 1; } // Update boss if (boss) boss.update(); // Boss shooting if (boss) shootBossBullets(); // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; b.update(); // Off screen if (b.y < -100) { b.destroy(); playerBullets.splice(i, 1); continue; } // Hit boss if (boss && b.intersects(boss) && boss._vulnerable) { // Player bullet damage increases 20x each level var playerBulletDamage = Math.pow(20, currentLevel - 1); boss.hp -= playerBulletDamage; LK.getSound('bossHit').play(); tween(boss, { scaleX: 1.2, scaleY: 1.2 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(boss, { scaleX: 1, scaleY: 1 }, { duration: 80 }); } }); updateBossHpBar(); b.destroy(); playerBullets.splice(i, 1); LK.setScore(LK.getScore() + 1); scoreText.setText('Score: ' + LK.getScore()); // Boss defeated if (boss.hp <= 0) { boss._vulnerable = false; LK.getSound('bossDefeat').play(); tween(boss, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { boss.destroy(); } }); if (currentLevel < maxLevel) { currentLevel++; // Increase player HP by 30, but not above 100 player.hp = Math.min(player.hp + 30, 100); playerHpText.setText('HP: ' + player.hp + ' / 100'); levelText.setText('Level ' + currentLevel); LK.setTimeout(function () { spawnBoss(currentLevel); }, 900); } else { // Win isYouWin = true; LK.showYouWin(); } } } } // Update boss bullets for (var i = bossBullets.length - 1; i >= 0; i--) { var b = bossBullets[i]; b.update(); // Off screen if (b.y > 2732 + 100 || b.x < -100 || b.x > 2048 + 100) { b.destroy(); bossBullets.splice(i, 1); continue; } // Hit player if (playerInvulnTicks === 0 && b.intersects(player)) { // 39% chance to be invincible (no damage, no invuln, just flash) if (Math.random() < 0.39) { // Flash yellow for invincible LK.effects.flashObject(player, 0xFFFF00, 400); // Optionally, you can add a little effect here } else { LK.getSound('playerHit').play(); tween(player, { scaleX: 1.3, scaleY: 1.3 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(player, { scaleX: 1, scaleY: 1 }, { duration: 80 }); } }); playerInvulnTicks = 60; // Decrease player HP by boss damage player.hp -= getBossDamage(currentLevel); if (player.hp < 0) player.hp = 0; // Update player HP UI playerHpText.setText('HP: ' + player.hp + ' / 100'); // Game over if HP <= 0 if (player.hp <= 0) { LK.effects.flashScreen(0xff0000, 800); isGameOver = true; LK.setTimeout(function () { LK.showGameOver(); }, 900); } } } } // Update hearts for (var i = hearts.length - 1; i >= 0; i--) { var h = hearts[i]; h.update(); // Off screen if (h.y > 2732 + 100) { h.destroy(); hearts.splice(i, 1); continue; } // Collect heart by tap if (h._collectedByTap) { // Already collected by tap, skip continue; } // Collect heart by intersecting with player if (h.intersects(player)) { // Heal player by 50% of max (100), but not above 100 var heal = Math.ceil(100 * 0.5); player.hp = Math.min(player.hp + heal, 100); playerHpText.setText('HP: ' + player.hp + ' / 100'); h.destroy(); hearts.splice(i, 1); // Optional: flash blue for heal LK.effects.flashObject(player, 0x4ec3ff, 400); continue; } } // Make hearts clickable to heal the player game.down = function (x, y, obj) { // Block gameplay tap input until start menu is dismissed if (!gameStarted) return; // Check if tap is on a heart for (var i = hearts.length - 1; i >= 0; i--) { var h = hearts[i]; // Defensive: check if already collected by tap if (h._collectedByTap) continue; // Convert tap to heart local coordinates var local = h.toLocal({ x: x, y: y }); // Check if tap is within heart bounds (ellipse, so use bounding box for simplicity) if (Math.abs(local.x) <= h.width / 2 && Math.abs(local.y) <= h.height / 2) { // Heal player by 50% of max (100), but not above 100 var heal = Math.ceil(100 * 0.5); player.hp = Math.min(player.hp + heal, 100); playerHpText.setText('HP: ' + player.hp + ' / 100'); h._collectedByTap = true; h.destroy(); hearts.splice(i, 1); LK.effects.flashObject(player, 0x4ec3ff, 400); return; // Only allow one heart per tap } } // Store tap position for bullet direction lastTapX = x; lastTapY = y; // Start continuous shooting isShooting = true; shootPlayerBullet(); if (shootInterval !== null) { LK.clearInterval(shootInterval); shootInterval = null; } shootInterval = LK.setInterval(function () { if (isShooting && gameStarted && !isGameOver && !isYouWin) { // Use the last position of the user's finger for bullet direction // If the user is still holding, obj.event.touches[0] gives the current position // But since we don't have access to the event here, we rely on lastTapX/lastTapY shootPlayerBullet(); } }, 60); }; }; // Stop continuous shooting on up game.up = function (x, y, obj) { isShooting = false; if (shootInterval !== null) { LK.clearInterval(shootInterval); shootInterval = null; } }; // Reset game state on game over or win LK.on('gameover', function () { // Clear boss shoot timer if exists if (typeof bossShootTimer !== "undefined" && bossShootTimer !== null) { LK.clearInterval(bossShootTimer); bossShootTimer = null; } // Clear heart spawn timer if exists if (typeof heartSpawnTimer !== "undefined" && heartSpawnTimer !== null) { LK.clearInterval(heartSpawnTimer); heartSpawnTimer = null; } resetGameState(); }); LK.on('youwin', function () { // Clear boss shoot timer if exists if (typeof bossShootTimer !== "undefined" && bossShootTimer !== null) { LK.clearInterval(bossShootTimer); bossShootTimer = null; } // Clear heart spawn timer if exists if (typeof heartSpawnTimer !== "undefined" && heartSpawnTimer !== null) { LK.clearInterval(heartSpawnTimer); heartSpawnTimer = null; } resetGameState(); }); // Track finger position for continuous shooting game.move = function (x, y, obj) { if (isShooting && gameStarted && !isGameOver && !isYouWin) { lastTapX = x; lastTapY = y; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Boss
var Boss = Container.expand(function () {
var self = Container.call(this);
var boss = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHp = 10;
self.hp = 10;
self.shootCooldown = 0;
self.patternTick = 0;
self.patternType = 0;
self.moveDir = 1;
self.moveSpeed = 6;
self.update = function () {
// Boss movement: horizontal oscillation
self.x += self.moveDir * self.moveSpeed;
if (self.x < 320) {
self.x = 320;
self.moveDir = 1;
}
if (self.x > 2048 - 320) {
self.x = 2048 - 320;
self.moveDir = -1;
}
self.patternTick++;
};
return self;
});
// Boss bullet
var BossBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('bossBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedY = 18;
self.speedX = 0;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
// Heart
var Heart = Container.expand(function () {
var self = Container.call(this);
var heart = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedY = 12;
self.update = function () {
self.y += self.speedY;
};
return self;
});
// Player
var Player = Container.expand(function () {
var self = Container.call(this);
var player = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.cooldown = 0;
return self;
});
// Player bullet
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Calculate direction toward last tap
var dx = lastTapX - player.x;
var dy = lastTapY - (player.y - 100);
var mag = Math.sqrt(dx * dx + dy * dy);
// Defensive: if mag is 0, shoot straight up
if (mag === 0) {
dx = 0;
dy = -1;
mag = 1;
}
var speed = 36;
self.speedX = dx / mag * speed;
self.speedY = dy / mag * speed;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181a1b
});
/****
* Game Code
****/
// Game state variables
// Player bullet
// Boss bullet
// Player
// Boss
// Boss HP bar
// Boss HP bar background
// Sound effects
// Music
var currentLevel = 1;
var maxLevel = 30;
var player, boss;
var playerBullets = [];
var bossBullets = [];
var canShoot = true;
var bossHpBar, bossHpBarBg, bossHpText;
var scoreText, levelText;
var isGameOver = false;
var isYouWin = false;
var lastPlayerHit = false;
var lastBossHit = false;
var playerInvulnTicks = 0;
// Hearts
var hearts = [];
var heartSpawnTimer = null;
// Store last tap position for bullet direction
var lastTapX = 2048 / 2;
var lastTapY = 600;
// --- Start Menu Overlay ---
var startMenuOverlay = new Container();
var startMenuBg = LK.getAsset('bossHpBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 1200,
height: 900
});
startMenuBg.alpha = 0.92;
startMenuOverlay.addChild(startMenuBg);
var startTitle = new Text2('BOSS SAVAŞI', {
size: 180,
fill: 0xFFE066
});
startTitle.anchor.set(0.5, 0.5);
startTitle.x = 2048 / 2;
startTitle.y = 2732 / 2 - 220;
startMenuOverlay.addChild(startTitle);
var startDesc = new Text2('10 zorlu bossu yen!\nHer seviyede güçlen!', {
size: 80,
fill: 0xffffff
});
startDesc.anchor.set(0.5, 0.5);
startDesc.x = 2048 / 2;
startDesc.y = 2732 / 2 - 40;
startMenuOverlay.addChild(startDesc);
var startBtn = LK.getAsset('bossHpBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 220,
width: 600,
height: 140
});
startBtn.alpha = 0.98;
startMenuOverlay.addChild(startBtn);
var startBtnText = new Text2('BAŞLA', {
size: 110,
fill: 0xffffff
});
startBtnText.anchor.set(0.5, 0.5);
startBtnText.x = 2048 / 2;
startBtnText.y = 2732 / 2 + 220;
startMenuOverlay.addChild(startBtnText);
game.addChild(startMenuOverlay);
var gameStarted = false;
// Start menu tap handler
startBtn.down = function (x, y, obj) {
if (!gameStarted) {
startMenuOverlay.visible = false;
gameStarted = true;
}
};
// Prevent game from starting until menu is dismissed
// Boss damage per level: first boss 10, +2 per level
function getBossDamage(level) {
return 10 + (level - 1) * 2;
}
// Start music
LK.playMusic('bossMusic');
// --- UI ---
scoreText = new Text2('Score: 0', {
size: 90,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
levelText = new Text2('Level 1', {
size: 70,
fill: 0xFFE066
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 110;
// Boss HP bar
bossHpBarBg = LK.getAsset('bossHpBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 320
});
bossHpBar = LK.getAsset('bossHpBar', {
anchorX: 0,
anchorY: 0.5,
x: 2048 / 2 - 400,
y: 320
});
bossHpText = new Text2('', {
size: 60,
fill: 0xFFFFFF
});
bossHpText.anchor.set(0.5, 0.5);
bossHpText.x = 2048 / 2;
bossHpText.y = 320;
game.addChild(bossHpBarBg);
game.addChild(bossHpBar);
game.addChild(bossHpText);
// --- Player ---
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 320;
player.hp = 100;
game.addChild(player);
// Player HP UI
var playerHpText = new Text2('HP: 100 / 100', {
size: 80,
fill: 0x4ec3ff
});
playerHpText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(playerHpText);
playerHpText.y = -40;
// --- Boss ---
var bossShootTimer = null;
function spawnBoss(level) {
if (boss) {
boss.destroy();
}
boss = new Boss();
// Boss HP increases 50x each level
boss.maxHp = 10 * Math.pow(50, level - 1);
boss.hp = boss.maxHp;
boss.x = 2048 / 2;
boss.y = 600;
boss.moveSpeed = 6 + Math.floor(level / 2);
boss.patternType = (level - 1) % 3;
boss.shootCooldown = 0;
boss.patternTick = 0;
game.addChild(boss);
boss._vulnerable = true;
updateBossHpBar();
// Clear any previous boss shoot timer
if (bossShootTimer !== null) {
LK.clearInterval(bossShootTimer);
bossShootTimer = null;
}
// Set up boss shooting every 2 seconds (2000ms), but fire more bullets as level increases
bossShootTimer = LK.setInterval(function () {
if (!isGameOver && !isYouWin && boss) {
// Number of bullets increases with level (minimum 1, max 10)
var numBullets = Math.min(1 + Math.floor((currentLevel - 1) / 1), 10);
var spread = 120 + 40 * (numBullets - 1);
for (var i = 0; i < numBullets; i++) {
var bullet = new BossBullet();
// Spread bullets horizontally
if (numBullets === 1) {
bullet.x = boss.x;
} else {
bullet.x = boss.x - spread / 2 + spread / (numBullets - 1) * i;
}
bullet.y = boss.y + 120;
bullet.speedY = 18 + currentLevel * 1.5;
bullet.speedX = 0;
bossBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('bossShoot').play();
}
}, 2000);
}
spawnBoss(currentLevel);
// --- Helper functions ---
function updateBossHpBar() {
var hpRatio = boss.hp / boss.maxHp;
bossHpBar.width = 800 * hpRatio;
bossHpText.setText('Boss HP: ' + boss.hp + ' / ' + boss.maxHp);
}
function resetGameState() {
// Remove all bullets
for (var i = 0; i < playerBullets.length; i++) {
playerBullets[i].destroy();
}
for (var i = 0; i < bossBullets.length; i++) {
bossBullets[i].destroy();
}
playerBullets = [];
bossBullets = [];
player.x = 2048 / 2;
player.y = 2732 - 320;
player.hp = 100;
playerHpText.setText('HP: 100 / 100');
playerInvulnTicks = 0;
lastPlayerHit = false;
lastBossHit = false;
isGameOver = false;
isYouWin = false;
canShoot = true;
LK.setScore(0);
scoreText.setText('Score: 0');
currentLevel = 1;
levelText.setText('Level 1');
// Remove all hearts
for (var i = 0; i < hearts.length; i++) {
hearts[i].destroy();
}
hearts = [];
// Clear heart spawn timer if exists
if (typeof heartSpawnTimer !== "undefined" && heartSpawnTimer !== null) {
LK.clearInterval(heartSpawnTimer);
heartSpawnTimer = null;
}
// Clear boss shoot timer if exists
if (typeof bossShootTimer !== "undefined" && bossShootTimer !== null) {
LK.clearInterval(bossShootTimer);
bossShootTimer = null;
}
spawnBoss(currentLevel);
// Start heart spawn timer (every 7-12 seconds, random)
heartSpawnTimer = LK.setInterval(function () {
if (!isGameOver && !isYouWin) {
// 80% chance to spawn a heart
if (Math.random() < 0.8) {
var heart = new Heart();
heart.x = 200 + Math.random() * (2048 - 400);
heart.y = -80;
hearts.push(heart);
game.addChild(heart);
}
}
}, 7000 + Math.floor(Math.random() * 5000));
}
// --- Shooting ---
var isShooting = false;
var shootInterval = null;
function shootPlayerBullet() {
if (!canShoot || isGameOver || isYouWin) return;
if (player.cooldown > 0) return;
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y - 100;
playerBullets.push(bullet);
game.addChild(bullet);
player.cooldown = 10;
LK.getSound('playerShoot').play();
}
function shootBossBullets() {
if (!boss) return;
var pattern = boss.patternType;
var tick = boss.patternTick;
var level = currentLevel;
// Patterns: 0 = straight, 1 = spread, 2 = aimed
if (pattern === 0) {
// Straight down, faster at higher levels
if (tick % Math.max(40 - level * 2, 12) === 0) {
var bullet = new BossBullet();
bullet.x = boss.x;
bullet.y = boss.y + 120;
bullet.speedY = 18 + level * 1.5;
bullet.speedX = 0;
bossBullets.push(bullet);
game.addChild(bullet);
LK.getSound('bossShoot').play();
}
} else if (pattern === 1) {
// Spread: 3 bullets
if (tick % Math.max(60 - level * 2, 18) === 0) {
for (var i = -1; i <= 1; i++) {
var bullet = new BossBullet();
bullet.x = boss.x;
bullet.y = boss.y + 120;
bullet.speedY = 16 + level * 1.2;
bullet.speedX = i * (6 + level * 0.7);
bossBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('bossShoot').play();
}
} else if (pattern === 2) {
// Aimed at player
if (tick % Math.max(50 - level * 2, 14) === 0) {
var dx = player.x - boss.x;
var dy = player.y - boss.y;
var mag = Math.sqrt(dx * dx + dy * dy);
var speed = 20 + level * 1.5;
var bullet = new BossBullet();
bullet.x = boss.x;
bullet.y = boss.y + 120;
bullet.speedX = dx / mag * speed;
bullet.speedY = dy / mag * speed;
bossBullets.push(bullet);
game.addChild(bullet);
LK.getSound('bossShoot').play();
}
}
}
// --- Game events ---
// Tap anywhere to shoot
game.down = function (x, y, obj) {
// Store tap position for bullet direction
lastTapX = x;
lastTapY = y;
shootPlayerBullet();
};
// No drag/move for player (player is stationary)
// --- Main update loop ---
game.update = function () {
// Block gameplay until start menu is dismissed
if (!gameStarted) return;
if (isGameOver || isYouWin) return;
// Player cooldown
if (player.cooldown > 0) player.cooldown--;
// Player invulnerability after hit
if (playerInvulnTicks > 0) {
playerInvulnTicks--;
if (playerInvulnTicks % 6 < 3) {
player.alpha = 0.4;
} else {
player.alpha = 1;
}
} else {
player.alpha = 1;
}
// Update boss
if (boss) boss.update();
// Boss shooting
if (boss) shootBossBullets();
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
// Off screen
if (b.y < -100) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Hit boss
if (boss && b.intersects(boss) && boss._vulnerable) {
// Player bullet damage increases 20x each level
var playerBulletDamage = Math.pow(20, currentLevel - 1);
boss.hp -= playerBulletDamage;
LK.getSound('bossHit').play();
tween(boss, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(boss, {
scaleX: 1,
scaleY: 1
}, {
duration: 80
});
}
});
updateBossHpBar();
b.destroy();
playerBullets.splice(i, 1);
LK.setScore(LK.getScore() + 1);
scoreText.setText('Score: ' + LK.getScore());
// Boss defeated
if (boss.hp <= 0) {
boss._vulnerable = false;
LK.getSound('bossDefeat').play();
tween(boss, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
boss.destroy();
}
});
if (currentLevel < maxLevel) {
currentLevel++;
// Increase player HP by 30, but not above 100
player.hp = Math.min(player.hp + 30, 100);
playerHpText.setText('HP: ' + player.hp + ' / 100');
levelText.setText('Level ' + currentLevel);
LK.setTimeout(function () {
spawnBoss(currentLevel);
}, 900);
} else {
// Win
isYouWin = true;
LK.showYouWin();
}
}
}
}
// Update boss bullets
for (var i = bossBullets.length - 1; i >= 0; i--) {
var b = bossBullets[i];
b.update();
// Off screen
if (b.y > 2732 + 100 || b.x < -100 || b.x > 2048 + 100) {
b.destroy();
bossBullets.splice(i, 1);
continue;
}
// Hit player
if (playerInvulnTicks === 0 && b.intersects(player)) {
// 39% chance to be invincible (no damage, no invuln, just flash)
if (Math.random() < 0.39) {
// Flash yellow for invincible
LK.effects.flashObject(player, 0xFFFF00, 400);
// Optionally, you can add a little effect here
} else {
LK.getSound('playerHit').play();
tween(player, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player, {
scaleX: 1,
scaleY: 1
}, {
duration: 80
});
}
});
playerInvulnTicks = 60;
// Decrease player HP by boss damage
player.hp -= getBossDamage(currentLevel);
if (player.hp < 0) player.hp = 0;
// Update player HP UI
playerHpText.setText('HP: ' + player.hp + ' / 100');
// Game over if HP <= 0
if (player.hp <= 0) {
LK.effects.flashScreen(0xff0000, 800);
isGameOver = true;
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
}
}
}
}
// Update hearts
for (var i = hearts.length - 1; i >= 0; i--) {
var h = hearts[i];
h.update();
// Off screen
if (h.y > 2732 + 100) {
h.destroy();
hearts.splice(i, 1);
continue;
}
// Collect heart by tap
if (h._collectedByTap) {
// Already collected by tap, skip
continue;
}
// Collect heart by intersecting with player
if (h.intersects(player)) {
// Heal player by 50% of max (100), but not above 100
var heal = Math.ceil(100 * 0.5);
player.hp = Math.min(player.hp + heal, 100);
playerHpText.setText('HP: ' + player.hp + ' / 100');
h.destroy();
hearts.splice(i, 1);
// Optional: flash blue for heal
LK.effects.flashObject(player, 0x4ec3ff, 400);
continue;
}
}
// Make hearts clickable to heal the player
game.down = function (x, y, obj) {
// Block gameplay tap input until start menu is dismissed
if (!gameStarted) return;
// Check if tap is on a heart
for (var i = hearts.length - 1; i >= 0; i--) {
var h = hearts[i];
// Defensive: check if already collected by tap
if (h._collectedByTap) continue;
// Convert tap to heart local coordinates
var local = h.toLocal({
x: x,
y: y
});
// Check if tap is within heart bounds (ellipse, so use bounding box for simplicity)
if (Math.abs(local.x) <= h.width / 2 && Math.abs(local.y) <= h.height / 2) {
// Heal player by 50% of max (100), but not above 100
var heal = Math.ceil(100 * 0.5);
player.hp = Math.min(player.hp + heal, 100);
playerHpText.setText('HP: ' + player.hp + ' / 100');
h._collectedByTap = true;
h.destroy();
hearts.splice(i, 1);
LK.effects.flashObject(player, 0x4ec3ff, 400);
return; // Only allow one heart per tap
}
}
// Store tap position for bullet direction
lastTapX = x;
lastTapY = y;
// Start continuous shooting
isShooting = true;
shootPlayerBullet();
if (shootInterval !== null) {
LK.clearInterval(shootInterval);
shootInterval = null;
}
shootInterval = LK.setInterval(function () {
if (isShooting && gameStarted && !isGameOver && !isYouWin) {
// Use the last position of the user's finger for bullet direction
// If the user is still holding, obj.event.touches[0] gives the current position
// But since we don't have access to the event here, we rely on lastTapX/lastTapY
shootPlayerBullet();
}
}, 60);
};
};
// Stop continuous shooting on up
game.up = function (x, y, obj) {
isShooting = false;
if (shootInterval !== null) {
LK.clearInterval(shootInterval);
shootInterval = null;
}
};
// Reset game state on game over or win
LK.on('gameover', function () {
// Clear boss shoot timer if exists
if (typeof bossShootTimer !== "undefined" && bossShootTimer !== null) {
LK.clearInterval(bossShootTimer);
bossShootTimer = null;
}
// Clear heart spawn timer if exists
if (typeof heartSpawnTimer !== "undefined" && heartSpawnTimer !== null) {
LK.clearInterval(heartSpawnTimer);
heartSpawnTimer = null;
}
resetGameState();
});
LK.on('youwin', function () {
// Clear boss shoot timer if exists
if (typeof bossShootTimer !== "undefined" && bossShootTimer !== null) {
LK.clearInterval(bossShootTimer);
bossShootTimer = null;
}
// Clear heart spawn timer if exists
if (typeof heartSpawnTimer !== "undefined" && heartSpawnTimer !== null) {
LK.clearInterval(heartSpawnTimer);
heartSpawnTimer = null;
}
resetGameState();
});
// Track finger position for continuous shooting
game.move = function (x, y, obj) {
if (isShooting && gameStarted && !isGameOver && !isYouWin) {
lastTapX = x;
lastTapY = y;
}
};
Alevli bir iskelet boss zırhı olsun ve alevli bir silahı olsun. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Bir büyücü ama erkek ve barışçıl bir savaşçı ama artık intikam arıyor. In-Game asset. 2d. High contrast. No shadows
Fire bullet. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Blue fire. In-Game asset. 2d. High contrast. No shadows