User prompt
dont instantly finish the game when i cant catch the obstacles just lose 1 heart
User prompt
show the health with 3 heart emojis
User prompt
only allow firing every 0.3 seconds
User prompt
only allow firing every 0.5 seconds
User prompt
only allow firing every 0.2 seconds ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the bullet 3x bigger
User prompt
make the bullet 1.5x bigger
User prompt
put the health under the score
User prompt
make the bullet 2.5x bigger
User prompt
Finish the game when I can't catch the incoming obstacles
User prompt
show the score under the wave
User prompt
make it so that only the x of the playership change
Code edit (1 edits merged)
Please save this source code
User prompt
Cosmic Defender
User prompt
can you regenerate the game idea
Initial prompt
give me a game idea
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Asteroid = Container.expand(function () { var self = Container.call(this); var asteroidGraphics = self.attachAsset('asteroid', { anchorX: 0.5, anchorY: 0.5 }); var size = 0.5 + Math.random() * 1.5; // Random size between 0.5 and 2.0 asteroidGraphics.scale.set(size, size); self.speed = 2 + Math.random() * 4; // Speed between 2 and 6 self.rotationSpeed = (Math.random() - 0.5) * 0.1; // Random rotation self.update = function () { self.y += self.speed; self.rotation += self.rotationSpeed; }; return self; }); var Bullet = Container.expand(function (isEnemy) { var self = Container.call(this); self.isEnemy = isEnemy || false; var assetId = self.isEnemy ? 'enemyBullet' : 'bullet'; var bulletGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5, scaleX: self.isEnemy ? 1 : 3, scaleY: self.isEnemy ? 1 : 3 }); self.speed = self.isEnemy ? 8 : -15; self.update = function () { self.y += self.speed; }; return self; }); var EnemyShip = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'basic'; var shipGraphics = self.attachAsset('enemyShip', { anchorX: 0.5, anchorY: 0.5 }); // Configure enemy based on type switch (self.type) { case 'basic': self.health = 1; self.speed = 3; self.points = 10; self.fireRate = 0; // Doesn't shoot break; case 'shooter': self.health = 2; self.speed = 2; self.points = 20; self.fireRate = 120; // Frames between shots shipGraphics.tint = 0x9b59b6; // Purple break; case 'elite': self.health = 3; self.speed = 4; self.points = 30; self.fireRate = 90; // Frames between shots shipGraphics.tint = 0xf39c12; // Orange break; } self.fireCounter = Math.floor(Math.random() * self.fireRate); self.movePattern = Math.floor(Math.random() * 3); // 0: straight, 1: zigzag, 2: sine self.patternStep = 0; self.initialX = 0; self.canFire = function () { if (self.fireRate === 0) { return false; } if (self.fireCounter <= 0) { self.fireCounter = self.fireRate; return true; } return false; }; self.hit = function () { self.health--; if (self.health <= 0) { return true; // Enemy destroyed } LK.effects.flashObject(self, 0xffffff, 200); return false; // Enemy still alive }; self.update = function () { // Move downward self.y += self.speed; // Apply movement pattern if (self.movePattern === 1) { // Zigzag if (self.patternStep < 60) { self.x += 1; } else if (self.patternStep < 120) { self.x -= 1; } else { self.patternStep = 0; } self.patternStep++; } else if (self.movePattern === 2) { // Sine wave if (self.initialX === 0) { self.initialX = self.x; } self.x = self.initialX + Math.sin(self.patternStep * 0.05) * 100; self.patternStep++; } // Update fire counter if (self.fireCounter > 0) { self.fireCounter--; } }; return self; }); var PlayerShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); self.shield = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.speed = 12; self.fireRate = 20; // Frames between shots self.fireCounter = 0; self.hasShield = false; self.hasDoubleFire = false; self.health = 3; self.activateShield = function () { self.hasShield = true; self.shield.alpha = 0.4; // Shield expires after 10 seconds LK.setTimeout(function () { self.hasShield = false; tween(self.shield, { alpha: 0 }, { duration: 500 }); }, 10000); }; self.hit = function () { if (self.hasShield) { self.hasShield = false; tween(self.shield, { alpha: 0 }, { duration: 500 }); return false; // No damage taken } else { self.health--; LK.getSound('playerHit').play(); LK.effects.flashObject(self, 0xff0000, 500); return true; // Damage taken } }; self.activateDoubleFire = function () { self.hasDoubleFire = true; // Double fire expires after 8 seconds LK.setTimeout(function () { self.hasDoubleFire = false; }, 8000); }; self.canFire = function () { if (self.fireCounter <= 0) { self.fireCounter = self.fireRate; return true; } return false; }; self.update = function () { if (self.fireCounter > 0) { self.fireCounter--; } }; return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); self.type = type || Math.random() < 0.5 ? 'shield' : 'doubleFire'; var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); // Set color based on type if (self.type === 'shield') { powerUpGraphics.tint = 0x3498db; // Blue } else if (self.type === 'doubleFire') { powerUpGraphics.tint = 0xf1c40f; // Yellow } self.speed = 3; self.pulseDirection = 1; self.pulseStep = 0; self.update = function () { self.y += self.speed; // Pulse animation self.pulseStep += 0.05 * self.pulseDirection; if (self.pulseStep >= 1) { self.pulseDirection = -1; } else if (self.pulseStep <= 0) { self.pulseDirection = 1; } powerUpGraphics.alpha = 0.7 + self.pulseStep * 0.3; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game state var gameActive = true; var score = 0; var wave = 1; var enemiesDefeated = 0; var enemiesRequired = 10; // Enemies to defeat to advance to next wave // Game elements var player; var bullets = []; var enemyBullets = []; var enemies = []; var asteroids = []; var powerUps = []; // Background stars var stars = []; var starCount = 50; // Game dimensions var gameWidth = 2048; var gameHeight = 2732; var playerBoundaryLeft = 50; var playerBoundaryRight = gameWidth - 50; var playerBoundaryTop = 100; var playerBoundaryBottom = gameHeight - 200; // UI elements var scoreTxt; var waveTxt; var healthTxt; // Spawn timers var enemySpawnTimer; var asteroidSpawnTimer; var powerUpSpawnTimer; // Initialize player function initPlayer() { player = new PlayerShip(); player.x = gameWidth / 2; player.y = gameHeight - 300; game.addChild(player); } // Initialize UI function initUI() { // Wave text waveTxt = new Text2('Wave: 1', { size: 60, fill: 0xFFFFFF }); waveTxt.anchor.set(0.5, 0); LK.gui.top.addChild(waveTxt); // Score text scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 70; // Position below the wave text LK.gui.top.addChild(scoreTxt); // Health text healthTxt = new Text2('❤️❤️❤️', { size: 60, fill: 0xFFFFFF }); healthTxt.anchor.set(0.5, 0); healthTxt.y = 140; // Position below the score text LK.gui.top.addChild(healthTxt); } // Initialize stars background function initStars() { for (var i = 0; i < starCount; i++) { var star = LK.getAsset('asteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1 + Math.random() * 0.1, scaleY: 0.1 + Math.random() * 0.1, alpha: 0.3 + Math.random() * 0.5 }); star.x = Math.random() * gameWidth; star.y = Math.random() * gameHeight; star.speed = 0.5 + Math.random() * 1.5; game.addChild(star); stars.push(star); } } // Spawn timers function initSpawnTimers() { // Enemy spawn timer (adjusted by wave) enemySpawnTimer = LK.setInterval(function () { spawnEnemy(); }, 2000 - (wave * 100 > 1500 ? 1500 : wave * 100)); // Asteroid spawn timer asteroidSpawnTimer = LK.setInterval(function () { spawnAsteroid(); }, 3000); // Power-up spawn timer powerUpSpawnTimer = LK.setInterval(function () { if (Math.random() < 0.3) { // 30% chance to spawn power-up spawnPowerUp(); } }, 10000); } // Spawn an enemy function spawnEnemy() { if (!gameActive) { return; } var enemyType = 'basic'; var rand = Math.random(); // Adjust enemy type probability based on wave if (wave >= 3) { if (rand < 0.3) { enemyType = 'shooter'; } else if (wave >= 5 && rand < 0.5) { enemyType = 'elite'; } } var enemy = new EnemyShip(enemyType); enemy.x = 100 + Math.random() * (gameWidth - 200); enemy.y = -100; game.addChild(enemy); enemies.push(enemy); } // Spawn an asteroid function spawnAsteroid() { if (!gameActive) { return; } var asteroid = new Asteroid(); asteroid.x = Math.random() * gameWidth; asteroid.y = -100; game.addChild(asteroid); asteroids.push(asteroid); } // Spawn a power-up function spawnPowerUp() { if (!gameActive) { return; } var powerUp = new PowerUp(); powerUp.x = 100 + Math.random() * (gameWidth - 200); powerUp.y = -100; game.addChild(powerUp); powerUps.push(powerUp); } // Fire player bullets function firePlayerBullet() { if (!player.canFire() || !gameActive) { return; } LK.getSound('playerShoot').play(); if (player.hasDoubleFire) { // Double fire - two bullets side by side var bullet1 = new Bullet(); bullet1.x = player.x - 20; bullet1.y = player.y - 30; game.addChild(bullet1); bullets.push(bullet1); var bullet2 = new Bullet(); bullet2.x = player.x + 20; bullet2.y = player.y - 30; game.addChild(bullet2); bullets.push(bullet2); } else { // Normal fire - single bullet var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y - 30; game.addChild(bullet); bullets.push(bullet); } } // Fire enemy bullet function fireEnemyBullet(enemy) { if (!gameActive) { return; } var bullet = new Bullet(true); bullet.x = enemy.x; bullet.y = enemy.y + 40; game.addChild(bullet); enemyBullets.push(bullet); LK.getSound('enemyShoot').play(); } // Handle collision between two game objects function checkCollision(obj1, obj2) { return obj1.intersects(obj2); } // Handle player movement function movePlayer(x, y) { if (!gameActive || !player) { return; } // Keep player within boundaries if (x < playerBoundaryLeft) { x = playerBoundaryLeft; } if (x > playerBoundaryRight) { x = playerBoundaryRight; } // Only change x position, keep y position fixed player.x = x; // Do not change y position anymore } // Update UI function updateUI() { scoreTxt.setText('Score: ' + score); waveTxt.setText('Wave: ' + wave); // Display health as heart emojis var hearts = ''; for (var i = 0; i < player.health; i++) { hearts += '❤️'; } healthTxt.setText(hearts); } // Check if wave is complete function checkWaveProgress() { if (enemiesDefeated >= enemiesRequired) { wave++; enemiesDefeated = 0; enemiesRequired = Math.min(10 + wave * 5, 50); // Increase required enemies, max 50 waveTxt.setText('Wave: ' + wave); // Reset spawn timers with new rates LK.clearInterval(enemySpawnTimer); enemySpawnTimer = LK.setInterval(function () { spawnEnemy(); }, Math.max(2000 - wave * 100, 500)); // Minimum 500ms } } // Game over check function checkGameOver() { if (player.health <= 0) { gameActive = false; // Check for high score if (score > storage.highScore) { storage.highScore = score; } // Show game over screen LK.setScore(score); LK.showGameOver(); } } // Initialize game function initGame() { // Set background color game.setBackgroundColor(0x0a0a2a); // Dark blue space color // Reset game state gameActive = true; score = 0; wave = 1; enemiesDefeated = 0; enemiesRequired = 10; LK.setScore(0); // Initialize game elements initPlayer(); initUI(); initStars(); initSpawnTimers(); // Play background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); } // Start the game initGame(); // Game touch controls var isDragging = false; game.down = function (x, y) { isDragging = true; movePlayer(x, y); // Fire a bullet when player touches the screen firePlayerBullet(); }; game.up = function () { isDragging = false; }; game.move = function (x, y) { if (isDragging) { movePlayer(x, y); } }; // Game update loop game.update = function () { if (!gameActive) { return; } // Update player if (player) { player.update(); } // Update stars for (var i = 0; i < stars.length; i++) { stars[i].y += stars[i].speed; // Reset star when it goes off-screen if (stars[i].y > gameHeight) { stars[i].y = -10; stars[i].x = Math.random() * gameWidth; } } // Update player bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; bullet.update(); // Remove bullets that go off-screen if (bullet.y < -50) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check bullet collisions with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (checkCollision(bullet, enemy)) { // Enemy hit if (enemy.hit()) { // Enemy destroyed score += enemy.points; LK.setScore(score); enemiesDefeated++; LK.getSound('explosion').play(); LK.effects.flashObject(enemy, 0xffffff, 100); enemy.destroy(); enemies.splice(j, 1); } // Remove bullet bullet.destroy(); bullets.splice(i, 1); break; } } // Check bullet collisions with asteroids if (bullets[i]) { // Make sure bullet wasn't removed in enemy collision check for (var j = asteroids.length - 1; j >= 0; j--) { var asteroid = asteroids[j]; if (checkCollision(bullet, asteroid)) { // Asteroid destroyed score += 5; LK.setScore(score); LK.getSound('explosion').play(); LK.effects.flashObject(asteroid, 0xffffff, 100); asteroid.destroy(); asteroids.splice(j, 1); // Remove bullet bullet.destroy(); bullets.splice(i, 1); break; } } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; bullet.update(); // Remove bullets that go off-screen if (bullet.y > gameHeight + 50) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } // Check bullet collisions with player if (player && checkCollision(bullet, player)) { if (player.hit()) { // Player damaged, check game over checkGameOver(); } // Remove bullet bullet.destroy(); enemyBullets.splice(i, 1); } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Reduce health if enemies reach the bottom if (enemy.y > gameHeight - 50) { player.health--; updateUI(); checkGameOver(); LK.getSound('playerHit').play(); LK.effects.flashObject(player, 0xff0000, 500); enemy.destroy(); enemies.splice(i, 1); continue; } // Remove enemies that go off-screen if (enemy.y > gameHeight + 100) { enemy.destroy(); enemies.splice(i, 1); continue; } // Fire enemy bullets if (enemy.canFire()) { fireEnemyBullet(enemy); } // Check collisions with player if (player && checkCollision(enemy, player)) { if (player.hit()) { // Player damaged, check game over checkGameOver(); } // Remove enemy enemy.destroy(); enemies.splice(i, 1); // Add to score and enemy count score += enemy.points; LK.setScore(score); enemiesDefeated++; LK.getSound('explosion').play(); continue; } } // Update asteroids for (var i = asteroids.length - 1; i >= 0; i--) { var asteroid = asteroids[i]; asteroid.update(); // Reduce health if asteroids reach the bottom if (asteroid.y > gameHeight - 50) { player.health--; updateUI(); checkGameOver(); LK.getSound('playerHit').play(); LK.effects.flashObject(player, 0xff0000, 500); asteroid.destroy(); asteroids.splice(i, 1); continue; } // Remove asteroids that go off-screen if (asteroid.y > gameHeight + 100) { asteroid.destroy(); asteroids.splice(i, 1); continue; } // Check collisions with player if (player && checkCollision(asteroid, player)) { if (player.hit()) { // Player damaged, check game over checkGameOver(); } // Remove asteroid asteroid.destroy(); asteroids.splice(i, 1); continue; } } // Update power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; powerUp.update(); // Remove power-ups that go off-screen if (powerUp.y > gameHeight + 100) { powerUp.destroy(); powerUps.splice(i, 1); continue; } // Check collisions with player if (player && checkCollision(powerUp, player)) { // Apply power-up effect if (powerUp.type === 'shield') { player.activateShield(); } else if (powerUp.type === 'doubleFire') { player.activateDoubleFire(); } LK.getSound('powerUpCollect').play(); // Remove power-up powerUp.destroy(); powerUps.splice(i, 1); } } // Auto-fire if player is dragging (every 0.3 seconds) if (isDragging && LK.ticks % 18 === 0) { firePlayerBullet(); } // Update UI updateUI(); // Check wave progress checkWaveProgress(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Asteroid = Container.expand(function () {
var self = Container.call(this);
var asteroidGraphics = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5
});
var size = 0.5 + Math.random() * 1.5; // Random size between 0.5 and 2.0
asteroidGraphics.scale.set(size, size);
self.speed = 2 + Math.random() * 4; // Speed between 2 and 6
self.rotationSpeed = (Math.random() - 0.5) * 0.1; // Random rotation
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
var Bullet = Container.expand(function (isEnemy) {
var self = Container.call(this);
self.isEnemy = isEnemy || false;
var assetId = self.isEnemy ? 'enemyBullet' : 'bullet';
var bulletGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.isEnemy ? 1 : 3,
scaleY: self.isEnemy ? 1 : 3
});
self.speed = self.isEnemy ? 8 : -15;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyShip = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
var shipGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Configure enemy based on type
switch (self.type) {
case 'basic':
self.health = 1;
self.speed = 3;
self.points = 10;
self.fireRate = 0; // Doesn't shoot
break;
case 'shooter':
self.health = 2;
self.speed = 2;
self.points = 20;
self.fireRate = 120; // Frames between shots
shipGraphics.tint = 0x9b59b6; // Purple
break;
case 'elite':
self.health = 3;
self.speed = 4;
self.points = 30;
self.fireRate = 90; // Frames between shots
shipGraphics.tint = 0xf39c12; // Orange
break;
}
self.fireCounter = Math.floor(Math.random() * self.fireRate);
self.movePattern = Math.floor(Math.random() * 3); // 0: straight, 1: zigzag, 2: sine
self.patternStep = 0;
self.initialX = 0;
self.canFire = function () {
if (self.fireRate === 0) {
return false;
}
if (self.fireCounter <= 0) {
self.fireCounter = self.fireRate;
return true;
}
return false;
};
self.hit = function () {
self.health--;
if (self.health <= 0) {
return true; // Enemy destroyed
}
LK.effects.flashObject(self, 0xffffff, 200);
return false; // Enemy still alive
};
self.update = function () {
// Move downward
self.y += self.speed;
// Apply movement pattern
if (self.movePattern === 1) {
// Zigzag
if (self.patternStep < 60) {
self.x += 1;
} else if (self.patternStep < 120) {
self.x -= 1;
} else {
self.patternStep = 0;
}
self.patternStep++;
} else if (self.movePattern === 2) {
// Sine wave
if (self.initialX === 0) {
self.initialX = self.x;
}
self.x = self.initialX + Math.sin(self.patternStep * 0.05) * 100;
self.patternStep++;
}
// Update fire counter
if (self.fireCounter > 0) {
self.fireCounter--;
}
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.shield = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.speed = 12;
self.fireRate = 20; // Frames between shots
self.fireCounter = 0;
self.hasShield = false;
self.hasDoubleFire = false;
self.health = 3;
self.activateShield = function () {
self.hasShield = true;
self.shield.alpha = 0.4;
// Shield expires after 10 seconds
LK.setTimeout(function () {
self.hasShield = false;
tween(self.shield, {
alpha: 0
}, {
duration: 500
});
}, 10000);
};
self.hit = function () {
if (self.hasShield) {
self.hasShield = false;
tween(self.shield, {
alpha: 0
}, {
duration: 500
});
return false; // No damage taken
} else {
self.health--;
LK.getSound('playerHit').play();
LK.effects.flashObject(self, 0xff0000, 500);
return true; // Damage taken
}
};
self.activateDoubleFire = function () {
self.hasDoubleFire = true;
// Double fire expires after 8 seconds
LK.setTimeout(function () {
self.hasDoubleFire = false;
}, 8000);
};
self.canFire = function () {
if (self.fireCounter <= 0) {
self.fireCounter = self.fireRate;
return true;
}
return false;
};
self.update = function () {
if (self.fireCounter > 0) {
self.fireCounter--;
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || Math.random() < 0.5 ? 'shield' : 'doubleFire';
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
// Set color based on type
if (self.type === 'shield') {
powerUpGraphics.tint = 0x3498db; // Blue
} else if (self.type === 'doubleFire') {
powerUpGraphics.tint = 0xf1c40f; // Yellow
}
self.speed = 3;
self.pulseDirection = 1;
self.pulseStep = 0;
self.update = function () {
self.y += self.speed;
// Pulse animation
self.pulseStep += 0.05 * self.pulseDirection;
if (self.pulseStep >= 1) {
self.pulseDirection = -1;
} else if (self.pulseStep <= 0) {
self.pulseDirection = 1;
}
powerUpGraphics.alpha = 0.7 + self.pulseStep * 0.3;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state
var gameActive = true;
var score = 0;
var wave = 1;
var enemiesDefeated = 0;
var enemiesRequired = 10; // Enemies to defeat to advance to next wave
// Game elements
var player;
var bullets = [];
var enemyBullets = [];
var enemies = [];
var asteroids = [];
var powerUps = [];
// Background stars
var stars = [];
var starCount = 50;
// Game dimensions
var gameWidth = 2048;
var gameHeight = 2732;
var playerBoundaryLeft = 50;
var playerBoundaryRight = gameWidth - 50;
var playerBoundaryTop = 100;
var playerBoundaryBottom = gameHeight - 200;
// UI elements
var scoreTxt;
var waveTxt;
var healthTxt;
// Spawn timers
var enemySpawnTimer;
var asteroidSpawnTimer;
var powerUpSpawnTimer;
// Initialize player
function initPlayer() {
player = new PlayerShip();
player.x = gameWidth / 2;
player.y = gameHeight - 300;
game.addChild(player);
}
// Initialize UI
function initUI() {
// Wave text
waveTxt = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(waveTxt);
// Score text
scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 70; // Position below the wave text
LK.gui.top.addChild(scoreTxt);
// Health text
healthTxt = new Text2('❤️❤️❤️', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 0);
healthTxt.y = 140; // Position below the score text
LK.gui.top.addChild(healthTxt);
}
// Initialize stars background
function initStars() {
for (var i = 0; i < starCount; i++) {
var star = LK.getAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1 + Math.random() * 0.1,
scaleY: 0.1 + Math.random() * 0.1,
alpha: 0.3 + Math.random() * 0.5
});
star.x = Math.random() * gameWidth;
star.y = Math.random() * gameHeight;
star.speed = 0.5 + Math.random() * 1.5;
game.addChild(star);
stars.push(star);
}
}
// Spawn timers
function initSpawnTimers() {
// Enemy spawn timer (adjusted by wave)
enemySpawnTimer = LK.setInterval(function () {
spawnEnemy();
}, 2000 - (wave * 100 > 1500 ? 1500 : wave * 100));
// Asteroid spawn timer
asteroidSpawnTimer = LK.setInterval(function () {
spawnAsteroid();
}, 3000);
// Power-up spawn timer
powerUpSpawnTimer = LK.setInterval(function () {
if (Math.random() < 0.3) {
// 30% chance to spawn power-up
spawnPowerUp();
}
}, 10000);
}
// Spawn an enemy
function spawnEnemy() {
if (!gameActive) {
return;
}
var enemyType = 'basic';
var rand = Math.random();
// Adjust enemy type probability based on wave
if (wave >= 3) {
if (rand < 0.3) {
enemyType = 'shooter';
} else if (wave >= 5 && rand < 0.5) {
enemyType = 'elite';
}
}
var enemy = new EnemyShip(enemyType);
enemy.x = 100 + Math.random() * (gameWidth - 200);
enemy.y = -100;
game.addChild(enemy);
enemies.push(enemy);
}
// Spawn an asteroid
function spawnAsteroid() {
if (!gameActive) {
return;
}
var asteroid = new Asteroid();
asteroid.x = Math.random() * gameWidth;
asteroid.y = -100;
game.addChild(asteroid);
asteroids.push(asteroid);
}
// Spawn a power-up
function spawnPowerUp() {
if (!gameActive) {
return;
}
var powerUp = new PowerUp();
powerUp.x = 100 + Math.random() * (gameWidth - 200);
powerUp.y = -100;
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Fire player bullets
function firePlayerBullet() {
if (!player.canFire() || !gameActive) {
return;
}
LK.getSound('playerShoot').play();
if (player.hasDoubleFire) {
// Double fire - two bullets side by side
var bullet1 = new Bullet();
bullet1.x = player.x - 20;
bullet1.y = player.y - 30;
game.addChild(bullet1);
bullets.push(bullet1);
var bullet2 = new Bullet();
bullet2.x = player.x + 20;
bullet2.y = player.y - 30;
game.addChild(bullet2);
bullets.push(bullet2);
} else {
// Normal fire - single bullet
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 30;
game.addChild(bullet);
bullets.push(bullet);
}
}
// Fire enemy bullet
function fireEnemyBullet(enemy) {
if (!gameActive) {
return;
}
var bullet = new Bullet(true);
bullet.x = enemy.x;
bullet.y = enemy.y + 40;
game.addChild(bullet);
enemyBullets.push(bullet);
LK.getSound('enemyShoot').play();
}
// Handle collision between two game objects
function checkCollision(obj1, obj2) {
return obj1.intersects(obj2);
}
// Handle player movement
function movePlayer(x, y) {
if (!gameActive || !player) {
return;
}
// Keep player within boundaries
if (x < playerBoundaryLeft) {
x = playerBoundaryLeft;
}
if (x > playerBoundaryRight) {
x = playerBoundaryRight;
}
// Only change x position, keep y position fixed
player.x = x;
// Do not change y position anymore
}
// Update UI
function updateUI() {
scoreTxt.setText('Score: ' + score);
waveTxt.setText('Wave: ' + wave);
// Display health as heart emojis
var hearts = '';
for (var i = 0; i < player.health; i++) {
hearts += '❤️';
}
healthTxt.setText(hearts);
}
// Check if wave is complete
function checkWaveProgress() {
if (enemiesDefeated >= enemiesRequired) {
wave++;
enemiesDefeated = 0;
enemiesRequired = Math.min(10 + wave * 5, 50); // Increase required enemies, max 50
waveTxt.setText('Wave: ' + wave);
// Reset spawn timers with new rates
LK.clearInterval(enemySpawnTimer);
enemySpawnTimer = LK.setInterval(function () {
spawnEnemy();
}, Math.max(2000 - wave * 100, 500)); // Minimum 500ms
}
}
// Game over check
function checkGameOver() {
if (player.health <= 0) {
gameActive = false;
// Check for high score
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over screen
LK.setScore(score);
LK.showGameOver();
}
}
// Initialize game
function initGame() {
// Set background color
game.setBackgroundColor(0x0a0a2a); // Dark blue space color
// Reset game state
gameActive = true;
score = 0;
wave = 1;
enemiesDefeated = 0;
enemiesRequired = 10;
LK.setScore(0);
// Initialize game elements
initPlayer();
initUI();
initStars();
initSpawnTimers();
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
}
// Start the game
initGame();
// Game touch controls
var isDragging = false;
game.down = function (x, y) {
isDragging = true;
movePlayer(x, y);
// Fire a bullet when player touches the screen
firePlayerBullet();
};
game.up = function () {
isDragging = false;
};
game.move = function (x, y) {
if (isDragging) {
movePlayer(x, y);
}
};
// Game update loop
game.update = function () {
if (!gameActive) {
return;
}
// Update player
if (player) {
player.update();
}
// Update stars
for (var i = 0; i < stars.length; i++) {
stars[i].y += stars[i].speed;
// Reset star when it goes off-screen
if (stars[i].y > gameHeight) {
stars[i].y = -10;
stars[i].x = Math.random() * gameWidth;
}
}
// Update player bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
bullet.update();
// Remove bullets that go off-screen
if (bullet.y < -50) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet collisions with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (checkCollision(bullet, enemy)) {
// Enemy hit
if (enemy.hit()) {
// Enemy destroyed
score += enemy.points;
LK.setScore(score);
enemiesDefeated++;
LK.getSound('explosion').play();
LK.effects.flashObject(enemy, 0xffffff, 100);
enemy.destroy();
enemies.splice(j, 1);
}
// Remove bullet
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
// Check bullet collisions with asteroids
if (bullets[i]) {
// Make sure bullet wasn't removed in enemy collision check
for (var j = asteroids.length - 1; j >= 0; j--) {
var asteroid = asteroids[j];
if (checkCollision(bullet, asteroid)) {
// Asteroid destroyed
score += 5;
LK.setScore(score);
LK.getSound('explosion').play();
LK.effects.flashObject(asteroid, 0xffffff, 100);
asteroid.destroy();
asteroids.splice(j, 1);
// Remove bullet
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
bullet.update();
// Remove bullets that go off-screen
if (bullet.y > gameHeight + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check bullet collisions with player
if (player && checkCollision(bullet, player)) {
if (player.hit()) {
// Player damaged, check game over
checkGameOver();
}
// Remove bullet
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Reduce health if enemies reach the bottom
if (enemy.y > gameHeight - 50) {
player.health--;
updateUI();
checkGameOver();
LK.getSound('playerHit').play();
LK.effects.flashObject(player, 0xff0000, 500);
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Remove enemies that go off-screen
if (enemy.y > gameHeight + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Fire enemy bullets
if (enemy.canFire()) {
fireEnemyBullet(enemy);
}
// Check collisions with player
if (player && checkCollision(enemy, player)) {
if (player.hit()) {
// Player damaged, check game over
checkGameOver();
}
// Remove enemy
enemy.destroy();
enemies.splice(i, 1);
// Add to score and enemy count
score += enemy.points;
LK.setScore(score);
enemiesDefeated++;
LK.getSound('explosion').play();
continue;
}
}
// Update asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
asteroid.update();
// Reduce health if asteroids reach the bottom
if (asteroid.y > gameHeight - 50) {
player.health--;
updateUI();
checkGameOver();
LK.getSound('playerHit').play();
LK.effects.flashObject(player, 0xff0000, 500);
asteroid.destroy();
asteroids.splice(i, 1);
continue;
}
// Remove asteroids that go off-screen
if (asteroid.y > gameHeight + 100) {
asteroid.destroy();
asteroids.splice(i, 1);
continue;
}
// Check collisions with player
if (player && checkCollision(asteroid, player)) {
if (player.hit()) {
// Player damaged, check game over
checkGameOver();
}
// Remove asteroid
asteroid.destroy();
asteroids.splice(i, 1);
continue;
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.update();
// Remove power-ups that go off-screen
if (powerUp.y > gameHeight + 100) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collisions with player
if (player && checkCollision(powerUp, player)) {
// Apply power-up effect
if (powerUp.type === 'shield') {
player.activateShield();
} else if (powerUp.type === 'doubleFire') {
player.activateDoubleFire();
}
LK.getSound('powerUpCollect').play();
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Auto-fire if player is dragging (every 0.3 seconds)
if (isDragging && LK.ticks % 18 === 0) {
firePlayerBullet();
}
// Update UI
updateUI();
// Check wave progress
checkWaveProgress();
};