User prompt
"Rotate the playerBullet's sprite/image to face left."
User prompt
undo
User prompt
"Rotate the playerBullet's sprite/image to face right."
User prompt
Rotate the enemyBullet's sprite/image to face left."
User prompt
undo
User prompt
"Rotate the enemyBullet's sprite/image to face right."
User prompt
undo
User prompt
"Rotate the enemyBullet direction to the right."
Remix started
Copy Space Defender
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var Asteroid = Container.expand(function () {
var self = Container.call(this);
// Random size asteroid
var size = Math.random() * 0.7 + 0.7; // 0.7 to 1.4
var asteroidGraphics = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size,
scaleY: size
});
self.health = 30 * size;
self.speed = 3 / size; // Bigger asteroids move slower
self.rotationSpeed = (Math.random() - 0.5) * 0.05;
self.points = Math.floor(50 * size);
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0x888888, 200);
LK.getSound('enemyShoot', {
volume: 0.5
}).play(); // Play hit sound
tween(asteroidGraphics, {
tint: 0xFFFFFF
}, {
duration: 50,
onFinish: function onFinish() {
asteroidGraphics.tint = 0x999999;
}
});
if (self.health <= 0) {
self.onDestroyed();
}
};
self.onDestroyed = function () {
// Add points to score
LK.setScore(LK.getScore() + self.points);
// Create explosion
var explosion = new Explosion(self.x, self.y, size);
game.addChild(explosion);
LK.getSound('explosion').play();
// Remove from game
var index = asteroids.indexOf(self);
if (index > -1) {
asteroids.splice(index, 1);
self.destroy();
}
};
self.update = function () {
self.y += self.speed;
asteroidGraphics.rotation += self.rotationSpeed;
// Check if asteroid is off-screen
if (self.y > 2732 + 100) {
var index = asteroids.indexOf(self);
if (index > -1) {
asteroids.splice(index, 1);
self.destroy();
}
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 500;
self.maxHealth = 500;
self.speed = 2;
self.points = 2000;
self.active = false;
self.phase = 1;
self.directionX = 1;
self.shootCooldown = 30;
self.specialAttackCooldown = 300;
// Health bar
self.healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
y: -150
});
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('enemyShoot', {
volume: 0.5
}).play(); // Play hit sound
tween(bossGraphics, {
tint: 0xFFFFFF
}, {
duration: 50,
onFinish: function onFinish() {
bossGraphics.tint = 0xff3300;
}
});
// Update health bar scale
self.healthBar.scaleX = Math.max(0, self.health / self.maxHealth);
// Phase transition at 50% health
if (self.health <= self.maxHealth / 2 && self.phase === 1) {
self.phase = 2;
self.speed = 4;
LK.effects.flashObject(self, 0xff00ff, 1000); // Purple flash for phase transition
}
if (self.health <= 0) {
self.onDestroyed();
}
};
self.onDestroyed = function () {
// Add points to score
LK.setScore(LK.getScore() + self.points);
// Create multiple explosions
for (var i = 0; i < 8; i++) {
var explosionX = self.x + (Math.random() * 300 - 150);
var explosionY = self.y + (Math.random() * 200 - 100);
var explosion = new Explosion(explosionX, explosionY, 2);
game.addChild(explosion);
// Stagger the explosions
(function (delay) {
LK.setTimeout(function () {
LK.getSound('explosion').play();
}, delay * 200);
})(i);
}
// Complete level
level++;
if (level > storage.level) {
storage.level = level;
}
// Check high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Show win screen
LK.showYouWin();
// Remove from game
var index = bosses.indexOf(self);
if (index > -1) {
bosses.splice(index, 1);
self.destroy();
}
};
self.shoot = function () {
// Basic attack - 3 bullets
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 80;
bullet.y = self.y + 100;
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
};
self.specialAttack = function () {
// Special attack based on phase
if (self.phase === 1) {
// Phase 1: Circle of 8 bullets
for (var i = 0; i < 8; i++) {
var angle = i / 8 * Math.PI * 2;
var bullet = new EnemyBullet();
bullet.x = self.x + Math.cos(angle) * 100;
bullet.y = self.y + Math.sin(angle) * 100;
bullet.directionX = Math.cos(angle);
bullet.directionY = Math.sin(angle);
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else {
// Phase 2: Targeted volley at player
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 100;
// Target the player
var dx = player.x - bullet.x;
var dy = player.y - bullet.y;
var dist = Math.sqrt(dx * dx + dy * dy);
bullet.directionX = dx / dist;
bullet.directionY = dy / dist;
bullet.speed = 8 + i;
game.addChild(bullet);
enemyBullets.push(bullet);
// Timeout was empty and served no purpose, bullet already added.
}
}
LK.getSound('enemyShoot').play();
};
self.update = function () {
if (!self.active) {
return;
}
// Movement
self.x += self.speed * self.directionX;
// Bounce at screen edges
if (self.x < 300) {
self.x = 300;
self.directionX = 1;
} else if (self.x > 2048 - 300) {
self.x = 2048 - 300;
self.directionX = -1;
}
// Regular attacks
self.shootCooldown--;
if (self.shootCooldown <= 0) {
self.shoot();
self.shootCooldown = self.phase === 1 ? 60 : 40;
}
// Special attacks
self.specialAttackCooldown--;
if (self.specialAttackCooldown <= 0) {
self.specialAttack();
self.specialAttackCooldown = 300;
}
};
self.activate = function () {
self.active = true;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 20;
self.speed = 2;
self.shootCooldown = Math.floor(Math.random() * 120) + 60;
self.points = 100;
self.movementPattern = "straight"; // Default movement pattern
self.directionX = 0;
self.directionChangeTimer = 0;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('enemyShoot', {
volume: 0.5
}).play(); // Play hit sound
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 50,
onFinish: function onFinish() {
enemyGraphics.tint = 0xff0000;
}
});
if (self.health <= 0) {
self.onDestroyed();
}
};
self.onDestroyed = function () {
// Add points to score
LK.setScore(LK.getScore() + self.points);
// Create explosion
var explosion = new Explosion(self.x, self.y, 1);
game.addChild(explosion);
LK.getSound('explosion').play();
// Increment enemies defeated count for level progression
enemiesDefeated++;
// Remove from game first
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
// Check if should drop powerup (20% chance) after removal is confirmed
if (Math.random() < 0.2) {
var powerup = new Powerup();
powerup.x = self.x;
powerup.y = self.y;
game.addChild(powerup);
powerups.push(powerup);
}
// Remove from game
self.destroy();
}
};
self.shoot = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 50;
game.addChild(bullet);
enemyBullets.push(bullet);
LK.getSound('enemyShoot').play();
};
self.setMovementPattern = function (pattern) {
self.movementPattern = pattern;
if (pattern === "zigzag") {
self.directionX = Math.random() < 0.5 ? -1 : 1;
self.speed = 3;
} else if (pattern === "circle") {
self.angle = Math.random() * Math.PI * 2;
self.centerX = self.x;
self.centerY = self.y;
self.radius = 100;
self.speed = 0.02;
} else if (pattern === "sine") {
self.startX = self.x;
self.amplitude = 150;
self.frequency = 0.01;
self.angle = Math.random() * Math.PI * 2;
}
};
self.update = function () {
// Movement based on pattern
if (self.movementPattern === "straight") {
self.y += self.speed;
} else if (self.movementPattern === "zigzag") {
self.y += self.speed;
self.x += self.speed * 2 * self.directionX;
self.directionChangeTimer++;
if (self.directionChangeTimer > 60) {
self.directionX *= -1;
self.directionChangeTimer = 0;
}
// Bounce off screen edges
if (self.x < 50) {
self.x = 50;
self.directionX = 1;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.directionX = -1;
}
} else if (self.movementPattern === "circle") {
self.angle += self.speed;
self.x = self.centerX + Math.cos(self.angle) * self.radius;
self.y = self.centerY + Math.sin(self.angle) * self.radius + self.speed * 20;
} else if (self.movementPattern === "sine") {
self.y += self.speed * 2;
self.angle += self.frequency;
self.x = self.startX + Math.sin(self.angle) * self.amplitude;
}
// Shooting
self.shootCooldown--;
if (self.shootCooldown <= 0) {
self.shoot();
self.shootCooldown = Math.floor(Math.random() * 120) + 120;
}
// Remove if off screen
if (self.y > 2732 + 100) {
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
self.destroy();
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.rotation = Math.PI * 1.5;
self.speed = 8;
self.damage = 10;
self.directionX = 0;
self.directionY = 1;
self.update = function () {
// Move based on direction
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Check if bullet is off-screen
if (self.y > 2732 + 50 || self.y < -50 || self.x < -50 || self.x > 2048 + 50) {
self.removeFromGame();
}
};
self.removeFromGame = function () {
var index = enemyBullets.indexOf(self);
if (index > -1) {
enemyBullets.splice(index, 1);
self.destroy();
}
};
return self;
});
var Explosion = Container.expand(function (x, y, size) {
var self = Container.call(this);
self.x = x;
self.y = y;
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size || 1,
scaleY: size || 1,
alpha: 0.9
});
// Animation for explosion
self.duration = 30; // 0.5 seconds at 60fps
self.timer = 0;
self.update = function () {
self.timer++;
// Scale up and fade out
var progress = self.timer / self.duration;
explosionGraphics.scaleX = (size || 1) * (1 + progress);
explosionGraphics.scaleY = (size || 1) * (1 + progress);
explosionGraphics.alpha = 1 - progress;
if (self.timer >= self.duration) {
self.destroy();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.speed = 15;
self.shootCooldown = 0;
self.invulnerable = false;
self.powerupTimer = 0;
self.powerupActive = false;
self.takeDamage = function (amount) {
if (self.invulnerable) {
return;
}
self.health -= amount;
LK.getSound('enemyShoot', {
volume: 0.7
}).play(); // Play player hit sound
if (self.health <= 0) {
self.health = 0;
self.onDestroyed();
} else {
// Flash player when hit
self.invulnerable = true;
LK.effects.flashObject(self, 0xffffff, 500);
// Screen shake on hit
LK.effects.flashScreen(0xFF0000, 300);
// Create small explosions around player for visual feedback
for (var i = 0; i < 3; i++) {
var explosionX = self.x + (Math.random() * 150 - 75);
var explosionY = self.y + (Math.random() * 150 - 75);
var smallExplosion = new Explosion(explosionX, explosionY, 0.5);
game.addChild(smallExplosion);
}
LK.setTimeout(function () {
self.invulnerable = false;
}, 1000);
}
};
self.applyPowerup = function () {
self.powerupActive = true;
self.powerupTimer = 300; // 5 seconds at 60fps
playerGraphics.tint = 0x00ff00; // Green tint for powered up
LK.getSound('powerup').play();
// Visual effect for power-up
tween(playerGraphics, {
alpha: 0.5,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playerGraphics, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Create a powerup aura
if (!self.powerupAura) {
self.powerupAura = LK.getAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
alpha: 0.3,
tint: 0x00FFAA
});
self.addChild(self.powerupAura);
} else {
self.powerupAura.alpha = 0.3;
}
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 70;
game.addChild(bullet);
bullets.push(bullet);
LK.getSound('playerShoot').play();
// If powered up, shoot 3 bullets instead of 1
if (self.powerupActive) {
var bulletLeft = new PlayerBullet();
bulletLeft.x = self.x - 40;
bulletLeft.y = self.y - 50;
var bulletRight = new PlayerBullet();
bulletRight.x = self.x + 40;
bulletRight.y = self.y - 50;
game.addChild(bulletLeft);
game.addChild(bulletRight);
bullets.push(bulletLeft);
bullets.push(bulletRight);
}
self.shootCooldown = self.powerupActive ? 10 : 15;
}
};
self.onDestroyed = function () {
var explosion = new Explosion(self.x, self.y, 2);
game.addChild(explosion);
LK.getSound('explosion').play();
// Show game over
LK.showGameOver();
};
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
if (self.powerupActive) {
self.powerupTimer--;
// Animate the powerup aura
if (self.powerupAura) {
self.powerupAura.rotation += 0.02;
// Pulse the aura
self.powerupAuraTime = (self.powerupAuraTime || 0) + 0.05;
self.powerupAura.alpha = 0.2 + Math.sin(self.powerupAuraTime) * 0.1;
self.powerupAura.scale.set(1.8 + Math.sin(self.powerupAuraTime) * 0.2);
}
// Warning animation when powerup is about to expire
if (self.powerupTimer < 60) {
// Flash the player when powerup is about to end
playerGraphics.alpha = 0.5 + Math.sin(self.powerupTimer * 0.2) * 0.5;
}
if (self.powerupTimer <= 0) {
self.powerupActive = false;
playerGraphics.alpha = 1;
// Remove powerup aura
if (self.powerupAura) {
self.powerupAura.destroy();
self.powerupAura = null;
}
// Reset powerup aura animation timer - Redundant as aura is destroyed
// self.powerupAuraTime = 0;
// The aura is already destroyed above, removing duplicate block.
}
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.rotation = Math.PI * 1.5;
self.speed = -15; // Move upwards
self.damage = 10;
self.update = function () {
self.y += self.speed;
// Check if bullet is off-screen
if (self.y < -50) {
self.removeFromGame();
}
};
self.removeFromGame = function () {
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
self.destroy();
}
};
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.pulsateTimer = 0;
self.update = function () {
self.y += self.speed;
// Pulsate effect
self.pulsateTimer += 0.05;
var scale = 1 + Math.sin(self.pulsateTimer) * 0.2;
powerupGraphics.scaleX = scale;
powerupGraphics.scaleY = scale;
powerupGraphics.alpha = 0.7 + Math.sin(self.pulsateTimer) * 0.3; // Pulsate alpha
// Remove if off screen
if (self.y > 2732 + 50) {
self.removeFromGame();
}
};
self.removeFromGame = function () {
var index = powerups.indexOf(self);
if (index > -1) {
powerups.splice(index, 1);
self.destroy();
}
};
self.alpha = 0;
self.scale.set(0.5);
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011 // Deep space blue
});
/****
* Game Code
****/
// Game state variables
var player;
var bullets = [];
var enemies = [];
var enemyBullets = [];
var asteroids = [];
var powerups = [];
var bosses = [];
var level = storage.level || 1;
var enemySpawnTimer = 0;
var asteroidSpawnTimer = 0;
var bossSpawned = false;
var gameStarted = false;
var levelEnemiesRequired;
var enemiesDefeated = 0;
var dragNode = null;
// Set up UI
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0); // Anchor top-right
scoreTxt.x = -20; // Padding from right edge
scoreTxt.y = 20; // Padding from top edge
LK.gui.topRight.addChild(scoreTxt);
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 60,
// Increased size
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0); // Anchor top-right
highScoreTxt.x = -20; // Align with scoreTxt padding
highScoreTxt.y = scoreTxt.y + scoreTxt.height + 10; // Position below scoreTxt
LK.gui.topRight.addChild(highScoreTxt);
var levelTxt = new Text2('Level: ' + level, {
size: 70,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0); // Anchor top-left now
LK.gui.topLeft.addChild(levelTxt);
levelTxt.x = 120; // Move slightly right from absolute left
levelTxt.y = 20; // Move slightly down from absolute top, matching score padding
// Add Glaud text
var glaudTxt = new Text2('Glaud', {
size: 40,
// Small size
fill: 0xFF8C00 // Orange color
});
glaudTxt.anchor.set(0, 0); // Anchor top-left
// Position below levelTxt
glaudTxt.x = levelTxt.x;
glaudTxt.y = levelTxt.y + levelTxt.height + 10; // 10px padding below
LK.gui.topLeft.addChild(glaudTxt);
var healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
scaleX: 1,
scaleY: 0.6
});
// Center the health bar horizontally relative to the bottom-center anchor
healthBar.x = 0;
// Position the bar slightly up from the absolute bottom edge
healthBar.y = -50;
LK.gui.bottom.addChild(healthBar);
var healthTxt = new Text2('Health', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 1); // Anchor bottom-center
// Position text centered horizontally, just above the health bar
healthTxt.x = healthBar.x;
healthTxt.y = healthBar.y - healthBar.height * healthBar.scaleY / 2 - 10;
LK.gui.bottom.addChild(healthTxt);
// Progress bar for level completion
var progressBarBg = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 0.4,
tint: 0x555555
});
progressBarBg.x = 2048 / 2;
progressBarBg.y = 100;
LK.gui.top.addChild(progressBarBg);
var progressBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
scaleX: 0,
scaleY: 0.3,
tint: 0x00FFFF
});
progressBar.x = 2048 / 2 - progressBarBg.width / 2;
progressBar.y = 100;
LK.gui.top.addChild(progressBar);
var progressTxt = new Text2('Progress', {
size: 50,
// Increased size
fill: 0xFFFFFF
});
progressTxt.anchor.set(0.5, 1); // Anchor bottom-center
progressTxt.x = progressBarBg.x;
// Position text above the background bar
progressTxt.y = progressBarBg.y - progressBarBg.height * progressBarBg.scaleY / 2 - 15;
LK.gui.top.addChild(progressTxt);
// Initialize player
function initPlayer() {
player = new Player();
player.x = 2048 / 2;
player.y = 2732 + 100; // Start off-screen
game.addChild(player);
// Animate player entrance
tween(player, {
y: 2732 - 200,
alpha: 1
}, {
duration: 1000,
easing: tween.easeOutBack
});
}
// Initialize level
function initLevel() {
// Clear any existing enemies and bullets
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].destroy();
}
for (var i = asteroids.length - 1; i >= 0; i--) {
asteroids[i].destroy();
}
for (var i = powerups.length - 1; i >= 0; i--) {
powerups[i].destroy();
}
for (var i = bosses.length - 1; i >= 0; i--) {
bosses[i].destroy();
}
enemies = [];
enemyBullets = [];
asteroids = [];
powerups = [];
bosses = [];
bossSpawned = false;
enemiesDefeated = 0;
// Set level difficulty
levelEnemiesRequired = level * 15;
enemySpawnTimer = 60;
asteroidSpawnTimer = 180;
// Update UI
levelTxt.setText('Level: ' + level);
// Stop pulsating effect on progress text if active
if (progressTxt.pulsating) {
tween.cancel(progressTxt.scale);
tween.cancel(progressTxt);
progressTxt.scale.set(1);
progressTxt.alpha = 1;
progressTxt.pulsating = false;
}
// Start music
LK.playMusic('bgMusic');
}
// Spawn enemy with random pattern
function spawnEnemy() {
var enemy = new Enemy();
// Random x position
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -100;
// Set health and pattern based on level
enemy.health = 20 + level * 5;
// Choose movement pattern
var patterns = ["straight", "zigzag", "sine"];
if (level >= 3) {
patterns.push("circle");
}
var pattern = patterns[Math.floor(Math.random() * patterns.length)];
enemy.setMovementPattern(pattern);
// Add spawn animation
enemy.alpha = 0;
enemy.scale.set(0.5);
game.addChild(enemy);
enemies.push(enemy);
// Animate entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOutBack
});
}
// Spawn asteroid
function spawnAsteroid() {
var asteroid = new Asteroid();
// Random x position
asteroid.x = Math.random() * (2048 - 200) + 100;
asteroid.y = -100;
game.addChild(asteroid);
asteroids.push(asteroid);
// Add entry animation
asteroid.alpha = 0.5;
tween(asteroid, {
alpha: 1,
rotation: Math.random() * Math.PI * 2
}, {
duration: 800,
easing: tween.easeOut
});
}
// Spawn boss
function spawnBoss() {
var boss = new Boss();
boss.x = 2048 / 2;
boss.y = 300;
// Adjust boss health based on level
boss.health = 500 + level * 100;
boss.maxHealth = boss.health;
game.addChild(boss);
bosses.push(boss);
LK.getSound('explosion', {
volume: 0.8
}).play(); // Play boss spawn sound
// Activate boss after entrance animation
tween(boss, {
y: 300
}, {
duration: 2000,
easing: tween.easeOutBack,
onFinish: function onFinish() {
boss.activate();
}
});
}
// Check collisions
function checkCollisions() {
// Player bullets vs enemies
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check against enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Create small impact effect
var impact = new Explosion(bullet.x, bullet.y, 0.3);
impact.duration = 15; // Shorter duration for impact
game.addChild(impact);
enemy.takeDamage(bullet.damage);
bullet.removeFromGame();
break;
}
}
// Check against asteroids
for (var j = asteroids.length - 1; j >= 0; j--) {
var asteroid = asteroids[j];
if (bullet.intersects(asteroid)) {
// Create small impact effect
var impact = new Explosion(bullet.x, bullet.y, 0.3);
impact.duration = 15; // Shorter duration for impact
game.addChild(impact);
asteroid.takeDamage(bullet.damage);
bullet.removeFromGame();
break;
}
}
// Check against bosses
for (var j = bosses.length - 1; j >= 0; j--) {
var boss = bosses[j];
if (bullet.intersects(boss) && boss.active) {
// Create small impact effect
var impact = new Explosion(bullet.x, bullet.y, 0.3);
impact.duration = 15; // Shorter duration for impact
game.addChild(impact);
boss.takeDamage(bullet.damage);
bullet.removeFromGame();
break;
}
}
}
// Enemy bullets vs player
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.intersects(player)) {
player.takeDamage(bullet.damage);
bullet.removeFromGame();
}
}
// Player vs enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
player.takeDamage(20);
enemy.takeDamage(enemy.health); // Destroy enemy
}
}
// Player vs asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
if (player.intersects(asteroid)) {
player.takeDamage(30);
asteroid.takeDamage(asteroid.health); // Destroy asteroid
}
}
// Player vs powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (player.intersects(powerup)) {
// Remove the powerup first to prevent potential multiple applications
powerup.removeFromGame();
// Then apply the effect
player.applyPowerup();
}
}
}
// Handle player movement
function handleDrag(x, y) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Constrain player to screen bounds
if (dragNode.x < 50) {
dragNode.x = 50;
}
if (dragNode.x > 2048 - 50) {
dragNode.x = 2048 - 50;
}
if (dragNode.y < 50) {
dragNode.y = 50;
}
if (dragNode.y > 2732 - 50) {
dragNode.y = 2732 - 50;
}
}
}
// Event handlers
game.down = function (x, y, obj) {
// Only set drag if we're started
if (gameStarted) {
dragNode = player;
handleDrag(x, y);
} else {
// Start game on first touch
gameStarted = true;
initPlayer();
initLevel();
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.move = function (x, y, obj) {
handleDrag(x, y);
};
// Main game update loop
game.update = function () {
if (!gameStarted) {
// Show start screen text
if (!game.startText) {
game.startText = new Text2('Tap to Start\nSpace Defender', {
size: 150,
fill: 0xFFFFFF
});
game.startText.anchor.set(0.5, 0.5);
game.startText.x = 2048 / 2;
game.startText.y = 2732 / 2;
game.addChild(game.startText);
// Add background stars for start screen
game.stars = [];
for (var i = 0; i < 50; i++) {
var star = LK.getAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: Math.random() * 0.3 + 0.1,
scaleY: Math.random() * 0.3 + 0.1,
alpha: Math.random() * 0.7 + 0.3,
tint: 0xFFFFFF
});
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.speed = Math.random() * 2 + 1;
game.addChild(star);
game.stars.push(star);
}
// Add pulsating effect to start text
game.pulseValue = 0;
// Add pulsing to the start text using tween
tween(game.startText, {
alpha: 0.5
}, {
duration: 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
// Animate stars in start screen
if (game.stars) {
// Manual scaling removed, handled by tween animation
// game.pulseValue += 0.05;
// game.startText.scale.set(1 + Math.sin(game.pulseValue) * 0.05);
for (var i = 0; i < game.stars.length; i++) {
var star = game.stars[i];
star.y += star.speed;
if (star.y > 2732) {
star.y = 0;
star.x = Math.random() * 2048;
}
}
}
return;
} else if (game.startText) {
game.startText.destroy();
game.startText = null;
// Clean up stars
if (game.stars) {
for (var i = 0; i < game.stars.length; i++) {
game.stars[i].destroy();
}
game.stars = null;
}
}
// Update UI
scoreTxt.setText('Score: ' + LK.getScore());
// Update high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('High Score: ' + storage.highScore);
}
// Update progress bar
if (!bossSpawned) {
var progress = enemiesDefeated / levelEnemiesRequired;
progressBar.scaleX = progress;
progressTxt.setText('Level Progress: ' + Math.floor(progress * 100) + '%');
} else {
progressTxt.setText('BOSS FIGHT!');
if (!progressTxt.pulsating) {
progressTxt.pulsating = true;
tween(progressTxt.scale, {
x: 1.2,
y: 1.2
}, {
duration: 300,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
tween(progressTxt, {
alpha: 0.5
}, {
duration: 300,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
}
progressBar.tint = 0xFF0000;
progressBar.scaleX = 1;
}
if (player) {
// Update health bar
healthBar.scaleX = Math.max(0, player.health / 100);
// Auto-fire
player.shoot();
}
// Spawn enemies
if (!bossSpawned) {
enemySpawnTimer--;
if (enemySpawnTimer <= 0) {
spawnEnemy();
// Spawn rate increases with level
enemySpawnTimer = Math.max(20, 100 - level * 10);
}
// Spawn asteroids
asteroidSpawnTimer--;
if (asteroidSpawnTimer <= 0) {
spawnAsteroid();
asteroidSpawnTimer = Math.max(60, 300 - level * 20);
}
// Check if we should spawn boss
if (enemiesDefeated >= levelEnemiesRequired) {
bossSpawned = true;
spawnBoss();
}
}
// Update all game objects
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].update();
}
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].update();
}
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].update();
}
for (var i = asteroids.length - 1; i >= 0; i--) {
asteroids[i].update();
}
for (var i = powerups.length - 1; i >= 0; i--) {
powerups[i].update();
}
for (var i = bosses.length - 1; i >= 0; i--) {
bosses[i].update();
}
// Check for collisions
checkCollisions();
};
// Start game music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
}); ===================================================================
--- original.js
+++ change.js
@@ -563,8 +563,9 @@
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
+ bulletGraphics.rotation = Math.PI * 1.5;
self.speed = -15; // Move upwards
self.damage = 10;
self.update = function () {
self.y += self.speed;
enemyBullet. In-Game asset. 2d. High contrast. No shadows
playerBullet. In-Game asset. 2d. High contrast. No shadows
powerup. In-Game asset. 2d. High contrast. No shadows
asteroid. In-Game asset. 2d. High contrast. No shadows
big boss spaceship. In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows
explosion. In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows
spaceship enemy. In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows