User prompt
Let them come from above, not from below
User prompt
If there is still no enemy coming from the opposite direction, create a mob called enemy and let them come from the opposite direction.
User prompt
The enemy is not coming from the enemy, let the enemy come from the opposite side
User prompt
Write "cehpane" instead of ammo
User prompt
Let the enemies come from the opposite direction and let's say you have 20 ammunition and 18 enemies come
Code edit (1 edits merged)
Please save this source code
User prompt
Ball Shooter Arena
Initial prompt
bir top olsun ardından o top ile düşmanları vuramlım vurdukça puan kazanalım
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
language: "Turkish"
});
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.speed = 12;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = 1 + Math.random() * 2;
self.directionX = (Math.random() - 0.5) * 2;
self.directionY = (Math.random() - 0.5) * 2;
self.update = function () {
self.x += self.directionX * self.moveSpeed;
self.y += self.directionY * self.moveSpeed;
// Keep enemies moving downward (toward player)
if (self.directionY < 0) {
self.directionY = 1;
}
// Bounce off side walls only
if (self.x <= 30 || self.x >= 2018) {
self.directionX *= -1;
}
// Remove enemies that go off bottom of screen
if (self.y > 2782) {
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var MenuButton = Container.expand(function (text, color) {
var self = Container.call(this);
var buttonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(text, {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.setText = function (newText) {
buttonText.setText(newText);
};
self.down = function (x, y, obj) {
// Button press feedback
self.scaleX = 0.9;
self.scaleY = 0.9;
};
self.up = function (x, y, obj) {
// Reset scale
self.scaleX = 1;
self.scaleY = 1;
};
return self;
});
var PirateShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('pirateShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = shipSpeedPerLevel[0]; // Start with level 1 speed
self.enemySpawnTimer = 0;
self.enemySpawnRate = enemySpawnRatePerLevel[0]; // Start with level 1 spawn rate
self.maxEnemiesFromShip = enemiesPerLevel[0]; // Start with level 1 enemy count
self.enemiesSpawnedFromShip = 0;
self.update = function () {
// Move ship horizontally across top of screen
self.x += self.moveSpeed;
// Reverse direction when hitting screen edges
if (self.x <= 100 || self.x >= 1948) {
self.moveSpeed *= -1;
}
// Spawn enemies from ship
self.enemySpawnTimer++;
if (self.enemySpawnTimer >= self.enemySpawnRate && self.enemiesSpawnedFromShip < self.maxEnemiesFromShip) {
spawnEnemyFromShip(self.x, self.y + 80);
self.enemySpawnTimer = 0;
self.enemiesSpawnedFromShip++;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.isReady = true;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Language system
var currentLanguage = storage.language || 'Turkish';
var translations = {
English: {
score: 'Score: ',
ammo: 'Ammo: ',
level: 'Level: ',
ready: 'READY',
shooting: 'SHOOTING',
settings: 'Settings',
language: 'Language',
close: 'Close',
menu: 'Menu'
},
Turkish: {
score: 'Puan: ',
ammo: 'Cephane: ',
level: 'Seviye: ',
ready: 'HAZIR',
shooting: 'ATIŞ',
settings: 'Ayarlar',
language: 'Dil',
close: 'Kapat',
menu: 'Menü'
}
};
function getText(key) {
return translations[currentLanguage][key] || key;
}
// Menu system variables
var menuOpen = false;
var menuContainer = null;
var settingsMenu = null;
var player = game.addChild(new Player());
player.x = 1024;
player.y = 2500;
var bullets = [];
var enemies = [];
var enemySpawnTimer = 0;
var difficultyTimer = 0;
var baseSpawnRate = 180; // frames between spawns
var currentSpawnRate = baseSpawnRate;
// Level system variables
var currentLevel = 1;
var maxLevel = 5;
var enemiesKilled = 0;
var enemiesPerLevel = [10, 15, 20, 25, 30]; // Enemies to kill per level
var shipSpeedPerLevel = [2, 2.5, 3, 3.5, 4]; // Ship speed per level
var enemySpawnRatePerLevel = [120, 100, 80, 60, 40]; // Spawn rate per level (lower = faster)
var maxEnemiesPerLevel = [8, 12, 16, 20, 25]; // Max enemies on screen per level
var ammoPerLevel = [20, 25, 30, 35, 40]; // Ammo given per level
var maxAmmo = ammoPerLevel[0]; // Start with level 1 ammo
var currentAmmo = maxAmmo;
var maxEnemies = maxEnemiesPerLevel[0]; // Start with level 1 max enemies
var enemiesSpawned = 0;
// Add pirate ship
var pirateShip = game.addChild(new PirateShip());
pirateShip.x = 200;
pirateShip.y = 150;
// UI Elements
var scoreTxt = new Text2(getText('score') + '0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var readyIndicator = new Text2(getText('ready'), {
size: 60,
fill: 0x00FF00
});
readyIndicator.anchor.set(0.5, 0.5);
LK.gui.center.addChild(readyIndicator);
var ammoTxt = new Text2(getText('ammo') + '20', {
size: 60,
fill: 0xFFFFFF
});
ammoTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(ammoTxt);
var levelTxt = new Text2(getText('level') + '1', {
size: 60,
fill: 0xFFD700
});
levelTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelTxt);
function updateScore() {
scoreTxt.setText(getText('score') + LK.getScore());
}
function updateAmmo() {
ammoTxt.setText(getText('ammo') + currentAmmo);
}
function updateLevel() {
levelTxt.setText(getText('level') + currentLevel);
}
function updateAllText() {
updateScore();
updateAmmo();
updateLevel();
if (player.isReady) {
readyIndicator.setText(getText('ready'));
} else {
readyIndicator.setText(getText('shooting'));
}
}
function createSettingsMenu() {
if (settingsMenu) return;
settingsMenu = new Container();
// Background
var menuBg = settingsMenu.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
// Title
var titleText = new Text2(getText('settings'), {
size: 70,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -200;
settingsMenu.addChild(titleText);
// Language button
var languageButton = settingsMenu.addChild(new MenuButton(getText('language') + ': ' + currentLanguage));
languageButton.y = -50;
languageButton.down = function (x, y, obj) {
MenuButton.prototype.down.call(this, x, y, obj);
// Toggle language
currentLanguage = currentLanguage === 'English' ? 'Turkish' : 'English';
storage.language = currentLanguage;
languageButton.setText(getText('language') + ': ' + currentLanguage);
updateAllText();
titleText.setText(getText('settings'));
closeButton.setText(getText('close'));
};
// Close button
var closeButton = settingsMenu.addChild(new MenuButton(getText('close')));
closeButton.y = 100;
closeButton.down = function (x, y, obj) {
MenuButton.prototype.down.call(this, x, y, obj);
closeSettingsMenu();
};
settingsMenu.x = 1024;
settingsMenu.y = 1366;
LK.gui.center.addChild(settingsMenu);
}
function openSettingsMenu() {
if (menuOpen) return;
menuOpen = true;
createSettingsMenu();
// Animate menu in
tween(settingsMenu, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
function closeSettingsMenu() {
if (!menuOpen || !settingsMenu) return;
menuOpen = false;
// Animate menu out
tween(settingsMenu, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (settingsMenu) {
settingsMenu.destroy();
settingsMenu = null;
}
}
});
}
function advanceLevel() {
if (currentLevel >= maxLevel) {
LK.showYouWin();
return;
}
currentLevel++;
enemiesKilled = 0;
enemiesSpawned = 0;
// Update pirate ship stats for new level
pirateShip.moveSpeed = Math.abs(pirateShip.moveSpeed) > 0 ? pirateShip.moveSpeed > 0 ? shipSpeedPerLevel[currentLevel - 1] : -shipSpeedPerLevel[currentLevel - 1] : shipSpeedPerLevel[currentLevel - 1];
pirateShip.enemySpawnRate = enemySpawnRatePerLevel[currentLevel - 1];
pirateShip.maxEnemiesFromShip = enemiesPerLevel[currentLevel - 1];
pirateShip.enemiesSpawnedFromShip = 0;
// Reduce ammo by 5 for new level
var newAmmo = ammoPerLevel[currentLevel - 1] - 5;
currentAmmo = Math.max(newAmmo, 5); // Ensure minimum 5 ammo
maxAmmo = Math.max(newAmmo, 5);
// Update displays
updateLevel();
updateAmmo();
// Flash screen green to indicate level up
LK.effects.flashScreen(0x00ff00, 500);
}
function spawnEnemy() {
if (enemiesSpawned >= maxEnemies) return;
var enemy = new Enemy();
// Spawn from top (opposite direction from player)
enemy.x = Math.random() * 2048;
enemy.y = -30; // Spawn from top of screen
// Set enemy to move toward bottom (toward player)
enemy.directionX = (Math.random() - 0.5) * 0.5;
enemy.directionY = 1; // Always move down toward player
enemy.moveSpeed = 1 + Math.random() * 2; // Ensure speed is set
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
try {
LK.getSound('enemySpawn').play();
} catch (e) {
console.log('Could not play enemySpawn sound');
}
}
function spawnEnemyFromShip(shipX, shipY) {
if (enemiesSpawned >= maxEnemies) return;
var enemy = new Enemy();
// Spawn from pirate ship position
enemy.x = shipX + (Math.random() - 0.5) * 100; // Small random offset from ship
enemy.y = shipY;
// Set enemy to move toward bottom (toward player)
enemy.directionX = (Math.random() - 0.5) * 0.5;
enemy.directionY = 1; // Always move down toward player
enemy.moveSpeed = 1 + Math.random() * 2;
// Add tween animation for enemy dropping from ship
tween(enemy, {
y: shipY + 50
}, {
duration: 500,
easing: tween.easeOut
});
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
try {
LK.getSound('enemySpawn').play();
} catch (e) {
console.log('Could not play enemySpawn sound');
}
}
function shootBullet(targetX, targetY) {
if (!player.isReady || currentAmmo <= 0) return;
currentAmmo--;
updateAmmo();
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
// Calculate direction to target
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize and set speed
bullet.speedX = dx / distance * bullet.speed;
bullet.speedY = dy / distance * bullet.speed;
bullets.push(bullet);
game.addChild(bullet);
player.isReady = false;
readyIndicator.setText(getText('shooting'));
readyIndicator.tint = 0xff0000;
try {
LK.getSound('shoot').play();
} catch (e) {
console.log('Could not play shoot sound');
}
}
function returnBulletToPlayer(bullet) {
// Animate bullet returning to player
tween(bullet, {
x: player.x,
y: player.y
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
bullet.destroy();
var index = bullets.indexOf(bullet);
if (index > -1) {
bullets.splice(index, 1);
}
player.isReady = true;
readyIndicator.setText(getText('ready'));
readyIndicator.tint = 0x00ff00;
}
});
}
game.down = function (x, y, obj) {
// Don't shoot if menu is open
if (menuOpen) return;
if (player.isReady) {
shootBullet(x, y);
}
};
// Handle pause event to show language settings
LK.on('pause', function () {
if (!menuOpen) {
openSettingsMenu();
}
});
// Handle resume event to close language settings
LK.on('resume', function () {
if (menuOpen) {
closeSettingsMenu();
}
});
game.update = function () {
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
returnBulletToPlayer(bullet);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Hit enemy
LK.setScore(LK.getScore() + 10);
updateScore();
enemiesKilled++;
// Flash effect on enemy
LK.effects.flashObject(enemy, 0xffffff, 200);
// Remove enemy
enemy.destroy();
enemies.splice(j, 1);
// Return bullet to player
returnBulletToPlayer(bullet);
hitEnemy = true;
try {
LK.getSound('hit').play();
} catch (e) {
console.log('Could not play hit sound');
}
// Level advancement will be handled at the end of update loop
break;
}
}
if (hitEnemy) break;
}
// Check if player collides with enemies
for (var k = 0; k < enemies.length; k++) {
var enemy = enemies[k];
if (player.intersects(enemy)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check if enemy has gotten behind the player (game over condition)
if (enemy.y > player.y + 50) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Disable regular enemy spawning - enemies now only come from pirate ship
// enemySpawnTimer++;
// if (enemySpawnTimer >= currentSpawnRate && enemiesSpawned < maxEnemies) {
// spawnEnemy();
// enemySpawnTimer = 0;
// }
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= 600) {
// Every 10 seconds
if (currentSpawnRate > 60) {
currentSpawnRate -= 5;
}
difficultyTimer = 0;
}
// Check if game should end (no ammo and no bullets in flight)
if (currentAmmo <= 0 && bullets.length === 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check win condition (completed all levels)
if (currentLevel > maxLevel) {
LK.showYouWin();
return;
}
// Limit number of enemies on screen based on current level
if (enemies.length > maxEnemiesPerLevel[currentLevel - 1]) {
var oldestEnemy = enemies.shift();
oldestEnemy.destroy();
}
// Check for level completion - advance when ship has spawned all its enemies AND all enemies are killed
if (pirateShip.enemiesSpawnedFromShip >= pirateShip.maxEnemiesFromShip && enemies.length === 0 && currentLevel < maxLevel) {
advanceLevel();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
language: "Turkish"
});
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.speed = 12;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = 1 + Math.random() * 2;
self.directionX = (Math.random() - 0.5) * 2;
self.directionY = (Math.random() - 0.5) * 2;
self.update = function () {
self.x += self.directionX * self.moveSpeed;
self.y += self.directionY * self.moveSpeed;
// Keep enemies moving downward (toward player)
if (self.directionY < 0) {
self.directionY = 1;
}
// Bounce off side walls only
if (self.x <= 30 || self.x >= 2018) {
self.directionX *= -1;
}
// Remove enemies that go off bottom of screen
if (self.y > 2782) {
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var MenuButton = Container.expand(function (text, color) {
var self = Container.call(this);
var buttonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(text, {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.setText = function (newText) {
buttonText.setText(newText);
};
self.down = function (x, y, obj) {
// Button press feedback
self.scaleX = 0.9;
self.scaleY = 0.9;
};
self.up = function (x, y, obj) {
// Reset scale
self.scaleX = 1;
self.scaleY = 1;
};
return self;
});
var PirateShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('pirateShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = shipSpeedPerLevel[0]; // Start with level 1 speed
self.enemySpawnTimer = 0;
self.enemySpawnRate = enemySpawnRatePerLevel[0]; // Start with level 1 spawn rate
self.maxEnemiesFromShip = enemiesPerLevel[0]; // Start with level 1 enemy count
self.enemiesSpawnedFromShip = 0;
self.update = function () {
// Move ship horizontally across top of screen
self.x += self.moveSpeed;
// Reverse direction when hitting screen edges
if (self.x <= 100 || self.x >= 1948) {
self.moveSpeed *= -1;
}
// Spawn enemies from ship
self.enemySpawnTimer++;
if (self.enemySpawnTimer >= self.enemySpawnRate && self.enemiesSpawnedFromShip < self.maxEnemiesFromShip) {
spawnEnemyFromShip(self.x, self.y + 80);
self.enemySpawnTimer = 0;
self.enemiesSpawnedFromShip++;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.isReady = true;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Language system
var currentLanguage = storage.language || 'Turkish';
var translations = {
English: {
score: 'Score: ',
ammo: 'Ammo: ',
level: 'Level: ',
ready: 'READY',
shooting: 'SHOOTING',
settings: 'Settings',
language: 'Language',
close: 'Close',
menu: 'Menu'
},
Turkish: {
score: 'Puan: ',
ammo: 'Cephane: ',
level: 'Seviye: ',
ready: 'HAZIR',
shooting: 'ATIŞ',
settings: 'Ayarlar',
language: 'Dil',
close: 'Kapat',
menu: 'Menü'
}
};
function getText(key) {
return translations[currentLanguage][key] || key;
}
// Menu system variables
var menuOpen = false;
var menuContainer = null;
var settingsMenu = null;
var player = game.addChild(new Player());
player.x = 1024;
player.y = 2500;
var bullets = [];
var enemies = [];
var enemySpawnTimer = 0;
var difficultyTimer = 0;
var baseSpawnRate = 180; // frames between spawns
var currentSpawnRate = baseSpawnRate;
// Level system variables
var currentLevel = 1;
var maxLevel = 5;
var enemiesKilled = 0;
var enemiesPerLevel = [10, 15, 20, 25, 30]; // Enemies to kill per level
var shipSpeedPerLevel = [2, 2.5, 3, 3.5, 4]; // Ship speed per level
var enemySpawnRatePerLevel = [120, 100, 80, 60, 40]; // Spawn rate per level (lower = faster)
var maxEnemiesPerLevel = [8, 12, 16, 20, 25]; // Max enemies on screen per level
var ammoPerLevel = [20, 25, 30, 35, 40]; // Ammo given per level
var maxAmmo = ammoPerLevel[0]; // Start with level 1 ammo
var currentAmmo = maxAmmo;
var maxEnemies = maxEnemiesPerLevel[0]; // Start with level 1 max enemies
var enemiesSpawned = 0;
// Add pirate ship
var pirateShip = game.addChild(new PirateShip());
pirateShip.x = 200;
pirateShip.y = 150;
// UI Elements
var scoreTxt = new Text2(getText('score') + '0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var readyIndicator = new Text2(getText('ready'), {
size: 60,
fill: 0x00FF00
});
readyIndicator.anchor.set(0.5, 0.5);
LK.gui.center.addChild(readyIndicator);
var ammoTxt = new Text2(getText('ammo') + '20', {
size: 60,
fill: 0xFFFFFF
});
ammoTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(ammoTxt);
var levelTxt = new Text2(getText('level') + '1', {
size: 60,
fill: 0xFFD700
});
levelTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelTxt);
function updateScore() {
scoreTxt.setText(getText('score') + LK.getScore());
}
function updateAmmo() {
ammoTxt.setText(getText('ammo') + currentAmmo);
}
function updateLevel() {
levelTxt.setText(getText('level') + currentLevel);
}
function updateAllText() {
updateScore();
updateAmmo();
updateLevel();
if (player.isReady) {
readyIndicator.setText(getText('ready'));
} else {
readyIndicator.setText(getText('shooting'));
}
}
function createSettingsMenu() {
if (settingsMenu) return;
settingsMenu = new Container();
// Background
var menuBg = settingsMenu.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
// Title
var titleText = new Text2(getText('settings'), {
size: 70,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -200;
settingsMenu.addChild(titleText);
// Language button
var languageButton = settingsMenu.addChild(new MenuButton(getText('language') + ': ' + currentLanguage));
languageButton.y = -50;
languageButton.down = function (x, y, obj) {
MenuButton.prototype.down.call(this, x, y, obj);
// Toggle language
currentLanguage = currentLanguage === 'English' ? 'Turkish' : 'English';
storage.language = currentLanguage;
languageButton.setText(getText('language') + ': ' + currentLanguage);
updateAllText();
titleText.setText(getText('settings'));
closeButton.setText(getText('close'));
};
// Close button
var closeButton = settingsMenu.addChild(new MenuButton(getText('close')));
closeButton.y = 100;
closeButton.down = function (x, y, obj) {
MenuButton.prototype.down.call(this, x, y, obj);
closeSettingsMenu();
};
settingsMenu.x = 1024;
settingsMenu.y = 1366;
LK.gui.center.addChild(settingsMenu);
}
function openSettingsMenu() {
if (menuOpen) return;
menuOpen = true;
createSettingsMenu();
// Animate menu in
tween(settingsMenu, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
function closeSettingsMenu() {
if (!menuOpen || !settingsMenu) return;
menuOpen = false;
// Animate menu out
tween(settingsMenu, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (settingsMenu) {
settingsMenu.destroy();
settingsMenu = null;
}
}
});
}
function advanceLevel() {
if (currentLevel >= maxLevel) {
LK.showYouWin();
return;
}
currentLevel++;
enemiesKilled = 0;
enemiesSpawned = 0;
// Update pirate ship stats for new level
pirateShip.moveSpeed = Math.abs(pirateShip.moveSpeed) > 0 ? pirateShip.moveSpeed > 0 ? shipSpeedPerLevel[currentLevel - 1] : -shipSpeedPerLevel[currentLevel - 1] : shipSpeedPerLevel[currentLevel - 1];
pirateShip.enemySpawnRate = enemySpawnRatePerLevel[currentLevel - 1];
pirateShip.maxEnemiesFromShip = enemiesPerLevel[currentLevel - 1];
pirateShip.enemiesSpawnedFromShip = 0;
// Reduce ammo by 5 for new level
var newAmmo = ammoPerLevel[currentLevel - 1] - 5;
currentAmmo = Math.max(newAmmo, 5); // Ensure minimum 5 ammo
maxAmmo = Math.max(newAmmo, 5);
// Update displays
updateLevel();
updateAmmo();
// Flash screen green to indicate level up
LK.effects.flashScreen(0x00ff00, 500);
}
function spawnEnemy() {
if (enemiesSpawned >= maxEnemies) return;
var enemy = new Enemy();
// Spawn from top (opposite direction from player)
enemy.x = Math.random() * 2048;
enemy.y = -30; // Spawn from top of screen
// Set enemy to move toward bottom (toward player)
enemy.directionX = (Math.random() - 0.5) * 0.5;
enemy.directionY = 1; // Always move down toward player
enemy.moveSpeed = 1 + Math.random() * 2; // Ensure speed is set
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
try {
LK.getSound('enemySpawn').play();
} catch (e) {
console.log('Could not play enemySpawn sound');
}
}
function spawnEnemyFromShip(shipX, shipY) {
if (enemiesSpawned >= maxEnemies) return;
var enemy = new Enemy();
// Spawn from pirate ship position
enemy.x = shipX + (Math.random() - 0.5) * 100; // Small random offset from ship
enemy.y = shipY;
// Set enemy to move toward bottom (toward player)
enemy.directionX = (Math.random() - 0.5) * 0.5;
enemy.directionY = 1; // Always move down toward player
enemy.moveSpeed = 1 + Math.random() * 2;
// Add tween animation for enemy dropping from ship
tween(enemy, {
y: shipY + 50
}, {
duration: 500,
easing: tween.easeOut
});
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
try {
LK.getSound('enemySpawn').play();
} catch (e) {
console.log('Could not play enemySpawn sound');
}
}
function shootBullet(targetX, targetY) {
if (!player.isReady || currentAmmo <= 0) return;
currentAmmo--;
updateAmmo();
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
// Calculate direction to target
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize and set speed
bullet.speedX = dx / distance * bullet.speed;
bullet.speedY = dy / distance * bullet.speed;
bullets.push(bullet);
game.addChild(bullet);
player.isReady = false;
readyIndicator.setText(getText('shooting'));
readyIndicator.tint = 0xff0000;
try {
LK.getSound('shoot').play();
} catch (e) {
console.log('Could not play shoot sound');
}
}
function returnBulletToPlayer(bullet) {
// Animate bullet returning to player
tween(bullet, {
x: player.x,
y: player.y
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
bullet.destroy();
var index = bullets.indexOf(bullet);
if (index > -1) {
bullets.splice(index, 1);
}
player.isReady = true;
readyIndicator.setText(getText('ready'));
readyIndicator.tint = 0x00ff00;
}
});
}
game.down = function (x, y, obj) {
// Don't shoot if menu is open
if (menuOpen) return;
if (player.isReady) {
shootBullet(x, y);
}
};
// Handle pause event to show language settings
LK.on('pause', function () {
if (!menuOpen) {
openSettingsMenu();
}
});
// Handle resume event to close language settings
LK.on('resume', function () {
if (menuOpen) {
closeSettingsMenu();
}
});
game.update = function () {
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
returnBulletToPlayer(bullet);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Hit enemy
LK.setScore(LK.getScore() + 10);
updateScore();
enemiesKilled++;
// Flash effect on enemy
LK.effects.flashObject(enemy, 0xffffff, 200);
// Remove enemy
enemy.destroy();
enemies.splice(j, 1);
// Return bullet to player
returnBulletToPlayer(bullet);
hitEnemy = true;
try {
LK.getSound('hit').play();
} catch (e) {
console.log('Could not play hit sound');
}
// Level advancement will be handled at the end of update loop
break;
}
}
if (hitEnemy) break;
}
// Check if player collides with enemies
for (var k = 0; k < enemies.length; k++) {
var enemy = enemies[k];
if (player.intersects(enemy)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check if enemy has gotten behind the player (game over condition)
if (enemy.y > player.y + 50) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Disable regular enemy spawning - enemies now only come from pirate ship
// enemySpawnTimer++;
// if (enemySpawnTimer >= currentSpawnRate && enemiesSpawned < maxEnemies) {
// spawnEnemy();
// enemySpawnTimer = 0;
// }
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= 600) {
// Every 10 seconds
if (currentSpawnRate > 60) {
currentSpawnRate -= 5;
}
difficultyTimer = 0;
}
// Check if game should end (no ammo and no bullets in flight)
if (currentAmmo <= 0 && bullets.length === 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check win condition (completed all levels)
if (currentLevel > maxLevel) {
LK.showYouWin();
return;
}
// Limit number of enemies on screen based on current level
if (enemies.length > maxEnemiesPerLevel[currentLevel - 1]) {
var oldestEnemy = enemies.shift();
oldestEnemy.destroy();
}
// Check for level completion - advance when ship has spawned all its enemies AND all enemies are killed
if (pirateShip.enemiesSpawnedFromShip >= pirateShip.maxEnemiesFromShip && enemies.length === 0 && currentLevel < maxLevel) {
advanceLevel();
}
};