/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.radius = bulletSprite.width * 0.5; self.speed = 32; self.dx = 0; self.dy = 0; self.update = function () { self.x += self.dx * self.speed; self.y += self.dy * self.speed; // Rotate bullet sprite to face its movement direction if (self.dx !== 0 || self.dy !== 0) { bulletSprite.rotation = Math.atan2(self.dy, self.dx); } }; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); var enemySprite = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.radius = enemySprite.width * 0.5; self.speed = 2 + Math.random() * 1.2; self.hp = 2; self.target = null; // set to player self.update = function () { if (!self.target) return; var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; self.hit = function () { self.hp--; LK.getSound('enemyhit').play(); LK.effects.flashObject(self, 0xffffff, 120); if (self.hp <= 0) { self.destroyed = true; } }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var playerSprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.radius = playerSprite.width * 0.5; self.speed = 18; self.hp = 5; self.invuln = 0; // frames of invulnerability after hit // For upgrades self.fireRate = 0; // frames between shots (0 saniye, instant fire) self.bulletSpeed = 32; self.bulletSpread = 0; // degrees self.lastShot = 0; self.update = function () { if (self.invuln > 0) { self.invuln--; playerSprite.alpha = 0.5 + 0.5 * Math.sin(LK.ticks * 0.4); } else { playerSprite.alpha = 1; } }; // Called when player is hit self.hit = function () { if (self.invuln > 0) return; self.hp--; self.invuln = 60; LK.effects.flashObject(self, 0xff0000, 400); LK.getSound('playerhit').play(); updateHpText(); if (self.hp <= 0) { LK.effects.flashScreen(0xff0000, 1200); LK.showGameOver(); } }; // Called when player picks up a powerup self.applyPowerup = function (type) { if (type === 'firerate') { self.fireRate = Math.max(8, self.fireRate - 4); } else if (type === 'spread') { self.bulletSpread = Math.min(30, self.bulletSpread + 10); } else if (type === 'hp') { self.hp = self.hp + 1; updateHpText(); } else if (type === 'bulletspeed') { self.bulletSpeed = Math.min(48, self.bulletSpeed + 4); } }; return self; }); // Powerup class var Powerup = Container.expand(function () { var self = Container.call(this); var powerupSprite = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.radius = powerupSprite.width * 0.5; self.type = 'firerate'; // default, can be changed self.spawnTick = LK.ticks; // Track when spawned self.update = function () { // Powerup disappears after 5 seconds (300 frames) if not collected if (LK.ticks - self.spawnTick >= 300) { self.destroy(); // Remove from powerups array in main update loop } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x7c3f1c }); /**** * Game Code ****/ // Play button and cover logic // Add background var coverBg = LK.getAsset('Playbg', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(coverBg); // Create Play button as a container with Playbg as background var playBtn = new Container(); var playBgSprite = LK.getAsset('Playbg', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Center Playbg in playBtn (container is at 0,0, so this centers the image) playBgSprite.x = 0; playBgSprite.y = 0; playBtn.addChild(playBgSprite); var playText = new Text2('PLAY', { size: 200, fill: "#fff", font: "Impact, Arial Black, Tahoma" }); playText.anchor.set(0.5, 0.5); playText.x = 0; playText.y = 0; playBtn.addChild(playText); playBtn.x = 2048 / 2; playBtn.y = 2732 / 2; // Add a white border to the play button background var border = new Container(); var borderSize = playBgSprite.width + 24; var borderHeight = playBgSprite.height + 24; var borderRect = LK.getAsset('Playbg', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, width: borderSize, height: borderHeight, tint: 0xffffff }); borderRect.alpha = 1; border.addChild(borderRect); border.x = 0; border.y = 0; playBtn.addChildAt(border, 0); playBtn.interactive = true; playBtn.buttonMode = true; game.addChild(playBtn); // Hide all gameplay and GUI until play button is pressed var gameStarted = false; // Ensure play text is visible until pressed playText.visible = true; // GUI var timerTxt = new Text2('20:00', { size: 90, fill: "#fff" }); timerTxt.anchor.set(1, 0); LK.gui.top.addChild(timerTxt); // Position timerTxt at right of the top GUI, leaving a margin timerTxt.x = LK.gui.top.width - 40; timerTxt.y = 0; var hpTxt = new Text2('HP: 5', { size: 90, fill: "#fff" }); hpTxt.anchor.set(1, 0); LK.gui.topRight.addChild(hpTxt); // Hide GUI elements until game starts timerTxt.visible = false; hpTxt.visible = false; // Play button event playBtn.down = function (x, y, obj) { // Remove cover and play button coverBg.visible = false; playBtn.visible = false; playText.visible = false; gameStarted = true; // Show GUI timerTxt.visible = true; hpTxt.visible = true; // Reposition timer text in case of GUI resize timerTxt.x = LK.gui.top.width - 40; timerTxt.y = 0; // Add main background var marsbg = LK.getAsset('marsbg', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(marsbg); // Spawn player in center player = new Player(); player.x = 2048 / 2; player.y = 2732 / 2; game.addChild(player); // Start music LK.playMusic('marsmusic'); // Initial GUI update updateTimerText(); updateHpText(); // Oyun başında ilk düşmanı doğur spawnEnemy(); lastEnemySpawn = LK.ticks; }; // Game variables var player; var enemies = []; var bullets = []; var powerups = []; var dragNode = null; var lastMoveX = 0, lastMoveY = 0; var score = 0; var timeLeft = 20 * 60; // 20 minutes in seconds, but we use frames (20*60*60) var timerFrames = 20 * 60 * 60; // 20 minutes * 60 seconds * 60 frames var lastEnemySpawn = 0; var enemySpawnInterval = 120; // 2 saniye * 60 fps = 120 frame (daha hızlı başlasın) var lastPowerupSpawn = 0; var powerupInterval = 600; // every 10 seconds (10*60) // GUI var timerTxt = new Text2('20:00', { size: 90, fill: "#fff" }); timerTxt.anchor.set(1, 0); LK.gui.top.addChild(timerTxt); // Position timerTxt at right of the top GUI, leaving a margin timerTxt.x = LK.gui.top.width - 40; timerTxt.y = 0; var hpTxt = new Text2('HP: 5', { size: 90, fill: "#fff" }); hpTxt.anchor.set(1, 0); LK.gui.topRight.addChild(hpTxt); // Score text removed; only timer is shown function updateTimerText() { var seconds = Math.floor(timerFrames / 60); var min = Math.floor(seconds / 60); var sec = seconds % 60; var t = (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec; timerTxt.setText(t); } function updateHpText() { if (player) hpTxt.setText('HP: ' + player.hp); } // (Player, music, and first enemy spawn are now handled in playBtn.down) // Move handler (drag to move player) function handleMove(x, y, obj) { if (!gameStarted) return; if (dragNode) { // Clamp to game area var px = Math.max(player.radius, Math.min(2048 - player.radius, x)); var py = Math.max(player.radius, Math.min(2732 - player.radius, y)); dragNode.x = px; dragNode.y = py; lastMoveX = px; lastMoveY = py; // Ateş yönünü güncelle (basılı tutarken) if (isFiring) { var dx = x - player.x; var dy = y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { fireDirection.dx = dx / dist; fireDirection.dy = dy / dist; } } } } game.move = handleMove; var isFiring = false; var fireDirection = { dx: 0, dy: -1 }; // Varsayılan yukarı game.down = function (x, y, obj) { if (!gameStarted) return; // Sadece karakterin üstüne basılı tutulduğunda karakteri hareket ettir var dx = x - player.x; var dy = y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); // Eğer dokunulan nokta karakterin üstündeyse (yarıçap dahil) if (dist <= player.radius) { dragNode = player; handleMove(x, y, obj); isFiring = false; // karakteri hareket ettirirken ateş etme } else if (x > 100 || y > 100) { // Karakterin dışında bir yere basıldıysa ateş et isFiring = false; // Sürekli ateş etme yok, sadece tıklamada ateş et // Ateş yönünü belirle if (dist > 0) { fireDirection.dx = dx / dist; fireDirection.dy = dy / dist; } else { fireDirection.dx = 0; fireDirection.dy = -1; } // Hemen ateş et fireBullets(); } }; game.up = function (x, y, obj) { if (!gameStarted) return; dragNode = null; isFiring = false; }; // Fire bullets when called (manual fire) function fireBullets() { if (LK.ticks - player.lastShot < player.fireRate) return; player.lastShot = LK.ticks; var spread = player.bulletSpread; var angles = [0]; if (spread > 0) { angles = [-spread, 0, spread]; } for (var i = 0; i < angles.length; i++) { var baseAngle = Math.atan2(fireDirection.dy, fireDirection.dx); var angle = baseAngle + angles[i] * Math.PI / 180; var b = new Bullet(); b.x = player.x; b.y = player.y; b.speed = player.bulletSpeed; b.dx = Math.cos(angle); b.dy = Math.sin(angle); bullets.push(b); game.addChild(b); LK.getSound('bullet_hit_39853').play(); } LK.getSound('shoot').play(); } // Spawn enemies at random edge function spawnEnemy() { var e = new Enemy(); // Pick random edge var edge = Math.floor(Math.random() * 4); var ex, ey; if (edge === 0) { // top ex = Math.random() * 2048; ey = -e.radius - 10; } else if (edge === 1) { // right ex = 2048 + e.radius + 10; ey = Math.random() * 2732; } else if (edge === 2) { // bottom ex = Math.random() * 2048; ey = 2732 + e.radius + 10; } else { // left ex = -e.radius - 10; ey = Math.random() * 2732; } e.x = ex; e.y = ey; e.target = player; enemies.push(e); game.addChild(e); } // Spawn powerup at random location function spawnPowerup() { var p = new Powerup(); p.type = 'hp'; // Sadece hp powerup p.x = 200 + Math.random() * (2048 - 400); p.y = 200 + Math.random() * (2732 - 400); powerups.push(p); game.addChild(p); } // Main update loop game.update = function () { if (!gameStarted) return; // Timer if (timerFrames > 0) { timerFrames--; // Score is now the number of seconds survived score = Math.floor((20 * 60 * 60 - timerFrames) / 60); updateTimerText(); } if (timerFrames === 0) { LK.effects.flashScreen(0x00ff00, 1200); LK.showYouWin(); return; } // Player update player.update(); // Removed auto-fire logic; bullets only fire on tap // Bullets update for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); // Remove if off screen if (b.x < -60 || b.x > 2048 + 60 || b.y < -60 || b.y > 2732 + 60) { b.destroy(); bullets.splice(i, 1); continue; } // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; var dx = b.x - e.x; var dy = b.y - e.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < b.radius + e.radius) { e.hp = 1; // 1 mermi 1 düşman öldürsün e.hit(); if (e.hp <= 0) { e.destroy(); enemies.splice(j, 1); // No score increment on enemy kill; score is now survival time // updateScoreText(); } b.destroy(); bullets.splice(i, 1); break; } } } // Enemies update for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Check collision with player var dx = e.x - player.x; var dy = e.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < e.radius + player.radius) { player.hit(); e.destroy(); enemies.splice(i, 1); continue; } // Remove if off screen (shouldn't happen, but just in case) if (e.x < -200 || e.x > 2048 + 200 || e.y < -200 || e.y > 2732 + 200) { e.destroy(); enemies.splice(i, 1); } } // Powerups update for (var i = powerups.length - 1; i >= 0; i--) { var p = powerups[i]; p.update && p.update(); // Call update for timer logic // Check collision with player var dx = p.x - player.x; var dy = p.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < p.radius + player.radius) { player.applyPowerup(p.type); LK.getSound('powerup').play(); p.destroy(); powerups.splice(i, 1); continue; } // Check collision with bullets (kalbe ateş edildiğinde HP artsın) for (var j = bullets.length - 1; j >= 0; j--) { var b = bullets[j]; var bdx = p.x - b.x; var bdy = p.y - b.y; var bdist = Math.sqrt(bdx * bdx + bdy * bdy); if (bdist < p.radius + b.radius) { // Bullet hits powerup (kalp) player.hp = player.hp + 1; updateHpText(); LK.getSound('powerup').play(); p.destroy(); powerups.splice(i, 1); b.destroy(); bullets.splice(j, 1); break; } } // Remove if destroyed by timer if (p._destroyed) { powerups.splice(i, 1); } } // Enemy spawn logic (increase spawn rate over time) // Düşman sadece 5 saniyede bir tane doğsun ve sayısı 10 saniyede bir artsın if (typeof enemyPerSpawn === "undefined") { enemyPerSpawn = 1; lastEnemyPerSpawnIncrease = LK.ticks; } if (LK.ticks - lastEnemyPerSpawnIncrease >= 900) { // 15 saniye = 15*60 = 900 frame enemyPerSpawn += 1; lastEnemyPerSpawnIncrease += 900; // Artışı tam 15 saniyede bir yap } // Her 5 saniyede bir (300 frame) sadece enemyPerSpawn kadar düşman doğur if (LK.ticks - lastEnemySpawn >= 300) { for (var i = 0; i < enemyPerSpawn; i++) { spawnEnemy(); } lastEnemySpawn = LK.ticks; } // Powerup spawn logic if (LK.ticks - lastPowerupSpawn > powerupInterval) { spawnPowerup(); lastPowerupSpawn = LK.ticks; } }; // (Initial GUI update and enemy spawn are now handled in playBtn.down)
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletSprite.width * 0.5;
self.speed = 32;
self.dx = 0;
self.dy = 0;
self.update = function () {
self.x += self.dx * self.speed;
self.y += self.dy * self.speed;
// Rotate bullet sprite to face its movement direction
if (self.dx !== 0 || self.dy !== 0) {
bulletSprite.rotation = Math.atan2(self.dy, self.dx);
}
};
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = enemySprite.width * 0.5;
self.speed = 2 + Math.random() * 1.2;
self.hp = 2;
self.target = null; // set to player
self.update = function () {
if (!self.target) return;
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
};
self.hit = function () {
self.hp--;
LK.getSound('enemyhit').play();
LK.effects.flashObject(self, 0xffffff, 120);
if (self.hp <= 0) {
self.destroyed = true;
}
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = playerSprite.width * 0.5;
self.speed = 18;
self.hp = 5;
self.invuln = 0; // frames of invulnerability after hit
// For upgrades
self.fireRate = 0; // frames between shots (0 saniye, instant fire)
self.bulletSpeed = 32;
self.bulletSpread = 0; // degrees
self.lastShot = 0;
self.update = function () {
if (self.invuln > 0) {
self.invuln--;
playerSprite.alpha = 0.5 + 0.5 * Math.sin(LK.ticks * 0.4);
} else {
playerSprite.alpha = 1;
}
};
// Called when player is hit
self.hit = function () {
if (self.invuln > 0) return;
self.hp--;
self.invuln = 60;
LK.effects.flashObject(self, 0xff0000, 400);
LK.getSound('playerhit').play();
updateHpText();
if (self.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1200);
LK.showGameOver();
}
};
// Called when player picks up a powerup
self.applyPowerup = function (type) {
if (type === 'firerate') {
self.fireRate = Math.max(8, self.fireRate - 4);
} else if (type === 'spread') {
self.bulletSpread = Math.min(30, self.bulletSpread + 10);
} else if (type === 'hp') {
self.hp = self.hp + 1;
updateHpText();
} else if (type === 'bulletspeed') {
self.bulletSpeed = Math.min(48, self.bulletSpeed + 4);
}
};
return self;
});
// Powerup class
var Powerup = Container.expand(function () {
var self = Container.call(this);
var powerupSprite = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = powerupSprite.width * 0.5;
self.type = 'firerate'; // default, can be changed
self.spawnTick = LK.ticks; // Track when spawned
self.update = function () {
// Powerup disappears after 5 seconds (300 frames) if not collected
if (LK.ticks - self.spawnTick >= 300) {
self.destroy();
// Remove from powerups array in main update loop
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x7c3f1c
});
/****
* Game Code
****/
// Play button and cover logic
// Add background
var coverBg = LK.getAsset('Playbg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(coverBg);
// Create Play button as a container with Playbg as background
var playBtn = new Container();
var playBgSprite = LK.getAsset('Playbg', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
// Center Playbg in playBtn (container is at 0,0, so this centers the image)
playBgSprite.x = 0;
playBgSprite.y = 0;
playBtn.addChild(playBgSprite);
var playText = new Text2('PLAY', {
size: 200,
fill: "#fff",
font: "Impact, Arial Black, Tahoma"
});
playText.anchor.set(0.5, 0.5);
playText.x = 0;
playText.y = 0;
playBtn.addChild(playText);
playBtn.x = 2048 / 2;
playBtn.y = 2732 / 2;
// Add a white border to the play button background
var border = new Container();
var borderSize = playBgSprite.width + 24;
var borderHeight = playBgSprite.height + 24;
var borderRect = LK.getAsset('Playbg', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
width: borderSize,
height: borderHeight,
tint: 0xffffff
});
borderRect.alpha = 1;
border.addChild(borderRect);
border.x = 0;
border.y = 0;
playBtn.addChildAt(border, 0);
playBtn.interactive = true;
playBtn.buttonMode = true;
game.addChild(playBtn);
// Hide all gameplay and GUI until play button is pressed
var gameStarted = false;
// Ensure play text is visible until pressed
playText.visible = true;
// GUI
var timerTxt = new Text2('20:00', {
size: 90,
fill: "#fff"
});
timerTxt.anchor.set(1, 0);
LK.gui.top.addChild(timerTxt);
// Position timerTxt at right of the top GUI, leaving a margin
timerTxt.x = LK.gui.top.width - 40;
timerTxt.y = 0;
var hpTxt = new Text2('HP: 5', {
size: 90,
fill: "#fff"
});
hpTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(hpTxt);
// Hide GUI elements until game starts
timerTxt.visible = false;
hpTxt.visible = false;
// Play button event
playBtn.down = function (x, y, obj) {
// Remove cover and play button
coverBg.visible = false;
playBtn.visible = false;
playText.visible = false;
gameStarted = true;
// Show GUI
timerTxt.visible = true;
hpTxt.visible = true;
// Reposition timer text in case of GUI resize
timerTxt.x = LK.gui.top.width - 40;
timerTxt.y = 0;
// Add main background
var marsbg = LK.getAsset('marsbg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(marsbg);
// Spawn player in center
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// Start music
LK.playMusic('marsmusic');
// Initial GUI update
updateTimerText();
updateHpText();
// Oyun başında ilk düşmanı doğur
spawnEnemy();
lastEnemySpawn = LK.ticks;
};
// Game variables
var player;
var enemies = [];
var bullets = [];
var powerups = [];
var dragNode = null;
var lastMoveX = 0,
lastMoveY = 0;
var score = 0;
var timeLeft = 20 * 60; // 20 minutes in seconds, but we use frames (20*60*60)
var timerFrames = 20 * 60 * 60; // 20 minutes * 60 seconds * 60 frames
var lastEnemySpawn = 0;
var enemySpawnInterval = 120; // 2 saniye * 60 fps = 120 frame (daha hızlı başlasın)
var lastPowerupSpawn = 0;
var powerupInterval = 600; // every 10 seconds (10*60)
// GUI
var timerTxt = new Text2('20:00', {
size: 90,
fill: "#fff"
});
timerTxt.anchor.set(1, 0);
LK.gui.top.addChild(timerTxt);
// Position timerTxt at right of the top GUI, leaving a margin
timerTxt.x = LK.gui.top.width - 40;
timerTxt.y = 0;
var hpTxt = new Text2('HP: 5', {
size: 90,
fill: "#fff"
});
hpTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(hpTxt);
// Score text removed; only timer is shown
function updateTimerText() {
var seconds = Math.floor(timerFrames / 60);
var min = Math.floor(seconds / 60);
var sec = seconds % 60;
var t = (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec;
timerTxt.setText(t);
}
function updateHpText() {
if (player) hpTxt.setText('HP: ' + player.hp);
}
// (Player, music, and first enemy spawn are now handled in playBtn.down)
// Move handler (drag to move player)
function handleMove(x, y, obj) {
if (!gameStarted) return;
if (dragNode) {
// Clamp to game area
var px = Math.max(player.radius, Math.min(2048 - player.radius, x));
var py = Math.max(player.radius, Math.min(2732 - player.radius, y));
dragNode.x = px;
dragNode.y = py;
lastMoveX = px;
lastMoveY = py;
// Ateş yönünü güncelle (basılı tutarken)
if (isFiring) {
var dx = x - player.x;
var dy = y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
fireDirection.dx = dx / dist;
fireDirection.dy = dy / dist;
}
}
}
}
game.move = handleMove;
var isFiring = false;
var fireDirection = {
dx: 0,
dy: -1
}; // Varsayılan yukarı
game.down = function (x, y, obj) {
if (!gameStarted) return;
// Sadece karakterin üstüne basılı tutulduğunda karakteri hareket ettir
var dx = x - player.x;
var dy = y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Eğer dokunulan nokta karakterin üstündeyse (yarıçap dahil)
if (dist <= player.radius) {
dragNode = player;
handleMove(x, y, obj);
isFiring = false; // karakteri hareket ettirirken ateş etme
} else if (x > 100 || y > 100) {
// Karakterin dışında bir yere basıldıysa ateş et
isFiring = false; // Sürekli ateş etme yok, sadece tıklamada ateş et
// Ateş yönünü belirle
if (dist > 0) {
fireDirection.dx = dx / dist;
fireDirection.dy = dy / dist;
} else {
fireDirection.dx = 0;
fireDirection.dy = -1;
}
// Hemen ateş et
fireBullets();
}
};
game.up = function (x, y, obj) {
if (!gameStarted) return;
dragNode = null;
isFiring = false;
};
// Fire bullets when called (manual fire)
function fireBullets() {
if (LK.ticks - player.lastShot < player.fireRate) return;
player.lastShot = LK.ticks;
var spread = player.bulletSpread;
var angles = [0];
if (spread > 0) {
angles = [-spread, 0, spread];
}
for (var i = 0; i < angles.length; i++) {
var baseAngle = Math.atan2(fireDirection.dy, fireDirection.dx);
var angle = baseAngle + angles[i] * Math.PI / 180;
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.speed = player.bulletSpeed;
b.dx = Math.cos(angle);
b.dy = Math.sin(angle);
bullets.push(b);
game.addChild(b);
LK.getSound('bullet_hit_39853').play();
}
LK.getSound('shoot').play();
}
// Spawn enemies at random edge
function spawnEnemy() {
var e = new Enemy();
// Pick random edge
var edge = Math.floor(Math.random() * 4);
var ex, ey;
if (edge === 0) {
// top
ex = Math.random() * 2048;
ey = -e.radius - 10;
} else if (edge === 1) {
// right
ex = 2048 + e.radius + 10;
ey = Math.random() * 2732;
} else if (edge === 2) {
// bottom
ex = Math.random() * 2048;
ey = 2732 + e.radius + 10;
} else {
// left
ex = -e.radius - 10;
ey = Math.random() * 2732;
}
e.x = ex;
e.y = ey;
e.target = player;
enemies.push(e);
game.addChild(e);
}
// Spawn powerup at random location
function spawnPowerup() {
var p = new Powerup();
p.type = 'hp'; // Sadece hp powerup
p.x = 200 + Math.random() * (2048 - 400);
p.y = 200 + Math.random() * (2732 - 400);
powerups.push(p);
game.addChild(p);
}
// Main update loop
game.update = function () {
if (!gameStarted) return;
// Timer
if (timerFrames > 0) {
timerFrames--;
// Score is now the number of seconds survived
score = Math.floor((20 * 60 * 60 - timerFrames) / 60);
updateTimerText();
}
if (timerFrames === 0) {
LK.effects.flashScreen(0x00ff00, 1200);
LK.showYouWin();
return;
}
// Player update
player.update();
// Removed auto-fire logic; bullets only fire on tap
// Bullets update
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Remove if off screen
if (b.x < -60 || b.x > 2048 + 60 || b.y < -60 || b.y > 2732 + 60) {
b.destroy();
bullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
var dx = b.x - e.x;
var dy = b.y - e.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < b.radius + e.radius) {
e.hp = 1; // 1 mermi 1 düşman öldürsün
e.hit();
if (e.hp <= 0) {
e.destroy();
enemies.splice(j, 1);
// No score increment on enemy kill; score is now survival time
// updateScoreText();
}
b.destroy();
bullets.splice(i, 1);
break;
}
}
}
// Enemies update
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Check collision with player
var dx = e.x - player.x;
var dy = e.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < e.radius + player.radius) {
player.hit();
e.destroy();
enemies.splice(i, 1);
continue;
}
// Remove if off screen (shouldn't happen, but just in case)
if (e.x < -200 || e.x > 2048 + 200 || e.y < -200 || e.y > 2732 + 200) {
e.destroy();
enemies.splice(i, 1);
}
}
// Powerups update
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update && p.update(); // Call update for timer logic
// Check collision with player
var dx = p.x - player.x;
var dy = p.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < p.radius + player.radius) {
player.applyPowerup(p.type);
LK.getSound('powerup').play();
p.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with bullets (kalbe ateş edildiğinde HP artsın)
for (var j = bullets.length - 1; j >= 0; j--) {
var b = bullets[j];
var bdx = p.x - b.x;
var bdy = p.y - b.y;
var bdist = Math.sqrt(bdx * bdx + bdy * bdy);
if (bdist < p.radius + b.radius) {
// Bullet hits powerup (kalp)
player.hp = player.hp + 1;
updateHpText();
LK.getSound('powerup').play();
p.destroy();
powerups.splice(i, 1);
b.destroy();
bullets.splice(j, 1);
break;
}
}
// Remove if destroyed by timer
if (p._destroyed) {
powerups.splice(i, 1);
}
}
// Enemy spawn logic (increase spawn rate over time)
// Düşman sadece 5 saniyede bir tane doğsun ve sayısı 10 saniyede bir artsın
if (typeof enemyPerSpawn === "undefined") {
enemyPerSpawn = 1;
lastEnemyPerSpawnIncrease = LK.ticks;
}
if (LK.ticks - lastEnemyPerSpawnIncrease >= 900) {
// 15 saniye = 15*60 = 900 frame
enemyPerSpawn += 1;
lastEnemyPerSpawnIncrease += 900; // Artışı tam 15 saniyede bir yap
}
// Her 5 saniyede bir (300 frame) sadece enemyPerSpawn kadar düşman doğur
if (LK.ticks - lastEnemySpawn >= 300) {
for (var i = 0; i < enemyPerSpawn; i++) {
spawnEnemy();
}
lastEnemySpawn = LK.ticks;
}
// Powerup spawn logic
if (LK.ticks - lastPowerupSpawn > powerupInterval) {
spawnPowerup();
lastPowerupSpawn = LK.ticks;
}
};
// (Initial GUI update and enemy spawn are now handled in playBtn.down)
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Mars: 20 Minutes Till Dawn" and with the description "A 2D top-down shooter on Mars where you survive waves of alien enemies for 20 minutes, collecting power-ups and upgrading weapons to last as long as possible.". No text on banner!
Sarı mermi olsun. In-Game asset. 2d. High contrast. No shadows
Pixel astronot olsun. Elbisesi turıncu olsun. In-Game asset. 2d. High contrast. No shadows
Pixel uzaylı olsun. In-Game asset. 2d. High contrast. No shadows
Pixel Mars zemini olsun. Top down olsun. In-Game asset. 2d. High contrast. No shadows
Pixel kalp. In-Game asset. 2d. High contrast. No shadows
pixel ufo. In-Game asset. 2d. High contrast. No shadows