User prompt
Save the code please
User prompt
Make that each level gets harder and harder and make the powerups rare to drop
User prompt
Earth-monster has 20 hearts
User prompt
If you defeated the earth-monster you win
User prompt
At the end of the game that’s level 10 the earth-monster comes out it’s bullets shoots 5 times more bullets and 3 times stronger
User prompt
Bad-oil is the same as oil-food but takes 10 percent of oil away
User prompt
If you touch oil-food you gain 1 percent of oil
User prompt
If you don’t have any oil the game stops and you start with 20/40
User prompt
If you touch oil-food you get 1 percent of oil if you do not have any oil then it says enemy’s win then the game stops
User prompt
Make there be Ten Hearts and Also, if you hit a new enemy and an enemy you lose one heart, but you kill the
User prompt
Make the new-ast like the asteroid but if you touch it you lose comes at level 2
User prompt
Make it the new-enemy goes left and right only
User prompt
Now make new-enemy the same as enemy but it only a comes out at level 4
User prompt
Make a second enemy that only appears at level 10
User prompt
Please fix the bug: 'Timeout.tick error: tween.to is not a function. (In 'tween.to(instructionsTxt, { alpha: 0 }, 1000)', 'tween.to' is undefined)' in or related to this line: 'tween.to(instructionsTxt, {' Line Number: 494 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The bullet hits the asteroid, then the bullet breaks and disappears.
User prompt
You can't Shoot and destroy the asteroid, but you can only dodge it
Code edit (1 edits merged)
Please save this source code
User prompt
Galactic Defender: Space Shooter
Initial prompt
A space shooter game
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Asteroid = Container.expand(function () {
	var self = Container.call(this);
	var asteroidGraphics = self.attachAsset('asteroid', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 1.5
	});
	self.speed = 6;
	self.rotationSpeed = Math.random() * 0.05 - 0.025;
	self.scoreValue = 5;
	self.lastY = -100; // Track last position for collision detection
	self.update = function () {
		self.lastY = self.y;
		self.y += self.speed;
		self.rotation += self.rotationSpeed;
		// Add side-to-side movement to make dodging more challenging
		self.x += Math.sin(LK.ticks * 0.02) * 2;
	};
	return self;
});
var BadOil = Container.expand(function () {
	var self = Container.call(this);
	var badOilGraphics = self.attachAsset('Bad-oil', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.2,
		scaleY: 1.2
	});
	self.speed = 5;
	self.lastY = -100;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.speed;
		// Add some side movement
		self.x += Math.sin(LK.ticks * 0.03) * 2;
	};
	return self;
});
var BossEnemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2.5,
		scaleY: 2.5,
		tint: 0xff0000
	});
	self.speed = 2;
	self.health = 5;
	self.moveDirection = 1; // 1 for right, -1 for left
	self.shootChance = 0.03; // Higher chance to shoot than regular enemies
	self.scoreValue = 50;
	self.lastY = -100;
	self.update = function () {
		self.lastY = self.y;
		// Move down more slowly
		self.y += self.speed;
		// Move in a more complex pattern
		self.x += self.moveDirection * 3 * Math.sin(LK.ticks * 0.02);
		// Change direction at edges
		if (self.x < 200 || self.x > 2048 - 200) {
			self.moveDirection *= -1;
		}
	};
	return self;
});
var EarthMonster = Container.expand(function () {
	var self = Container.call(this);
	var monsterGraphics = self.attachAsset('Earth-monster', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 3.0,
		scaleY: 3.0
	});
	self.speed = 1.5;
	self.health = 20; // Earth-monster has 20 hearts
	self.moveDirection = 1; // 1 for right, -1 for left
	self.shootChance = 0.05; // Higher chance to shoot than other enemies
	self.scoreValue = 200;
	self.lastY = -100;
	self.update = function () {
		self.lastY = self.y;
		// Move down more slowly
		self.y += self.speed;
		// Move in a complex pattern
		self.x += self.moveDirection * 2 * Math.sin(LK.ticks * 0.03);
		// Change direction at edges
		if (self.x < 300 || self.x > 2048 - 300) {
			self.moveDirection *= -1;
		}
	};
	return self;
});
var EarthMonsterBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 1.5,
		tint: 0x00ffff
	});
	self.speed = 12; // Faster than regular enemy bullets
	self.damage = 3; // Does 3x damage
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 3;
	self.moveDirection = 1; // 1 for right, -1 for left
	self.shootChance = 0.01; // Chance to shoot per update
	self.scoreValue = 10;
	self.update = function () {
		// Move down
		self.y += self.speed;
		// Move side to side
		self.x += self.moveDirection * 2;
		// Change direction at edges
		if (self.x < 100 || self.x > 2048 - 100) {
			self.moveDirection *= -1;
		}
	};
	return self;
});
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var Heart = Container.expand(function () {
	var self = Container.call(this);
	var heartGraphics = self.attachAsset('playerBullet', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0xff0000,
		scaleX: 0.8,
		scaleY: 0.8
	});
	self.setActive = function (active) {
		heartGraphics.alpha = active ? 1 : 0.3;
	};
	return self;
});
var NewAsteroid = Container.expand(function () {
	var self = Container.call(this);
	var asteroidGraphics = self.attachAsset('New-ast', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 1.5
	});
	self.speed = 7; // Faster than regular asteroid
	self.rotationSpeed = Math.random() * 0.08 - 0.04; // Faster rotation
	self.scoreValue = 0; // No points for this one since it's deadly
	self.lastY = -100; // Track last position for collision detection
	self.update = function () {
		self.lastY = self.y;
		self.y += self.speed;
		self.rotation += self.rotationSpeed;
		// More erratic movement pattern
		self.x += Math.sin(LK.ticks * 0.03) * 3;
	};
	return self;
});
var NewEnemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('New-enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 4; // Faster than regular enemy
	self.moveDirection = 1; // 1 for right, -1 for left
	self.shootChance = 0.02; // Higher chance to shoot than regular enemies
	self.scoreValue = 20; // Worth more points than regular enemies
	self.update = function () {
		// Only move left and right, no vertical movement
		// Move side to side more aggressively
		self.x += self.moveDirection * 3;
		// Change direction at edges
		if (self.x < 100 || self.x > 2048 - 100) {
			self.moveDirection *= -1;
		}
	};
	return self;
});
var OilFood = Container.expand(function () {
	var self = Container.call(this);
	var oilFoodGraphics = self.attachAsset('Oil-food', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.2,
		scaleY: 1.2
	});
	self.speed = 5;
	self.lastY = -100;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.speed;
		// Add some side movement
		self.x += Math.sin(LK.ticks * 0.03) * 2;
	};
	return self;
});
var PlayerBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('playerBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -15;
	self.update = function () {
		self.y += self.speed;
	};
	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.hasShield = false;
	self.fireRate = 20; // Time between shots in ticks
	self.fireCooldown = 0;
	self.rapidFire = false;
	self.rapidFireTimer = 0;
	self.lives = 3; // Keep this for backward compatibility
	self.activateShield = function () {
		self.hasShield = true;
		self.shield.alpha = 0.5;
	};
	self.deactivateShield = function () {
		self.hasShield = false;
		self.shield.alpha = 0;
	};
	self.activateRapidFire = function () {
		self.rapidFire = true;
		self.rapidFireTimer = 300; // 5 seconds at 60 FPS
	};
	self.canFire = function () {
		if (self.fireCooldown <= 0) {
			self.fireCooldown = self.rapidFire ? Math.floor(self.fireRate / 2) : self.fireRate;
			return true;
		}
		return false;
	};
	self.hit = function () {
		if (self.hasShield) {
			self.deactivateShield();
			return false; // Shield absorbed the hit
		} else {
			// Use the hearts system instead of lives
			if (currentHearts > 0) {
				currentHearts--;
				updateHearts();
				LK.effects.flashObject(self, 0xff0000, 500);
				return true; // Ship took damage
			}
			return false;
		}
	};
	self.update = function () {
		if (self.fireCooldown > 0) {
			self.fireCooldown--;
		}
		if (self.rapidFire && self.rapidFireTimer > 0) {
			self.rapidFireTimer--;
			if (self.rapidFireTimer <= 0) {
				self.rapidFire = false;
			}
		}
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerupGraphics = self.attachAsset('powerup', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 3;
	self.type = Math.floor(Math.random() * 2); // 0 for shield, 1 for rapid fire
	// Set color based on type
	if (self.type === 0) {
		powerupGraphics.tint = 0x3498db; // Blue for shield
	} else {
		powerupGraphics.tint = 0xf39c12; // Orange for rapid fire
	}
	self.update = function () {
		self.y += self.speed;
		// Floating animation
		self.x += Math.sin(LK.ticks * 0.05) * 1;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Save the current game state
function saveGame() {
	storage.set('saveSpace_level', gameLevel);
	storage.set('saveSpace_score', scoreValue);
	storage.set('saveSpace_hearts', currentHearts);
	storage.set('saveSpace_oil', oilPercentage);
}
// Load the saved game state
function loadGame() {
	var savedLevel = storage.get('saveSpace_level', 1);
	var savedScore = storage.get('saveSpace_score', 0);
	var savedHearts = storage.get('saveSpace_hearts', 10);
	var savedOil = storage.get('saveSpace_oil', 20);
	gameLevel = savedLevel;
	scoreValue = savedScore;
	currentHearts = savedHearts;
	oilPercentage = savedOil;
	// Update UI elements
	levelTxt.setText('Level: ' + gameLevel);
	scoreTxt.setText('Score: ' + scoreValue);
	oilTxt.setText('Oil: ' + oilPercentage + '/' + maxOilPercentage);
	updateHearts();
	// Set game difficulty based on loaded level
	difficultyMultiplier = 1.0 + gameLevel * 0.15;
	enemySpawnRate = Math.max(60, Math.floor(240 / difficultyMultiplier));
	asteroidSpawnRate = Math.max(45, Math.floor(90 / difficultyMultiplier));
	oilFoodSpawnRate = Math.min(600, Math.floor(360 * (1 + gameLevel * 0.1)));
}
// Auto-save every minute
LK.setInterval(saveGame, 60000);
// Save when player takes damage
var originalHit = PlayerShip.prototype.hit;
PlayerShip.prototype.hit = function () {
	var result = originalHit.apply(this, arguments);
	if (result) {
		saveGame();
	}
	return result;
};
// Save on level up
var originalCheckLevelProgress = checkLevelProgress;
checkLevelProgress = function checkLevelProgress() {
	var oldLevel = gameLevel;
	originalCheckLevelProgress.apply(this, arguments);
	if (gameLevel > oldLevel) {
		saveGame();
	}
};
// Try to load saved game at start
loadGame();
game.setBackgroundColor(0x0c1445);
// Game variables
var player;
var playerBullets = [];
var enemies = [];
var bossEnemies = []; // Track boss enemies separately
var enemyBullets = [];
var asteroids = [];
var powerups = [];
var hearts = [];
var oilFoods = []; // Array to track oil foods
var heartsContainer;
var maxHearts = 10;
var currentHearts = 10;
var gameLevel = 1;
var enemySpawnRate = 240; // Reduced enemy spawn rate to focus on dodging asteroids
var asteroidSpawnRate = 90; // Increased asteroid spawn rate to create dodging challenge
var powerupSpawnRate = 900; // Every 15 seconds - rarer powerups
var bossSpawnRate = 600; // How often to check for boss spawn when at level 10
var newEnemySpawnRate = 180; // More frequent than regular enemies
var oilFoodSpawnRate = 360; // Every 6 seconds - slightly rarer
var gameState = "playing";
var scoreValue = 0;
var oilPercentage = 20; // Track oil percentage, starting at 20 out of 40
var maxOilPercentage = 40; // Maximum oil percentage
var powerupChance = 0.7; // 70% chance to actually spawn a powerup when the timer triggers
var difficultyMultiplier = 1.0; // Base difficulty multiplier that increases with level
// Setup score display
var scoreTxt = new Text2('Score: 0', {
	size: 60,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -300; // Offset from right edge
// Hearts display - text version as fallback
var livesTxt = new Text2('Hearts: 10/10', {
	size: 60,
	fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(livesTxt);
livesTxt.x = -300;
livesTxt.y = 70; // Below score text
// Function to update hearts display
function updateHearts() {
	for (var i = 0; i < hearts.length; i++) {
		hearts[i].setActive(i < currentHearts);
	}
	livesTxt.setText('Hearts: ' + currentHearts + '/' + maxHearts);
	// Game over condition
	if (currentHearts <= 0) {
		gameState = "over";
		LK.effects.flashScreen(0xff0000, 1000);
		LK.showGameOver();
	}
}
// Level display
var levelTxt = new Text2('Level: 1', {
	size: 60,
	fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -300;
levelTxt.y = 140; // Below lives text
// Oil percentage display
var oilTxt = new Text2('Oil: 20/40', {
	size: 60,
	fill: 0xFFFFFF
});
oilTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(oilTxt);
oilTxt.x = -300;
oilTxt.y = 210; // Below level text
// Initialize player
function initializePlayer() {
	player = new PlayerShip();
	player.x = 2048 / 2;
	player.y = 2732 - 200;
	game.addChild(player);
	// Initialize hearts display
	initializeHearts();
}
// Initialize hearts display
function initializeHearts() {
	// Remove existing hearts if any
	if (heartsContainer) {
		heartsContainer.destroy();
		hearts = [];
	}
	// Create container for hearts
	heartsContainer = new Container();
	game.addChild(heartsContainer);
	heartsContainer.x = 100;
	heartsContainer.y = 100;
	// Create hearts
	currentHearts = maxHearts;
	for (var i = 0; i < maxHearts; i++) {
		var heart = new Heart();
		heart.x = i % 5 * 40;
		heart.y = Math.floor(i / 5) * 40;
		heart.setActive(true);
		hearts.push(heart);
		heartsContainer.addChild(heart);
	}
}
// Spawn enemy
function spawnEnemy() {
	var enemy = new Enemy();
	enemy.x = Math.random() * (2048 - 200) + 100;
	enemy.y = -100;
	enemy.speed = 2 + gameLevel * 0.5 * difficultyMultiplier; // Scale with difficulty multiplier
	enemy.shootChance = Math.min(0.05, 0.01 + gameLevel * 0.004); // Increase shoot chance with level
	enemy.health = 1 + Math.floor(gameLevel / 5); // Tougher enemies at higher levels
	enemies.push(enemy);
	game.addChild(enemy);
}
// Spawn asteroid
function spawnAsteroid() {
	// At level 2 and above, randomly spawn the deadly asteroid
	// Chance increases with level
	if (gameLevel >= 2 && Math.random() < 0.2 + gameLevel * 0.03) {
		var deadlyAsteroid = new NewAsteroid();
		deadlyAsteroid.x = Math.random() * (2048 - 200) + 100;
		deadlyAsteroid.y = -100;
		deadlyAsteroid.speed = 7 + gameLevel * 0.4; // Faster with level
		asteroids.push(deadlyAsteroid);
		game.addChild(deadlyAsteroid);
	} else {
		var asteroid = new Asteroid();
		asteroid.x = Math.random() * (2048 - 200) + 100;
		asteroid.y = -100;
		asteroid.speed = 3 + gameLevel * 0.3 * difficultyMultiplier; // Scale with difficulty multiplier
		asteroids.push(asteroid);
		game.addChild(asteroid);
	}
}
// Spawn power-up
function spawnPowerUp() {
	// Only spawn powerup based on chance - gets rarer with higher levels
	if (Math.random() < powerupChance - gameLevel * 0.05) {
		var powerup = new PowerUp();
		powerup.x = Math.random() * (2048 - 200) + 100;
		powerup.y = -100;
		powerups.push(powerup);
		game.addChild(powerup);
	}
}
// Spawn oil food
function spawnOilFood() {
	var oilFood = new OilFood();
	oilFood.x = Math.random() * (2048 - 200) + 100;
	oilFood.y = -100;
	oilFoods.push(oilFood);
	game.addChild(oilFood);
}
// Spawn bad oil
function spawnBadOil() {
	var badOil = new BadOil();
	badOil.x = Math.random() * (2048 - 200) + 100;
	badOil.y = -100;
	oilFoods.push(badOil);
	game.addChild(badOil);
}
// Spawn new enemy
function spawnNewEnemy() {
	var newEnemy = new NewEnemy();
	newEnemy.x = Math.random() * (2048 - 200) + 100;
	newEnemy.y = -100;
	newEnemy.speed = 3 + gameLevel * 0.5; // Increase speed with level
	enemies.push(newEnemy);
	game.addChild(newEnemy);
}
// Spawn boss enemy
function spawnBossEnemy() {
	// At level 10, spawn Earth-monster instead of regular boss
	var boss;
	if (gameLevel >= 10) {
		boss = new EarthMonster();
		// Create a special alert for Earth-monster
		var bossAlert = new Text2('EARTH-MONSTER INCOMING!', {
			size: 100,
			fill: 0x00FFFF
		});
	} else {
		boss = new BossEnemy();
		// Create a regular boss alert
		var bossAlert = new Text2('BOSS INCOMING!', {
			size: 100,
			fill: 0xFF0000
		});
	}
	boss.x = 2048 / 2;
	boss.y = -200;
	bossEnemies.push(boss);
	game.addChild(boss);
	bossAlert.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(bossAlert);
	// Fade out the alert after 2 seconds
	LK.setTimeout(function () {
		tween(bossAlert, {
			alpha: 0
		}, {
			duration: 1000,
			onComplete: function onComplete() {
				bossAlert.destroy();
			}
		});
	}, 2000);
}
// Fire player bullet
function firePlayerBullet() {
	if (player && player.canFire()) {
		var bullet = new PlayerBullet();
		bullet.x = player.x;
		bullet.y = player.y - 50;
		playerBullets.push(bullet);
		game.addChild(bullet);
		LK.getSound('laser').play();
	}
}
// Fire enemy bullet
function fireEnemyBullet(enemy) {
	// Check if enemy is Earth-monster to create special bullets
	if (enemy instanceof EarthMonster) {
		// Earth-monster fires 5 bullets at once in a spread pattern
		for (var i = 0; i < 5; i++) {
			var bullet = new EarthMonsterBullet();
			// Position bullets in a spread pattern
			bullet.x = enemy.x + (i - 2) * 50; // -100, -50, 0, 50, 100 offset
			bullet.y = enemy.y + 50;
			enemyBullets.push(bullet);
			game.addChild(bullet);
		}
	} else {
		var bullet = new EnemyBullet();
		bullet.x = enemy.x;
		bullet.y = enemy.y + 50;
		enemyBullets.push(bullet);
		game.addChild(bullet);
	}
}
// Update score
function updateScore(points) {
	scoreValue += points;
	LK.setScore(scoreValue);
	scoreTxt.setText('Score: ' + scoreValue);
}
// Check level progression
function checkLevelProgress() {
	if (scoreValue >= gameLevel * 100) {
		gameLevel++;
		levelTxt.setText('Level: ' + gameLevel);
		// Increase difficulty multiplier
		difficultyMultiplier = 1.0 + gameLevel * 0.15;
		// Make game more difficult
		enemySpawnRate = Math.max(60, Math.floor(240 / difficultyMultiplier));
		asteroidSpawnRate = Math.max(45, Math.floor(90 / difficultyMultiplier));
		// Decrease oil food spawn rate
		oilFoodSpawnRate = Math.min(600, Math.floor(360 * (1 + gameLevel * 0.1)));
		// Make enemies faster and stronger via game update loop
		// Show level up message
		var levelUpTxt = new Text2('LEVEL ' + gameLevel + '!', {
			size: 100,
			fill: 0xFFFF00
		});
		levelUpTxt.anchor.set(0.5, 0.5);
		LK.gui.center.addChild(levelUpTxt);
		// Fade out the message after 1.5 seconds
		LK.setTimeout(function () {
			tween(levelUpTxt, {
				alpha: 0
			}, {
				duration: 800,
				onComplete: function onComplete() {
					levelUpTxt.destroy();
				}
			});
		}, 1500);
	}
}
// Drag handling
var isDragging = false;
function handleMove(x, y, obj) {
	if (isDragging && player) {
		// Constrain player to screen bounds
		player.x = Math.max(50, Math.min(2048 - 50, x));
		player.y = Math.max(50, Math.min(2732 - 50, y));
	}
}
game.move = handleMove;
game.down = function (x, y, obj) {
	isDragging = true;
	handleMove(x, y, obj);
	// Auto-fire when touching
	firePlayerBullet();
};
game.up = function (x, y, obj) {
	isDragging = false;
};
// Main game loop
game.update = function () {
	if (gameState !== "playing") {
		return;
	}
	// Spawn enemies - spawn multiple based on level
	if (LK.ticks % enemySpawnRate === 0) {
		// At higher levels, spawn multiple enemies at once
		var enemiesToSpawn = 1 + Math.floor(gameLevel / 3);
		for (var i = 0; i < enemiesToSpawn && i < 4; i++) {
			// Cap at 4 enemies per spawn
			spawnEnemy();
		}
	}
	// Spawn asteroids - more frequent at higher levels
	if (LK.ticks % asteroidSpawnRate === 0) {
		// At higher levels, spawn multiple asteroids
		var asteroidsToSpawn = 1 + Math.floor(gameLevel / 4);
		for (var i = 0; i < asteroidsToSpawn && i < 3; i++) {
			// Cap at 3 asteroids per spawn
			spawnAsteroid();
		}
	}
	// Spawn powerups - rare chance based on level
	if (LK.ticks % powerupSpawnRate === 0) {
		spawnPowerUp();
	}
	// Spawn oil food - less frequent at higher levels
	if (LK.ticks % oilFoodSpawnRate === 0) {
		spawnOilFood();
	}
	// Spawn bad oil - more frequent at higher levels
	if (LK.ticks % Math.max(180, 360 - gameLevel * 15) === 0) {
		spawnBadOil();
	}
	// Spawn boss enemies at level 5+ (earlier) and more frequently at level 10
	if (gameLevel >= 5 && gameLevel < 10 && LK.ticks % bossSpawnRate === 0 && bossEnemies.length < 1 || gameLevel >= 10 && LK.ticks % (bossSpawnRate / 2) === 0 && bossEnemies.length < 1) {
		spawnBossEnemy();
	}
	// Spawn new enemies at level 3 (earlier)
	if (gameLevel >= 3 && LK.ticks % Math.max(60, newEnemySpawnRate - gameLevel * 10) === 0) {
		spawnNewEnemy();
	}
	// Auto fire for enemies, not asteroids
	if (player && LK.ticks % 15 === 0) {
		firePlayerBullet();
	}
	// Update player bullets
	for (var i = playerBullets.length - 1; i >= 0; i--) {
		var bullet = playerBullets[i];
		// Remove bullets that go off screen
		if (bullet.y < -50) {
			bullet.destroy();
			playerBullets.splice(i, 1);
			continue;
		}
		// Check collisions with enemies
		for (var j = enemies.length - 1; j >= 0; j--) {
			var enemy = enemies[j];
			if (bullet.intersects(enemy)) {
				// Destroy enemy and bullet
				updateScore(enemy.scoreValue);
				LK.effects.flashObject(enemy, 0xff0000, 200);
				LK.getSound('explosion').play();
				enemy.destroy();
				enemies.splice(j, 1);
				bullet.destroy();
				playerBullets.splice(i, 1);
				checkLevelProgress();
				break;
			}
		}
		// Check collisions with boss enemies
		if (playerBullets[i]) {
			for (var j = bossEnemies.length - 1; j >= 0; j--) {
				var boss = bossEnemies[j];
				if (bullet.intersects(boss)) {
					// Damage boss
					boss.health--;
					LK.effects.flashObject(boss, 0xff0000, 200);
					// Destroy bullet
					bullet.destroy();
					playerBullets.splice(i, 1);
					// Check if boss is defeated
					if (boss.health <= 0) {
						updateScore(boss.scoreValue);
						LK.getSound('explosion').play();
						boss.destroy();
						bossEnemies.splice(j, 1);
						checkLevelProgress();
						// If it's Earth-monster, player wins
						if (boss instanceof EarthMonster) {
							// Display victory message
							var victoryTxt = new Text2('YOU DEFEATED THE EARTH-MONSTER!', {
								size: 80,
								fill: 0x00FF00
							});
							victoryTxt.anchor.set(0.5, 0.5);
							LK.gui.center.addChild(victoryTxt);
							// Game won
							gameState = "won";
							LK.effects.flashScreen(0x00FF00, 1000);
							LK.setTimeout(function () {
								LK.showYouWin();
							}, 2000);
						}
					}
					break;
				}
			}
		}
		// Check bullet collisions with asteroids
		if (playerBullets[i]) {
			for (var k = asteroids.length - 1; k >= 0; k--) {
				if (playerBullets[i].intersects(asteroids[k])) {
					// Destroy only the bullet when it hits an asteroid
					LK.effects.flashObject(playerBullets[i], 0xff0000, 200);
					playerBullets[i].destroy();
					playerBullets.splice(i, 1);
					break;
				}
			}
		}
	}
	// Update enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		// Remove bullets that go off screen
		if (bullet.y > 2732 + 50) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
			continue;
		}
		// Check collisions with player
		if (player && bullet.intersects(player)) {
			// Check if it's an Earth-monster bullet for 3x damage
			if (bullet instanceof EarthMonsterBullet) {
				// Apply damage three times for Earth-monster bullets
				for (var dmg = 0; dmg < 3; dmg++) {
					var hitSuccess = player.hit();
				}
				LK.effects.flashObject(player, 0x00ffff, 700); // Special effect for Earth-monster hit
			} else {
				// Regular bullet damage
				var hitSuccess = player.hit();
			}
			// Destroy bullet
			bullet.destroy();
			enemyBullets.splice(i, 1);
		}
	}
	// Update enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		// Remove enemies that go off screen
		if (enemy.y > 2732 + 50) {
			enemy.destroy();
			enemies.splice(i, 1);
			continue;
		}
		// Enemy shooting
		if (Math.random() < enemy.shootChance) {
			fireEnemyBullet(enemy);
		}
		// Check collisions with player
		if (player && enemy.intersects(player)) {
			// Player takes damage
			var hitSuccess = player.hit();
			// New collision behavior - check if it's a NewEnemy
			if (enemy instanceof NewEnemy) {
				// Always lose one heart for NewEnemy
				currentHearts--;
				updateHearts();
			}
			// Destroy enemy
			enemy.destroy();
			enemies.splice(i, 1);
			LK.getSound('explosion').play();
		}
	}
	// Update boss enemies
	for (var i = bossEnemies.length - 1; i >= 0; i--) {
		var boss = bossEnemies[i];
		// Remove boss that go off screen
		if (boss.y > 2732 + 50) {
			boss.destroy();
			bossEnemies.splice(i, 1);
			continue;
		}
		// Boss shooting (more frequent)
		if (Math.random() < boss.shootChance) {
			fireEnemyBullet(boss);
			// Boss shoots additional bullets in different directions
			if (Math.random() < 0.5) {
				var bulletLeft = new EnemyBullet();
				bulletLeft.x = boss.x - 50;
				bulletLeft.y = boss.y + 50;
				enemyBullets.push(bulletLeft);
				game.addChild(bulletLeft);
				var bulletRight = new EnemyBullet();
				bulletRight.x = boss.x + 50;
				bulletRight.y = boss.y + 50;
				enemyBullets.push(bulletRight);
				game.addChild(bulletRight);
			}
		}
		// Check collisions with player
		if (player && boss.intersects(player)) {
			// Player always takes damage from boss collision
			var hitSuccess = player.hit();
			// Boss is not destroyed on collision, just damaged
			boss.health--;
			LK.effects.flashObject(boss, 0xff0000, 200);
			if (boss.health <= 0) {
				updateScore(boss.scoreValue);
				boss.destroy();
				bossEnemies.splice(i, 1);
				LK.getSound('explosion').play();
			}
		}
	}
	// Update asteroids
	for (var i = asteroids.length - 1; i >= 0; i--) {
		var asteroid = asteroids[i];
		// Track if asteroid just passed the player
		if (asteroid.lastY < player.y - 100 && asteroid.y >= player.y - 100) {
			// Award points for successful dodge
			updateScore(10);
			checkLevelProgress();
		}
		// Remove asteroids that go off screen
		if (asteroid.y > 2732 + 50) {
			asteroid.destroy();
			asteroids.splice(i, 1);
			continue;
		}
		// Check collisions with player
		if (player && asteroid.intersects(player)) {
			// Check if it's a new deadly asteroid
			if (asteroid instanceof NewAsteroid) {
				// Game over immediately
				gameState = "over";
				LK.effects.flashScreen(0xff0000, 1000);
				LK.showGameOver();
			} else {
				// Regular asteroid - player takes damage
				var hitSuccess = player.hit();
			}
			// Destroy asteroid
			asteroid.destroy();
			asteroids.splice(i, 1);
			LK.getSound('explosion').play();
		}
	}
	// Update powerups
	for (var i = powerups.length - 1; i >= 0; i--) {
		var powerup = powerups[i];
		// Remove powerups that go off screen
		if (powerup.y > 2732 + 50) {
			powerup.destroy();
			powerups.splice(i, 1);
			continue;
		}
		// Check collisions with player
		if (player && powerup.intersects(player)) {
			// Apply powerup effect
			if (powerup.type === 0) {
				player.activateShield();
			} else {
				player.activateRapidFire();
			}
			// Destroy powerup
			powerup.destroy();
			powerups.splice(i, 1);
			LK.getSound('powerupCollect').play();
			updateScore(25); // Bonus points for collecting powerup
		}
	}
	// Update oil foods
	for (var i = oilFoods.length - 1; i >= 0; i--) {
		var oilFood = oilFoods[i];
		// Remove oil foods that go off screen
		if (oilFood.y > 2732 + 50) {
			oilFood.destroy();
			oilFoods.splice(i, 1);
			continue;
		}
		// Check collisions with player
		if (player && oilFood.intersects(player)) {
			// Check if it's a bad oil or good oil food
			if (oilFood instanceof BadOil) {
				// Decrease oil percentage by 10%
				oilPercentage -= 10;
				// Flash red to indicate bad effect
				LK.effects.flashObject(player, 0xff0000, 500);
			} else {
				// Increase oil percentage by 1%
				oilPercentage += 1;
				// Cap oil percentage at max value
				if (oilPercentage > maxOilPercentage) {
					oilPercentage = maxOilPercentage;
				}
			}
			oilTxt.setText('Oil: ' + oilPercentage + '/' + maxOilPercentage);
			// If player has no oil, enemies win
			if (oilPercentage <= 0) {
				// Display enemies win message
				var enemiesWinTxt = new Text2('ENEMIES WIN!', {
					size: 100,
					fill: 0xFF0000
				});
				enemiesWinTxt.anchor.set(0.5, 0.5);
				LK.gui.center.addChild(enemiesWinTxt);
				// Game over
				gameState = "over";
				LK.effects.flashScreen(0xff0000, 1000);
				LK.setTimeout(function () {
					LK.showGameOver();
				}, 2000);
			}
			// Destroy oil food
			oilFood.destroy();
			oilFoods.splice(i, 1);
		}
	}
};
// Create instructions text
var instructionsTxt = new Text2('DODGE THE ASTEROIDS TO SURVIVE!', {
	size: 80,
	fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionsTxt);
instructionsTxt.y = -150;
// Hide instructions after 5 seconds
LK.setTimeout(function () {
	tween(instructionsTxt, {
		alpha: 0
	}, {
		duration: 1000
	});
}, 5000);
// Initialize the game
initializePlayer();
// Set initial oil text
oilTxt.setText('Oil: ' + oilPercentage + '/' + maxOilPercentage);
// Play background music
LK.playMusic('bgmusic');
; ===================================================================
--- original.js
+++ change.js
@@ -332,9 +332,58 @@
 
 /**** 
 * Game Code
 ****/ 
-// Background
+// Save the current game state
+function saveGame() {
+	storage.set('saveSpace_level', gameLevel);
+	storage.set('saveSpace_score', scoreValue);
+	storage.set('saveSpace_hearts', currentHearts);
+	storage.set('saveSpace_oil', oilPercentage);
+}
+// Load the saved game state
+function loadGame() {
+	var savedLevel = storage.get('saveSpace_level', 1);
+	var savedScore = storage.get('saveSpace_score', 0);
+	var savedHearts = storage.get('saveSpace_hearts', 10);
+	var savedOil = storage.get('saveSpace_oil', 20);
+	gameLevel = savedLevel;
+	scoreValue = savedScore;
+	currentHearts = savedHearts;
+	oilPercentage = savedOil;
+	// Update UI elements
+	levelTxt.setText('Level: ' + gameLevel);
+	scoreTxt.setText('Score: ' + scoreValue);
+	oilTxt.setText('Oil: ' + oilPercentage + '/' + maxOilPercentage);
+	updateHearts();
+	// Set game difficulty based on loaded level
+	difficultyMultiplier = 1.0 + gameLevel * 0.15;
+	enemySpawnRate = Math.max(60, Math.floor(240 / difficultyMultiplier));
+	asteroidSpawnRate = Math.max(45, Math.floor(90 / difficultyMultiplier));
+	oilFoodSpawnRate = Math.min(600, Math.floor(360 * (1 + gameLevel * 0.1)));
+}
+// Auto-save every minute
+LK.setInterval(saveGame, 60000);
+// Save when player takes damage
+var originalHit = PlayerShip.prototype.hit;
+PlayerShip.prototype.hit = function () {
+	var result = originalHit.apply(this, arguments);
+	if (result) {
+		saveGame();
+	}
+	return result;
+};
+// Save on level up
+var originalCheckLevelProgress = checkLevelProgress;
+checkLevelProgress = function checkLevelProgress() {
+	var oldLevel = gameLevel;
+	originalCheckLevelProgress.apply(this, arguments);
+	if (gameLevel > oldLevel) {
+		saveGame();
+	}
+};
+// Try to load saved game at start
+loadGame();
 game.setBackgroundColor(0x0c1445);
 // Game variables
 var player;
 var playerBullets = [];
:quality(85)/https://cdn.frvr.ai/680ade0499a163a8ea9c1750.png%3F3) 
 Rocky rock. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680adfd799a163a8ea9c1760.png%3F3) 
 A space ship with guns. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680ae14299a163a8ea9c177b.png%3F3) 
 A spaceship with weapons and four wings. Single Game Texture. In-Game asset. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680ae53a99a163a8ea9c17bc.png%3F3) 
 A spaceship with engines at the back and lots of mini spaceships next to the big one. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680ae7a999a163a8ea9c17c6.png%3F3) 
 Rocky green rock with green venom dripping off it. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680aeb76b54cc7f0ed85d30f.png%3F3) 
 Black oil dripping out a container. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680aeca3b54cc7f0ed85d31a.png%3F3) 
 Red oil floating in space with skulls flowing too. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680aef2db54cc7f0ed85d321.png%3F3) 
 Super scary earth with sharp teeth. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c0047cdb2650caf349aa1.png%3F3) 
 Energy ball. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows