/****
* 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