User prompt
1- make background scroll faster 2- add 1 health point all enemies from the start 3- add hurt animation to all enemies ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
use 3 images and make them move downwards consecutively like a smooth animation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
1- make powerup spawn delay random between 12 to 16 2- add a space themed background image
User prompt
1- make powerup spawn delay random between 12 and 16 2- when an enemy reaches the bottom of the screen player will lose 1 healthpoint 3- make all enemies move a bit faster
User prompt
1- send ally spaceship from a random location when picked up 2- make tank enemy have 3 different attack types 3- make ally spaceship bigger 4- make tank enemy start move like zigzag enemy when stop ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
1- lower the chance of hearth drop when enemies die to 5 percent 2- add a supportship powerup that sends an ally spaceship horizontally from bottom to top and make it destroy all enemies exept tank enemy on its path ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a start screen music
User prompt
add a background music to the game
User prompt
1-change shield's explanation in the controls tab with "Prevents from taking damage" 2- make yellow transparent circles bigger and less transparent 3- make "tap to play" and "controls" as buttons and remove orange box beneath it
User prompt
1- change shield's explanation in the controls tab with "prevents from taking damage" 2- add transparent yellow circle as a background for spreadshot powerup image and shield powerup image ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
1- delete the rapidfire powerup 2- change the shield animation with a transparent blue circle bigger than player whenever shield powerup is taken 3- make the enemies drop a hearth with ten percent chance when destroyed 4- when player take the hearth refill 1 healthpoint of player 5- add explanations of powerups in the controls tab ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
1- add tank enemies hurt animation to all enemies 2-make spreadshot powerup shoot bullets into 3 different directions 3- display the tank enemies health bar at the topside of the screen when spawned ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
1- delete the speed powerup 2- add a spreadshot powerup that makes player shoot triple bullets 3- Make the white boxes 10 pixels wider 4- Make the white boxes metalic orange colour 5- drop down the enemy spawn rate 6- put the hearth symbols stand next to each other
User prompt
1- Make only 1 tank enemy appear every 5 wave and spawn it in the middle 2- show player's health with hearth shapes 3- every time a tank enemy show up show it's health with a bar on top of screen 4- increase all enemies health by 1 except tank enemy every 10 waves 5- increase tank enemies health by 2 every 5 wave 6- stop player shooting before the game start 7- player will stop shooting after the game over 8- add a white box background for the buttons in the start screen
User prompt
1- make player able to move horizontally 2- make a start screen and add a control explanation tab
User prompt
1- Make tank enemies appear only every five waves 2- Make tank enemies with 5 hitpoint 3- Make tank enemies stop when reaching horizontal mid lenght 4- Make zigzag enemies start appear after wave 2 5- Make bomber enemies start appearing after wave 3 6- Make fast enemies start appearing after wave 2 7- Make player have 3 hitpoints and show how much hitpoint left on top left corner
User prompt
make more type of enemies
Initial prompt
add some powerups
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BomberEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('bomberEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5;
self.shootTimer = 0;
self.shootDelay = 200 + Math.random() * 150; // Shoots less frequently but more bullets
self.update = function () {
self.y += self.speed;
// Bomber enemy shooting logic - shoots in spread pattern
self.shootTimer++;
if (self.shootTimer >= self.shootDelay && self.y > 100 && self.y < 2500) {
// Shoot 5 bullets in spread pattern
for (var i = -2; i <= 2; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 15;
bullet.y = self.y + 30;
// Add slight angle to bullets for spread
bullet.angleOffset = i * 0.1;
enemyBullets.push(bullet);
game.addChild(bullet);
}
self.shootTimer = 0;
self.shootDelay = 150 + Math.random() * 200;
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.shootTimer = 0;
self.shootDelay = 120 + Math.random() * 120; // Random shoot delay
self.update = function () {
self.y += self.speed;
// Enemy shooting logic
self.shootTimer++;
if (self.shootTimer >= self.shootDelay && self.y > 100 && self.y < 2500) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 30;
enemyBullets.push(bullet);
game.addChild(bullet);
self.shootTimer = 0;
self.shootDelay = 60 + Math.random() * 180;
}
};
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.angleOffset = 0; // For spread shots
self.update = function () {
self.y += self.speed;
// Add horizontal movement for angled bullets
if (self.angleOffset !== 0) {
self.x += self.angleOffset * self.speed;
}
};
return self;
});
var FastEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.shootTimer = 0;
self.shootDelay = 80 + Math.random() * 60; // Shoots more frequently
self.update = function () {
self.y += self.speed;
// Fast enemy shooting logic
self.shootTimer++;
if (self.shootTimer >= self.shootDelay && self.y > 100 && self.y < 2500) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 20;
bullet.speed = 10; // Faster bullets
enemyBullets.push(bullet);
game.addChild(bullet);
self.shootTimer = 0;
self.shootDelay = 40 + Math.random() * 100;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootTimer = 0;
self.shootDelay = 15; // Auto-fire rate
self.update = function () {
// Only shoot when game is playing
if (gameState !== 'playing') {
return;
}
// Use dynamic shoot delay from powerups
self.shootDelay = playerShootDelay;
// Auto-fire bullets
self.shootTimer++;
if (self.shootTimer >= self.shootDelay) {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 40;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
self.shootTimer = 0;
}
};
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 = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
self.type = 'speed'; // Will be set when created
self.speed = 3;
self.bobTimer = 0;
self.originalY = 0;
self.init = function (type) {
self.type = type;
var assetName = 'powerupSpeed';
if (type === 'rapidfire') assetName = 'powerupRapidFire';
if (type === 'shield') assetName = 'powerupShield';
var powerupGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.originalY = self.y;
};
self.update = function () {
self.y += self.speed;
// Add bobbing motion
self.bobTimer += 0.1;
if (self.originalY !== 0) {
self.y = self.originalY + self.speed * (LK.ticks - self.spawnTick) + Math.sin(self.bobTimer) * 5;
}
};
return self;
});
var TankEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('tankEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.shootTimer = 0;
self.shootDelay = 180 + Math.random() * 120; // Shoots less frequently
self.health = baseTankHealth + Math.floor(waveNumber / 5) * 2; // Increases by 2 every 5 waves
self.maxHealth = self.health;
self.stopped = false;
self.update = function () {
// Stop at horizontal mid length (around Y = 1366, which is half of 2732)
if (!self.stopped && self.y >= 1366) {
self.stopped = true;
self.speed = 0;
}
if (!self.stopped) {
self.y += self.speed;
}
// Visual feedback for damage
var healthRatio = self.health / self.maxHealth;
enemyGraphics.alpha = 0.4 + 0.6 * healthRatio;
// Tank enemy shooting logic - shoots 3 bullets at once
self.shootTimer++;
if (self.shootTimer >= self.shootDelay && self.y > 100 && self.y < 2500) {
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 25;
bullet.y = self.y + 35;
enemyBullets.push(bullet);
game.addChild(bullet);
}
self.shootTimer = 0;
self.shootDelay = 120 + Math.random() * 180;
}
};
return self;
});
var ZigzagEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('zigzagEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.shootTimer = 0;
self.shootDelay = 150 + Math.random() * 100;
self.zigzagTimer = 0;
self.zigzagSpeed = 3;
self.startX = 0; // Will be set when spawned
self.update = function () {
self.y += self.speed;
// Zigzag movement
self.zigzagTimer += 0.05;
self.x = self.startX + Math.sin(self.zigzagTimer) * 150;
// Shooting logic
self.shootTimer++;
if (self.shootTimer >= self.shootDelay && self.y > 100 && self.y < 2500) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 22;
enemyBullets.push(bullet);
game.addChild(bullet);
self.shootTimer = 0;
self.shootDelay = 80 + Math.random() * 120;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Game state
var gameState = 'start'; // 'start', 'playing', 'gameover'
var startScreen;
var controlsScreen;
var showingControls = false;
// Game variables
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var powerups = [];
var enemySpawnTimer = 0;
var enemySpawnDelay = 60;
var powerupSpawnTimer = 0;
var powerupSpawnDelay = 900; // 15 seconds at 60fps
var waveNumber = 1;
var difficultyTimer = 0;
var dragNode = null;
var tankSpawnedThisWave = false;
var currentTankEnemy = null;
// Player powerup states
var playerSpeed = 1;
var playerShootDelay = 15;
var playerShield = false;
var speedBoostTimer = 0;
var rapidFireTimer = 0;
var shieldTimer = 0;
// Player health system
var playerHealth = 3;
var maxPlayerHealth = 3;
// Enemy health scaling
var baseEnemyHealth = 1;
var baseTankHealth = 5;
// Initialize score display
var scoreTxt = new Text2('0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize wave display
var waveTxt = new Text2('Wave 1', {
size: 40,
fill: 0xFFFF00
});
waveTxt.anchor.set(1, 0);
waveTxt.x = -20;
waveTxt.y = 20;
LK.gui.topRight.addChild(waveTxt);
// Initialize health display with hearts
var healthHearts = [];
for (var h = 0; h < maxPlayerHealth; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = 140 + h * 50;
heart.y = 40;
healthHearts.push(heart);
LK.gui.topLeft.addChild(heart);
}
// Initialize tank health bar (hidden initially)
var tankHealthBarBg = LK.getAsset('tankHealthBar', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 20
});
tankHealthBarBg.x = 2048 / 2;
tankHealthBarBg.y = 60;
tankHealthBarBg.visible = false;
LK.gui.top.addChild(tankHealthBarBg);
var tankHealthBarFill = LK.getAsset('tankHealthBarFill', {
anchorX: 0.5,
anchorY: 0.5,
width: 396,
height: 16
});
tankHealthBarFill.x = 2048 / 2;
tankHealthBarFill.y = 60;
tankHealthBarFill.visible = false;
LK.gui.top.addChild(tankHealthBarFill);
// Create player
// Create start screen
startScreen = new Container();
var titleTxt = new Text2('SPACE DEFENDER', {
size: 120,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 2048 / 2;
titleTxt.y = 800;
startScreen.addChild(titleTxt);
var playBtnBg = LK.getAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 100
});
playBtnBg.x = 2048 / 2;
playBtnBg.y = 1200;
startScreen.addChild(playBtnBg);
var playBtn = new Text2('TAP TO PLAY', {
size: 80,
fill: 0x00FF00
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 2048 / 2;
playBtn.y = 1200;
startScreen.addChild(playBtn);
var controlsBtnBg = LK.getAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
width: 320,
height: 80
});
controlsBtnBg.x = 2048 / 2;
controlsBtnBg.y = 1350;
startScreen.addChild(controlsBtnBg);
var controlsBtn = new Text2('CONTROLS', {
size: 60,
fill: 0xFFFF00
});
controlsBtn.anchor.set(0.5, 0.5);
controlsBtn.x = 2048 / 2;
controlsBtn.y = 1350;
startScreen.addChild(controlsBtn);
var highScoreTxt = new Text2('High Score: ' + (storage.highScore || 0), {
size: 50,
fill: 0xCCCCCC
});
highScoreTxt.anchor.set(0.5, 0.5);
highScoreTxt.x = 2048 / 2;
highScoreTxt.y = 1500;
startScreen.addChild(highScoreTxt);
game.addChild(startScreen);
// Create controls screen
controlsScreen = new Container();
var controlsTitleTxt = new Text2('CONTROLS', {
size: 100,
fill: 0xFFFFFF
});
controlsTitleTxt.anchor.set(0.5, 0.5);
controlsTitleTxt.x = 2048 / 2;
controlsTitleTxt.y = 600;
controlsScreen.addChild(controlsTitleTxt);
var controlsInfo1 = new Text2('DRAG to move your ship left and right', {
size: 50,
fill: 0xCCCCCC
});
controlsInfo1.anchor.set(0.5, 0.5);
controlsInfo1.x = 2048 / 2;
controlsInfo1.y = 900;
controlsScreen.addChild(controlsInfo1);
var controlsInfo2 = new Text2('Your ship AUTOMATICALLY FIRES bullets', {
size: 50,
fill: 0xCCCCCC
});
controlsInfo2.anchor.set(0.5, 0.5);
controlsInfo2.x = 2048 / 2;
controlsInfo2.y = 1000;
controlsScreen.addChild(controlsInfo2);
var controlsInfo3 = new Text2('Destroy enemies and collect powerups', {
size: 50,
fill: 0xCCCCCC
});
controlsInfo3.anchor.set(0.5, 0.5);
controlsInfo3.x = 2048 / 2;
controlsInfo3.y = 1100;
controlsScreen.addChild(controlsInfo3);
var controlsInfo4 = new Text2('Survive as long as possible!', {
size: 50,
fill: 0x00FF00
});
controlsInfo4.anchor.set(0.5, 0.5);
controlsInfo4.x = 2048 / 2;
controlsInfo4.y = 1200;
controlsScreen.addChild(controlsInfo4);
var backBtn = new Text2('TAP TO GO BACK', {
size: 60,
fill: 0xFFFF00
});
backBtn.anchor.set(0.5, 0.5);
backBtn.x = 2048 / 2;
backBtn.y = 1400;
controlsScreen.addChild(backBtn);
controlsScreen.visible = false;
game.addChild(controlsScreen);
// Create player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 150;
// Initially hide game UI and player
player.visible = false;
scoreTxt.visible = false;
waveTxt.visible = false;
for (var h = 0; h < healthHearts.length; h++) {
healthHearts[h].visible = false;
}
tankHealthBarBg.visible = false;
tankHealthBarFill.visible = false;
// Game input handling
var playerTargetX = 2048 / 2; // Default center position
var isPlayerMoving = false;
function handleMove(x, y, obj) {
if (dragNode) {
var speed = playerSpeed;
playerTargetX = Math.max(80, Math.min(2048 - 80, x));
isPlayerMoving = true;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (gameState === 'start') {
if (!showingControls) {
// Check if controls button was tapped (approximate area)
if (y > 1300 && y < 1400) {
showingControls = true;
startScreen.visible = false;
controlsScreen.visible = true;
} else {
// Start game
gameState = 'playing';
startScreen.visible = false;
controlsScreen.visible = false;
player.visible = true;
scoreTxt.visible = true;
waveTxt.visible = true;
for (var h = 0; h < healthHearts.length; h++) {
healthHearts[h].visible = h < playerHealth;
}
}
} else {
// Go back from controls
showingControls = false;
startScreen.visible = true;
controlsScreen.visible = false;
}
} else if (gameState === 'playing') {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Only update game when playing
if (gameState !== 'playing') {
return;
}
// Update player horizontal movement
if (isPlayerMoving || Math.abs(player.x - playerTargetX) > 2) {
var speed = playerSpeed * 8; // Horizontal movement speed
var deltaX = playerTargetX - player.x;
player.x += deltaX * 0.2 * speed;
// Stop moving when close enough
if (Math.abs(deltaX) < 2) {
isPlayerMoving = false;
}
}
// Update powerup timers
if (speedBoostTimer > 0) {
speedBoostTimer--;
if (speedBoostTimer === 0) {
playerSpeed = 1;
}
}
if (rapidFireTimer > 0) {
rapidFireTimer--;
if (rapidFireTimer === 0) {
playerShootDelay = 15;
}
}
if (shieldTimer > 0) {
shieldTimer--;
if (shieldTimer === 0) {
playerShield = false;
player.alpha = 1.0;
} else {
// Shield visual effect
player.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.3);
}
}
// Update difficulty over time
difficultyTimer++;
if (difficultyTimer >= 1800) {
// Every 30 seconds at 60fps
waveNumber++;
waveTxt.setText('Wave ' + waveNumber);
enemySpawnDelay = Math.max(20, enemySpawnDelay - 5);
difficultyTimer = 0;
tankSpawnedThisWave = false; // Reset tank spawn for new wave
// Increase enemy health every 10 waves
if (waveNumber % 10 === 0) {
baseEnemyHealth++;
}
}
// Spawn powerups
powerupSpawnTimer++;
if (powerupSpawnTimer >= powerupSpawnDelay) {
var powerup = new Powerup();
var types = ['speed', 'rapidfire', 'shield'];
var randomType = types[Math.floor(Math.random() * types.length)];
powerup.x = 100 + Math.random() * (2048 - 200);
powerup.y = -50;
powerup.spawnTick = LK.ticks;
powerup.originalY = powerup.y;
powerup.init(randomType);
powerups.push(powerup);
game.addChild(powerup);
powerupSpawnTimer = 0;
powerupSpawnDelay = 600 + Math.random() * 600; // 10-20 seconds
}
// Spawn enemies
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnDelay) {
var enemy;
var spawnChance = Math.random();
var x = 100 + Math.random() * (2048 - 200);
var y = -50;
// Spawn different enemy types based on wave restrictions
var canSpawnFast = waveNumber >= 2;
var canSpawnZigzag = waveNumber >= 2;
var canSpawnBomber = waveNumber >= 3;
var canSpawnTank = waveNumber % 5 === 0 && !tankSpawnedThisWave; // Every 5 waves, only 1 per wave
if (canSpawnTank && spawnChance > 0.85) {
// Tank enemy only every 5 waves, spawn in middle
enemy = new TankEnemy();
enemy.speed = 0.8 + waveNumber * 0.15 + Math.random() * 1;
enemy.health = baseTankHealth + Math.floor(waveNumber / 5) * 2; // Update health based on wave
enemy.maxHealth = enemy.health;
x = 2048 / 2; // Spawn in middle
tankSpawnedThisWave = true;
currentTankEnemy = enemy;
// Show tank health bar
tankHealthBarBg.visible = true;
tankHealthBarFill.visible = true;
} else if (canSpawnBomber && spawnChance > 0.7 && spawnChance <= 0.85) {
// Bomber enemy after wave 3
enemy = new BomberEnemy();
enemy.speed = 1 + waveNumber * 0.25 + Math.random() * 1.5;
} else if (canSpawnZigzag && spawnChance > 0.55 && spawnChance <= 0.7) {
// Zigzag enemy after wave 2
enemy = new ZigzagEnemy();
enemy.startX = x;
enemy.speed = 1.5 + waveNumber * 0.2 + Math.random() * 1;
} else if (canSpawnFast && spawnChance > 0.4 && spawnChance <= 0.55) {
// Fast enemy after wave 2
enemy = new FastEnemy();
enemy.speed = 3 + waveNumber * 0.4 + Math.random() * 2;
} else {
// Basic enemy (always available)
enemy = new Enemy();
}
enemy.x = x;
enemy.y = y;
// Apply health scaling to all non-tank enemies
if (enemy.constructor !== TankEnemy) {
enemy.health = baseEnemyHealth;
enemy.maxHealth = baseEnemyHealth;
}
// Apply base speed increase for non-tank enemies
if (enemy.constructor !== TankEnemy && enemy.constructor !== ZigzagEnemy) {
enemy.speed = enemy.speed || 1 + waveNumber * 0.3 + Math.random() * 2;
}
enemies.push(enemy);
game.addChild(enemy);
enemySpawnTimer = 0;
}
// Update and check player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -30 && bullet.y < -30) {
bullet.destroy();
playerBullets.splice(i, 1);
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)) {
// Handle different enemy types
if (enemy.health !== undefined && enemy.health > 1) {
// Multi-health enemy - reduce health
enemy.health--;
LK.setScore(LK.getScore() + 5);
// Update tank health bar if this is the current tank
if (enemy === currentTankEnemy) {
var healthRatio = enemy.health / enemy.maxHealth;
tankHealthBarFill.scaleX = healthRatio;
}
if (enemy.health <= 0) {
var points = 15;
if (enemy.constructor === TankEnemy) {
points = 50;
currentTankEnemy = null;
tankHealthBarBg.visible = false;
tankHealthBarFill.visible = false;
}
LK.setScore(LK.getScore() + points);
enemy.destroy();
enemies.splice(j, 1);
}
} else {
// Regular enemy - destroy immediately
var points = 10;
if (enemy.constructor === FastEnemy) points = 15;else if (enemy.constructor === ZigzagEnemy) points = 20;else if (enemy.constructor === BomberEnemy) points = 25;
LK.setScore(LK.getScore() + points);
enemy.destroy();
enemies.splice(j, 1);
}
scoreTxt.setText(LK.getScore().toString());
LK.getSound('enemyHit').play();
bullet.destroy();
playerBullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (hitEnemy) continue;
bullet.lastY = bullet.y;
}
// Update and check enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2762 && bullet.y > 2762) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
if (playerShield) {
// Shield absorbs the bullet
LK.effects.flashObject(player, 0x0088ff, 300);
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
} else {
playerHealth--;
// Update heart display
for (var h = 0; h < healthHearts.length; h++) {
healthHearts[h].visible = h < playerHealth;
}
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 500);
bullet.destroy();
enemyBullets.splice(i, 1);
if (playerHealth <= 0) {
// Save high score
var currentScore = LK.getScore();
var highScore = storage.highScore || 0;
if (currentScore > highScore) {
storage.highScore = currentScore;
}
gameState = 'start';
startScreen.visible = true;
controlsScreen.visible = false;
showingControls = false;
// Reset game state
playerHealth = maxPlayerHealth;
waveNumber = 1;
waveTxt.setText('Wave 1');
tankSpawnedThisWave = false;
currentTankEnemy = null;
baseEnemyHealth = 1;
player.visible = false;
scoreTxt.visible = false;
waveTxt.visible = false;
for (var h = 0; h < healthHearts.length; h++) {
healthHearts[h].visible = false;
}
tankHealthBarBg.visible = false;
tankHealthBarFill.visible = false;
// Update high score display
highScoreTxt.setText('High Score: ' + (storage.highScore || 0));
LK.showGameOver();
return;
}
continue;
}
}
bullet.lastY = bullet.y;
}
// Update and check enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that go off screen
if (enemy.lastY <= 2762 && enemy.y > 2762) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
if (playerShield) {
// Shield destroys the enemy
LK.effects.flashObject(player, 0x0088ff, 300);
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore().toString());
enemy.destroy();
enemies.splice(i, 1);
continue;
} else {
playerHealth--;
// Update heart display
for (var h = 0; h < healthHearts.length; h++) {
healthHearts[h].visible = h < playerHealth;
}
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 500);
enemy.destroy();
enemies.splice(i, 1);
if (playerHealth <= 0) {
// Save high score
var currentScore = LK.getScore();
var highScore = storage.highScore || 0;
if (currentScore > highScore) {
storage.highScore = currentScore;
}
gameState = 'start';
startScreen.visible = true;
controlsScreen.visible = false;
showingControls = false;
// Reset game state
playerHealth = maxPlayerHealth;
waveNumber = 1;
waveTxt.setText('Wave 1');
tankSpawnedThisWave = false;
currentTankEnemy = null;
baseEnemyHealth = 1;
player.visible = false;
scoreTxt.visible = false;
waveTxt.visible = false;
for (var h = 0; h < healthHearts.length; h++) {
healthHearts[h].visible = false;
}
tankHealthBarBg.visible = false;
tankHealthBarFill.visible = false;
// Update high score display
highScoreTxt.setText('High Score: ' + (storage.highScore || 0));
LK.showGameOver();
return;
}
continue;
}
}
enemy.lastY = enemy.y;
}
// Update and check powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.lastY === undefined) powerup.lastY = powerup.y;
// Remove powerups that go off screen
if (powerup.lastY <= 2762 && powerup.y > 2762) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with player
if (powerup.intersects(player)) {
LK.getSound('powerup').play();
LK.effects.flashObject(player, 0x00ff00, 500);
// Apply powerup effect
if (powerup.type === 'speed') {
playerSpeed = 2.5;
speedBoostTimer = 600; // 10 seconds
} else if (powerup.type === 'rapidfire') {
playerShootDelay = 5;
rapidFireTimer = 600; // 10 seconds
} else if (powerup.type === 'shield') {
playerShield = true;
shieldTimer = 480; // 8 seconds
}
powerup.destroy();
powerups.splice(i, 1);
continue;
}
powerup.lastY = powerup.y;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -113,8 +113,12 @@
});
self.shootTimer = 0;
self.shootDelay = 15; // Auto-fire rate
self.update = function () {
+ // Only shoot when game is playing
+ if (gameState !== 'playing') {
+ return;
+ }
// Use dynamic shoot delay from powerups
self.shootDelay = playerShootDelay;
// Auto-fire bullets
self.shootTimer++;
@@ -177,10 +181,10 @@
});
self.speed = 1;
self.shootTimer = 0;
self.shootDelay = 180 + Math.random() * 120; // Shoots less frequently
- self.health = 5; // Takes multiple hits
- self.maxHealth = 5;
+ self.health = baseTankHealth + Math.floor(waveNumber / 5) * 2; // Increases by 2 every 5 waves
+ self.maxHealth = self.health;
self.stopped = false;
self.update = function () {
// Stop at horizontal mid length (around Y = 1366, which is half of 2732)
if (!self.stopped && self.y >= 1366) {
@@ -268,8 +272,10 @@
var powerupSpawnDelay = 900; // 15 seconds at 60fps
var waveNumber = 1;
var difficultyTimer = 0;
var dragNode = null;
+var tankSpawnedThisWave = false;
+var currentTankEnemy = null;
// Player powerup states
var playerSpeed = 1;
var playerShootDelay = 15;
var playerShield = false;
@@ -278,8 +284,11 @@
var shieldTimer = 0;
// Player health system
var playerHealth = 3;
var maxPlayerHealth = 3;
+// Enemy health scaling
+var baseEnemyHealth = 1;
+var baseTankHealth = 5;
// Initialize score display
var scoreTxt = new Text2('0', {
size: 60,
fill: 0xFFFFFF
@@ -294,17 +303,41 @@
waveTxt.anchor.set(1, 0);
waveTxt.x = -20;
waveTxt.y = 20;
LK.gui.topRight.addChild(waveTxt);
-// Initialize health display
-var healthTxt = new Text2('Health: 3', {
- size: 40,
- fill: 0xff0000
+// Initialize health display with hearts
+var healthHearts = [];
+for (var h = 0; h < maxPlayerHealth; h++) {
+ var heart = LK.getAsset('heart', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ heart.x = 140 + h * 50;
+ heart.y = 40;
+ healthHearts.push(heart);
+ LK.gui.topLeft.addChild(heart);
+}
+// Initialize tank health bar (hidden initially)
+var tankHealthBarBg = LK.getAsset('tankHealthBar', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 400,
+ height: 20
});
-healthTxt.anchor.set(0, 0);
-healthTxt.x = 120;
-healthTxt.y = 20;
-LK.gui.topLeft.addChild(healthTxt);
+tankHealthBarBg.x = 2048 / 2;
+tankHealthBarBg.y = 60;
+tankHealthBarBg.visible = false;
+LK.gui.top.addChild(tankHealthBarBg);
+var tankHealthBarFill = LK.getAsset('tankHealthBarFill', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 396,
+ height: 16
+});
+tankHealthBarFill.x = 2048 / 2;
+tankHealthBarFill.y = 60;
+tankHealthBarFill.visible = false;
+LK.gui.top.addChild(tankHealthBarFill);
// Create player
// Create start screen
startScreen = new Container();
var titleTxt = new Text2('SPACE DEFENDER', {
@@ -314,16 +347,34 @@
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 2048 / 2;
titleTxt.y = 800;
startScreen.addChild(titleTxt);
+var playBtnBg = LK.getAsset('buttonBg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 400,
+ height: 100
+});
+playBtnBg.x = 2048 / 2;
+playBtnBg.y = 1200;
+startScreen.addChild(playBtnBg);
var playBtn = new Text2('TAP TO PLAY', {
size: 80,
fill: 0x00FF00
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 2048 / 2;
playBtn.y = 1200;
startScreen.addChild(playBtn);
+var controlsBtnBg = LK.getAsset('buttonBg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 320,
+ height: 80
+});
+controlsBtnBg.x = 2048 / 2;
+controlsBtnBg.y = 1350;
+startScreen.addChild(controlsBtnBg);
var controlsBtn = new Text2('CONTROLS', {
size: 60,
fill: 0xFFFF00
});
@@ -399,9 +450,13 @@
// Initially hide game UI and player
player.visible = false;
scoreTxt.visible = false;
waveTxt.visible = false;
-healthTxt.visible = false;
+for (var h = 0; h < healthHearts.length; h++) {
+ healthHearts[h].visible = false;
+}
+tankHealthBarBg.visible = false;
+tankHealthBarFill.visible = false;
// Game input handling
var playerTargetX = 2048 / 2; // Default center position
var isPlayerMoving = false;
function handleMove(x, y, obj) {
@@ -427,9 +482,11 @@
controlsScreen.visible = false;
player.visible = true;
scoreTxt.visible = true;
waveTxt.visible = true;
- healthTxt.visible = true;
+ for (var h = 0; h < healthHearts.length; h++) {
+ healthHearts[h].visible = h < playerHealth;
+ }
}
} else {
// Go back from controls
showingControls = false;
@@ -490,8 +547,13 @@
waveNumber++;
waveTxt.setText('Wave ' + waveNumber);
enemySpawnDelay = Math.max(20, enemySpawnDelay - 5);
difficultyTimer = 0;
+ tankSpawnedThisWave = false; // Reset tank spawn for new wave
+ // Increase enemy health every 10 waves
+ if (waveNumber % 10 === 0) {
+ baseEnemyHealth++;
+ }
}
// Spawn powerups
powerupSpawnTimer++;
if (powerupSpawnTimer >= powerupSpawnDelay) {
@@ -518,13 +580,21 @@
// Spawn different enemy types based on wave restrictions
var canSpawnFast = waveNumber >= 2;
var canSpawnZigzag = waveNumber >= 2;
var canSpawnBomber = waveNumber >= 3;
- var canSpawnTank = waveNumber % 5 === 0; // Every 5 waves
+ var canSpawnTank = waveNumber % 5 === 0 && !tankSpawnedThisWave; // Every 5 waves, only 1 per wave
if (canSpawnTank && spawnChance > 0.85) {
- // Tank enemy only every 5 waves
+ // Tank enemy only every 5 waves, spawn in middle
enemy = new TankEnemy();
enemy.speed = 0.8 + waveNumber * 0.15 + Math.random() * 1;
+ enemy.health = baseTankHealth + Math.floor(waveNumber / 5) * 2; // Update health based on wave
+ enemy.maxHealth = enemy.health;
+ x = 2048 / 2; // Spawn in middle
+ tankSpawnedThisWave = true;
+ currentTankEnemy = enemy;
+ // Show tank health bar
+ tankHealthBarBg.visible = true;
+ tankHealthBarFill.visible = true;
} else if (canSpawnBomber && spawnChance > 0.7 && spawnChance <= 0.85) {
// Bomber enemy after wave 3
enemy = new BomberEnemy();
enemy.speed = 1 + waveNumber * 0.25 + Math.random() * 1.5;
@@ -542,8 +612,13 @@
enemy = new Enemy();
}
enemy.x = x;
enemy.y = y;
+ // Apply health scaling to all non-tank enemies
+ if (enemy.constructor !== TankEnemy) {
+ enemy.health = baseEnemyHealth;
+ enemy.maxHealth = baseEnemyHealth;
+ }
// Apply base speed increase for non-tank enemies
if (enemy.constructor !== TankEnemy && enemy.constructor !== ZigzagEnemy) {
enemy.speed = enemy.speed || 1 + waveNumber * 0.3 + Math.random() * 2;
}
@@ -566,14 +641,26 @@
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Handle different enemy types
- if (enemy.health !== undefined) {
- // Tank enemy - reduce health
+ if (enemy.health !== undefined && enemy.health > 1) {
+ // Multi-health enemy - reduce health
enemy.health--;
LK.setScore(LK.getScore() + 5);
+ // Update tank health bar if this is the current tank
+ if (enemy === currentTankEnemy) {
+ var healthRatio = enemy.health / enemy.maxHealth;
+ tankHealthBarFill.scaleX = healthRatio;
+ }
if (enemy.health <= 0) {
- LK.setScore(LK.getScore() + 15); // Bonus points for destroying tank
+ var points = 15;
+ if (enemy.constructor === TankEnemy) {
+ points = 50;
+ currentTankEnemy = null;
+ tankHealthBarBg.visible = false;
+ tankHealthBarFill.visible = false;
+ }
+ LK.setScore(LK.getScore() + points);
enemy.destroy();
enemies.splice(j, 1);
}
} else {
@@ -614,9 +701,12 @@
enemyBullets.splice(i, 1);
continue;
} else {
playerHealth--;
- healthTxt.setText('Health: ' + playerHealth);
+ // Update heart display
+ for (var h = 0; h < healthHearts.length; h++) {
+ healthHearts[h].visible = h < playerHealth;
+ }
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 500);
bullet.destroy();
enemyBullets.splice(i, 1);
@@ -630,12 +720,23 @@
gameState = 'start';
startScreen.visible = true;
controlsScreen.visible = false;
showingControls = false;
+ // Reset game state
+ playerHealth = maxPlayerHealth;
+ waveNumber = 1;
+ waveTxt.setText('Wave 1');
+ tankSpawnedThisWave = false;
+ currentTankEnemy = null;
+ baseEnemyHealth = 1;
player.visible = false;
scoreTxt.visible = false;
waveTxt.visible = false;
- healthTxt.visible = false;
+ for (var h = 0; h < healthHearts.length; h++) {
+ healthHearts[h].visible = false;
+ }
+ tankHealthBarBg.visible = false;
+ tankHealthBarFill.visible = false;
// Update high score display
highScoreTxt.setText('High Score: ' + (storage.highScore || 0));
LK.showGameOver();
return;
@@ -666,9 +767,12 @@
enemies.splice(i, 1);
continue;
} else {
playerHealth--;
- healthTxt.setText('Health: ' + playerHealth);
+ // Update heart display
+ for (var h = 0; h < healthHearts.length; h++) {
+ healthHearts[h].visible = h < playerHealth;
+ }
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 500);
enemy.destroy();
enemies.splice(i, 1);
@@ -682,12 +786,23 @@
gameState = 'start';
startScreen.visible = true;
controlsScreen.visible = false;
showingControls = false;
+ // Reset game state
+ playerHealth = maxPlayerHealth;
+ waveNumber = 1;
+ waveTxt.setText('Wave 1');
+ tankSpawnedThisWave = false;
+ currentTankEnemy = null;
+ baseEnemyHealth = 1;
player.visible = false;
scoreTxt.visible = false;
waveTxt.visible = false;
- healthTxt.visible = false;
+ for (var h = 0; h < healthHearts.length; h++) {
+ healthHearts[h].visible = false;
+ }
+ tankHealthBarBg.visible = false;
+ tankHealthBarFill.visible = false;
// Update high score display
highScoreTxt.setText('High Score: ' + (storage.highScore || 0));
LK.showGameOver();
return;
a spaceship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a blue shield. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Bomb shaped spaceship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a spaceship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
spaceship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a spaceship carrier from upside perspective. In-Game asset. 2d. High contrast. No shadows
pixelart heart. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
3 dot lines , aqua colour. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a 2D small space warship. In-Game asset. 2d. High contrast. No shadows
space theme background with stars and planets that are too far away,realistic. In-Game asset. 2d. High contrast. No shadows