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('Health: 3', {
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);
healthTxt.setText('Health: ' + player.health);
}
// 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);
// Don't automatically fire on touch - will be handled by the auto-fire timer
};
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();
// End game if enemies reach the bottom
if (enemy.y > gameHeight - 50) {
gameActive = false;
if (score > storage.highScore) {
storage.highScore = score;
}
LK.setScore(score);
LK.showGameOver();
return;
}
// 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();
// End game if asteroids reach the bottom
if (asteroid.y > gameHeight - 50) {
gameActive = false;
if (score > storage.highScore) {
storage.highScore = score;
}
LK.setScore(score);
LK.showGameOver();
return;
}
// 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, limited to every 0.5 seconds (30 frames)
if (isDragging && LK.ticks % 30 === 0) {
firePlayerBullet();
}
// Update UI
updateUI();
// Check wave progress
checkWaveProgress();
}; ===================================================================
--- original.js
+++ change.js
@@ -244,10 +244,8 @@
var powerUps = [];
// Background stars
var stars = [];
var starCount = 50;
-// Bullet firing control
-var canFireBullet = true;
// Game dimensions
var gameWidth = 2048;
var gameHeight = 2732;
var playerBoundaryLeft = 50;
@@ -374,17 +372,11 @@
powerUps.push(powerUp);
}
// Fire player bullets
function firePlayerBullet() {
- if (!player.canFire() || !gameActive || !canFireBullet) {
+ if (!player.canFire() || !gameActive) {
return;
}
- // Set cooldown of 0.2 seconds (200ms)
- canFireBullet = false;
- tween.stop(canFireBullet);
- LK.setTimeout(function () {
- canFireBullet = true;
- }, 200);
LK.getSound('playerShoot').play();
if (player.hasDoubleFire) {
// Double fire - two bullets side by side
var bullet1 = new Bullet();
@@ -502,10 +494,9 @@
var isDragging = false;
game.down = function (x, y) {
isDragging = true;
movePlayer(x, y);
- // Fire a bullet when player touches the screen
- firePlayerBullet();
+ // Don't automatically fire on touch - will be handled by the auto-fire timer
};
game.up = function () {
isDragging = false;
};
@@ -701,10 +692,10 @@
powerUp.destroy();
powerUps.splice(i, 1);
}
}
- // Auto-fire if player is dragging and can fire
- if (isDragging && canFireBullet) {
+ // Auto-fire if player is dragging, limited to every 0.5 seconds (30 frames)
+ if (isDragging && LK.ticks % 30 === 0) {
firePlayerBullet();
}
// Update UI
updateUI();