User prompt
rubah kontrol player bisa bebas ke arah mana saja.
User prompt
hapus wave ganti endless game
User prompt
player auto menembak setiap 1 detik
User prompt
musuh bisa menembak kearah player
User prompt
enemy menembak secara bergantian
User prompt
kurangi jumlah musuh
User prompt
kurangi kecepatan gerakan player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat kontrol player lebih halus dan tidak terlalu cepat ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
reduce bullet appear
Code edit (1 edits merged)
Please save this source code
User prompt
Space Defender
Initial prompt
buat game mirip galaga atau space invander
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 3 }); bossGraphics.tint = 0x800080; // Purple tint for boss self.maxHealth = 20; self.health = self.maxHealth; self.speed = 1; self.direction = 1; self.shootTimer = 0; self.shootInterval = 30; // Shoot every 0.5 seconds self.specialAttackTimer = 0; self.specialAttackInterval = 180; // Special attack every 3 seconds self.points = 100; self.phase = 1; self.movementTimer = 0; self.lastShoot = 0; self.shotCount = 0; // Track number of shots fired self.update = function () { self.movementTimer++; // Movement pattern if (self.movementTimer < 120) { // Move horizontally self.x += self.direction * self.speed; if (self.x <= 150 || self.x >= 1900) { self.direction *= -1; } } else if (self.movementTimer < 180) { // Move down slightly self.y += 0.5; } else { // Reset movement cycle self.movementTimer = 0; } // Regular shooting self.shootTimer++; if (self.shootTimer >= self.shootInterval) { self.shootTimer = 0; self.shootAtPlayer(); } // Special attack self.specialAttackTimer++; if (self.specialAttackTimer >= self.specialAttackInterval) { self.specialAttackTimer = 0; self.specialAttack(); } }; self.shootAtPlayer = function () { // Create single bullet aimed at player var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 100; // Calculate direction towards player var deltaX = player.x - bullet.x; var deltaY = player.y - bullet.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); bullet.directionX = deltaX / distance * bullet.speed; bullet.directionY = deltaY / distance * bullet.speed; enemyBullets.push(bullet); game.addChild(bullet); // Increment shot count and check for death after 55 shots self.shotCount++; if (self.shotCount >= 55) { // Boss dies after 55 shots LK.setScore(LK.getScore() + 500); scoreText.setText('Score: ' + LK.getScore()); LK.getSound('bossDefeat').play(); self.destroy(); currentBoss = null; isBossFight = false; } }; self.specialAttack = function () { // Circular pattern of bullets for (var i = 0; i < 4; i++) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 50; var angle = i / 4 * Math.PI * 2; bullet.directionX = Math.cos(angle) * bullet.speed; bullet.directionY = Math.sin(angle) * bullet.speed; enemyBullets.push(bullet); game.addChild(bullet); // Increment shot count for each bullet self.shotCount++; } // Check for death after 55 total shots if (self.shotCount >= 55) { // Boss dies after 55 shots LK.setScore(LK.getScore() + 500); scoreText.setText('Score: ' + LK.getScore()); LK.getSound('bossDefeat').play(); self.destroy(); currentBoss = null; isBossFight = false; } }; self.takeDamage = function () { self.health--; if (self.health <= 0) { // Boss defeated - give big score bonus LK.setScore(LK.getScore() + 500); scoreText.setText('Score: ' + LK.getScore()); LK.getSound('enemyHit').play(); self.destroy(); currentBoss = null; return true; // Boss destroyed } return false; // Boss still alive }; 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 = 2; self.direction = 1; self.moveDownDistance = 60; self.shootChance = 0.001; self.points = 10; self.health = 1; self.maxHealth = 1; self.lastShoot = 0; self.update = function () { self.y += self.speed; }; self.moveDown = function () { self.y += self.moveDownDistance; self.direction *= -1; }; self.takeDamage = function () { self.health--; if (self.health <= 0) { // Mark enemy as dying to prevent further damage self.isDying = true; // Flash screen red when enemy explodes LK.effects.flashScreen(0xFF0000, 150); // Enemy explodes - dramatic visual effect tween(self, { tint: 0xFF0000, scaleX: 2.5, scaleY: 2.5, alpha: 0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { // Mark for removal after animation self.readyForDestroy = true; } }); return true; // Enemy destroyed } else { // Add red flash effect for damage tween(self, { tint: 0xFF0000 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { tint: 0xFFFFFF }, { duration: 200, easing: tween.easeIn }); } }); } return false; // Enemy still alive }; 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.directionX = 0; self.directionY = self.speed; self.update = function () { self.x += self.directionX; self.y += self.directionY; }; return self; }); var LifePowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('lifePowerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.type = 'life'; self.update = function () { self.y += self.speed; self.rotation += 0.1; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.lastShoot = 0; self.shootDelay = 15; self.lives = 3; self.invulnerable = false; self.invulnerableTime = 0; self.shoot = function () { if (LK.ticks - self.lastShoot > self.shootDelay) { // Create three bullets in a spread pattern for (var i = 0; i < 3; i++) { var bullet = new PlayerBullet(); bullet.x = self.x + (i - 1) * 30; // Spread bullets horizontally: -30, 0, +30 bullet.y = self.y - 40; playerBullets.push(bullet); game.addChild(bullet); } self.lastShoot = LK.ticks; LK.getSound('shoot').play(); } }; self.takeDamage = function () { if (!self.invulnerable) { self.lives--; self.invulnerable = true; self.invulnerableTime = LK.ticks + 120; // 2 seconds of invulnerability LK.getSound('playerHit').play(); livesText.setText('Lives: ' + self.lives); if (self.lives <= 0) { LK.showGameOver(); } } }; self.update = function () { if (self.invulnerable && LK.ticks > self.invulnerableTime) { self.invulnerable = false; } }; 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 = -18; self.update = function () { self.y += self.speed; }; 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 = 'rapidfire'; // Default type self.update = function () { self.y += self.speed; self.rotation += 0.1; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ // Create static background var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(background); var player = new Player(); player.x = 1024; player.y = 2500; game.addChild(player); var playerBullets = []; var enemyBullets = []; var enemies = []; var powerups = []; var lifePowerups = []; var enemySpawnTimer = 0; var enemySpawnInterval = 120; // Spawn enemy every 2 seconds (120 ticks at 60fps) var maxEnemies = 12; // Maximum enemies on screen at once var dragNode = null; var rapidFireEndTime = 0; var currentShootingEnemyIndex = 0; var enemyShootTimer = 0; var enemyShootInterval = 90; // Shoot every 1.5 seconds (90 ticks at 60fps) var playerAutoShootTimer = 0; var playerAutoShootInterval = 60; // Auto shoot every 1 second (60 ticks at 60fps) var currentLevel = 1; var enemiesKilledThisLevel = 0; var enemiesNeededForNextLevel = 10; // UI Elements var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); scoreText.x = 50; scoreText.y = 50; LK.gui.topLeft.addChild(scoreText); var livesText = new Text2('Lives: 3', { size: 80, fill: 0xFFFFFF }); livesText.anchor.set(1, 0); LK.gui.topRight.addChild(livesText); var levelText = new Text2('Level: 1', { size: 60, fill: 0x00FF00 }); levelText.anchor.set(0.5, 0); levelText.x = 1024; levelText.y = 100; LK.gui.top.addChild(levelText); var levelChangeNotice = new Text2('', { size: 100, fill: 0xFFD700 }); levelChangeNotice.anchor.set(0.5, 0.5); levelChangeNotice.x = 1024; levelChangeNotice.y = 1366; levelChangeNotice.alpha = 0; LK.gui.center.addChild(levelChangeNotice); function spawnEnemy() { if (enemies.length < maxEnemies) { var enemy = new Enemy(); enemy.x = Math.random() * (2048 - 120) + 60; // Random X position enemy.y = -60; // Start above screen // Increase difficulty based on level enemy.speed = 2 + Math.random() * 3 + (currentLevel - 1) * 0.5; // Speed increases with level enemy.shootChance = 0.001 + (currentLevel - 1) * 0.0005; // Shooting frequency increases enemy.health = 1 + Math.floor((currentLevel - 1) / 3); // Health increases every 3 levels enemy.maxHealth = enemy.health; enemy.points = 10 + (currentLevel - 1) * 2; // More points per level enemies.push(enemy); game.addChild(enemy); } } // Play background music when game starts LK.playMusic('1battlefieldepic'); function handleTouch(x, y, obj) { // Allow free movement in all directions within screen bounds var targetX = Math.max(40, Math.min(2008, x)); var targetY = Math.max(40, Math.min(2692, y)); // Stop any existing movement tween tween.stop(player, { x: true, y: true }); // Slower and more controlled movement to target position tween(player, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut }); } game.move = handleTouch; game.down = function (x, y, obj) { // Move player to touch position immediately handleTouch(x, y, obj); player.shoot(); }; game.up = function (x, y, obj) { // Continue moving to last touch position on release handleTouch(x, y, obj); }; game.update = function () { // Static background - no scrolling logic needed // Check if rapid fire is active var isRapidFire = LK.ticks < rapidFireEndTime; if (isRapidFire) { player.shootDelay = 5; } else { player.shootDelay = 15; } // Auto shoot every 1 second playerAutoShootTimer++; if (playerAutoShootTimer >= playerAutoShootInterval) { playerAutoShootTimer = 0; player.shoot(); } // Update 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 >= -10 && bullet.y < -10) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check collision with enemies var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { if (bullet.intersects(enemies[j]) && !enemies[j].isDying) { var enemyDestroyed = enemies[j].takeDamage(); if (enemyDestroyed) { LK.setScore(LK.getScore() + enemies[j].points); scoreText.setText('Score: ' + LK.getScore()); LK.getSound('enemyHit').play(); enemiesKilledThisLevel++; // Check for level up if (enemiesKilledThisLevel >= enemiesNeededForNextLevel) { currentLevel++; enemiesKilledThisLevel = 0; enemiesNeededForNextLevel += 5; // Need 5 more enemies each level levelText.setText('Level: ' + currentLevel); // Show level change notice with animation levelChangeNotice.setText('LEVEL ' + currentLevel); levelChangeNotice.alpha = 0; tween(levelChangeNotice, { alpha: 1 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(levelChangeNotice, { alpha: 0 }, { duration: 1000, easing: tween.easeIn }); } }); } // Chance to drop power-up if (Math.random() < 0.1) { var powerup = new PowerUp(); powerup.x = enemies[j].x; powerup.y = enemies[j].y; powerups.push(powerup); game.addChild(powerup); } // Chance to drop life power-up (lower chance) if (Math.random() < 0.05) { var lifePowerup = new LifePowerUp(); lifePowerup.x = enemies[j].x; lifePowerup.y = enemies[j].y; lifePowerups.push(lifePowerup); game.addChild(lifePowerup); } // Don't destroy immediately - wait for animation } hitEnemy = true; break; } } if (hitEnemy) { bullet.destroy(); playerBullets.splice(i, 1); continue; } bullet.lastY = bullet.y; } // Update 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 <= 2742 && bullet.y > 2742) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } // Check collision with player if (bullet.intersects(player)) { player.takeDamage(); bullet.destroy(); enemyBullets.splice(i, 1); continue; } bullet.lastY = bullet.y; } // Handle alternating enemy shooting enemyShootTimer++; if (enemyShootTimer >= enemyShootInterval && enemies.length > 0) { // Reset timer enemyShootTimer = 0; // Find next valid enemy to shoot var attempts = 0; var maxAttempts = enemies.length; while (attempts < maxAttempts) { // Make sure index is within bounds if (currentShootingEnemyIndex >= enemies.length) { currentShootingEnemyIndex = 0; } var shootingEnemy = enemies[currentShootingEnemyIndex]; if (shootingEnemy && shootingEnemy.y < 2000) { // Only shoot if enemy is not too low // Create bullet from this enemy var bullet = new EnemyBullet(); bullet.x = shootingEnemy.x; bullet.y = shootingEnemy.y + 30; // Calculate direction towards player var deltaX = player.x - shootingEnemy.x; var deltaY = player.y - shootingEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // Normalize direction and apply speed bullet.directionX = deltaX / distance * bullet.speed; bullet.directionY = deltaY / distance * bullet.speed; enemyBullets.push(bullet); game.addChild(bullet); break; } // Move to next enemy currentShootingEnemyIndex = (currentShootingEnemyIndex + 1) % enemies.length; attempts++; } // Move to next enemy for next turn currentShootingEnemyIndex = (currentShootingEnemyIndex + 1) % enemies.length; } // Spawn new enemies continuously with level-based spawn rate enemySpawnTimer++; var adjustedSpawnInterval = Math.max(60, enemySpawnInterval - (currentLevel - 1) * 5); // Faster spawning at higher levels if (enemySpawnTimer >= adjustedSpawnInterval) { enemySpawnTimer = 0; spawnEnemy(); } // Update enemies and remove off-screen ones for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.lastY === undefined) enemy.lastY = enemy.y; // Remove enemies that finished exploding if (enemy.readyForDestroy) { enemy.destroy(); enemies.splice(i, 1); continue; } // Remove enemies that go off bottom of screen if (enemy.lastY <= 2800 && enemy.y > 2800) { enemy.destroy(); enemies.splice(i, 1); continue; } // Check if enemies reached player (only if not dying) if (enemy.y > 2300 && enemy.intersects(player) && !enemy.isDying) { player.takeDamage(); } enemy.lastY = enemy.y; } // Update power-ups for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (powerup.lastY === undefined) powerup.lastY = powerup.y; // Remove power-ups that go off screen if (powerup.lastY <= 2742 && powerup.y > 2742) { powerup.destroy(); powerups.splice(i, 1); continue; } // Check collision with player if (powerup.intersects(player)) { if (powerup.type === 'rapidfire') { rapidFireEndTime = LK.ticks + 300; // 5 seconds of rapid fire } LK.getSound('powerupCollect').play(); powerup.destroy(); powerups.splice(i, 1); continue; } powerup.lastY = powerup.y; } // Update life power-ups for (var i = lifePowerups.length - 1; i >= 0; i--) { var lifePowerup = lifePowerups[i]; if (lifePowerup.lastY === undefined) lifePowerup.lastY = lifePowerup.y; // Remove life power-ups that go off screen if (lifePowerup.lastY <= 2742 && lifePowerup.y > 2742) { lifePowerup.destroy(); lifePowerups.splice(i, 1); continue; } // Check collision with player if (lifePowerup.intersects(player)) { if (lifePowerup.type === 'life') { player.lives++; livesText.setText('Lives: ' + player.lives); } LK.getSound('powerupCollect').play(); lifePowerup.destroy(); lifePowerups.splice(i, 1); continue; } lifePowerup.lastY = lifePowerup.y; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
bossGraphics.tint = 0x800080; // Purple tint for boss
self.maxHealth = 20;
self.health = self.maxHealth;
self.speed = 1;
self.direction = 1;
self.shootTimer = 0;
self.shootInterval = 30; // Shoot every 0.5 seconds
self.specialAttackTimer = 0;
self.specialAttackInterval = 180; // Special attack every 3 seconds
self.points = 100;
self.phase = 1;
self.movementTimer = 0;
self.lastShoot = 0;
self.shotCount = 0; // Track number of shots fired
self.update = function () {
self.movementTimer++;
// Movement pattern
if (self.movementTimer < 120) {
// Move horizontally
self.x += self.direction * self.speed;
if (self.x <= 150 || self.x >= 1900) {
self.direction *= -1;
}
} else if (self.movementTimer < 180) {
// Move down slightly
self.y += 0.5;
} else {
// Reset movement cycle
self.movementTimer = 0;
}
// Regular shooting
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shootAtPlayer();
}
// Special attack
self.specialAttackTimer++;
if (self.specialAttackTimer >= self.specialAttackInterval) {
self.specialAttackTimer = 0;
self.specialAttack();
}
};
self.shootAtPlayer = function () {
// Create single bullet aimed at player
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 100;
// Calculate direction towards player
var deltaX = player.x - bullet.x;
var deltaY = player.y - bullet.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
bullet.directionX = deltaX / distance * bullet.speed;
bullet.directionY = deltaY / distance * bullet.speed;
enemyBullets.push(bullet);
game.addChild(bullet);
// Increment shot count and check for death after 55 shots
self.shotCount++;
if (self.shotCount >= 55) {
// Boss dies after 55 shots
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('bossDefeat').play();
self.destroy();
currentBoss = null;
isBossFight = false;
}
};
self.specialAttack = function () {
// Circular pattern of bullets
for (var i = 0; i < 4; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 50;
var angle = i / 4 * Math.PI * 2;
bullet.directionX = Math.cos(angle) * bullet.speed;
bullet.directionY = Math.sin(angle) * bullet.speed;
enemyBullets.push(bullet);
game.addChild(bullet);
// Increment shot count for each bullet
self.shotCount++;
}
// Check for death after 55 total shots
if (self.shotCount >= 55) {
// Boss dies after 55 shots
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('bossDefeat').play();
self.destroy();
currentBoss = null;
isBossFight = false;
}
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
// Boss defeated - give big score bonus
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('enemyHit').play();
self.destroy();
currentBoss = null;
return true; // Boss destroyed
}
return false; // Boss still alive
};
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 = 2;
self.direction = 1;
self.moveDownDistance = 60;
self.shootChance = 0.001;
self.points = 10;
self.health = 1;
self.maxHealth = 1;
self.lastShoot = 0;
self.update = function () {
self.y += self.speed;
};
self.moveDown = function () {
self.y += self.moveDownDistance;
self.direction *= -1;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
// Mark enemy as dying to prevent further damage
self.isDying = true;
// Flash screen red when enemy explodes
LK.effects.flashScreen(0xFF0000, 150);
// Enemy explodes - dramatic visual effect
tween(self, {
tint: 0xFF0000,
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mark for removal after animation
self.readyForDestroy = true;
}
});
return true; // Enemy destroyed
} else {
// Add red flash effect for damage
tween(self, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
return false; // Enemy still alive
};
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.directionX = 0;
self.directionY = self.speed;
self.update = function () {
self.x += self.directionX;
self.y += self.directionY;
};
return self;
});
var LifePowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('lifePowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.type = 'life';
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.lastShoot = 0;
self.shootDelay = 15;
self.lives = 3;
self.invulnerable = false;
self.invulnerableTime = 0;
self.shoot = function () {
if (LK.ticks - self.lastShoot > self.shootDelay) {
// Create three bullets in a spread pattern
for (var i = 0; i < 3; i++) {
var bullet = new PlayerBullet();
bullet.x = self.x + (i - 1) * 30; // Spread bullets horizontally: -30, 0, +30
bullet.y = self.y - 40;
playerBullets.push(bullet);
game.addChild(bullet);
}
self.lastShoot = LK.ticks;
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
if (!self.invulnerable) {
self.lives--;
self.invulnerable = true;
self.invulnerableTime = LK.ticks + 120; // 2 seconds of invulnerability
LK.getSound('playerHit').play();
livesText.setText('Lives: ' + self.lives);
if (self.lives <= 0) {
LK.showGameOver();
}
}
};
self.update = function () {
if (self.invulnerable && LK.ticks > self.invulnerableTime) {
self.invulnerable = false;
}
};
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 = -18;
self.update = function () {
self.y += self.speed;
};
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 = 'rapidfire'; // Default type
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Create static background
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
var player = new Player();
player.x = 1024;
player.y = 2500;
game.addChild(player);
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerups = [];
var lifePowerups = [];
var enemySpawnTimer = 0;
var enemySpawnInterval = 120; // Spawn enemy every 2 seconds (120 ticks at 60fps)
var maxEnemies = 12; // Maximum enemies on screen at once
var dragNode = null;
var rapidFireEndTime = 0;
var currentShootingEnemyIndex = 0;
var enemyShootTimer = 0;
var enemyShootInterval = 90; // Shoot every 1.5 seconds (90 ticks at 60fps)
var playerAutoShootTimer = 0;
var playerAutoShootInterval = 60; // Auto shoot every 1 second (60 ticks at 60fps)
var currentLevel = 1;
var enemiesKilledThisLevel = 0;
var enemiesNeededForNextLevel = 10;
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 50;
scoreText.y = 50;
LK.gui.topLeft.addChild(scoreText);
var livesText = new Text2('Lives: 3', {
size: 80,
fill: 0xFFFFFF
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
var levelText = new Text2('Level: 1', {
size: 60,
fill: 0x00FF00
});
levelText.anchor.set(0.5, 0);
levelText.x = 1024;
levelText.y = 100;
LK.gui.top.addChild(levelText);
var levelChangeNotice = new Text2('', {
size: 100,
fill: 0xFFD700
});
levelChangeNotice.anchor.set(0.5, 0.5);
levelChangeNotice.x = 1024;
levelChangeNotice.y = 1366;
levelChangeNotice.alpha = 0;
LK.gui.center.addChild(levelChangeNotice);
function spawnEnemy() {
if (enemies.length < maxEnemies) {
var enemy = new Enemy();
enemy.x = Math.random() * (2048 - 120) + 60; // Random X position
enemy.y = -60; // Start above screen
// Increase difficulty based on level
enemy.speed = 2 + Math.random() * 3 + (currentLevel - 1) * 0.5; // Speed increases with level
enemy.shootChance = 0.001 + (currentLevel - 1) * 0.0005; // Shooting frequency increases
enemy.health = 1 + Math.floor((currentLevel - 1) / 3); // Health increases every 3 levels
enemy.maxHealth = enemy.health;
enemy.points = 10 + (currentLevel - 1) * 2; // More points per level
enemies.push(enemy);
game.addChild(enemy);
}
}
// Play background music when game starts
LK.playMusic('1battlefieldepic');
function handleTouch(x, y, obj) {
// Allow free movement in all directions within screen bounds
var targetX = Math.max(40, Math.min(2008, x));
var targetY = Math.max(40, Math.min(2692, y));
// Stop any existing movement tween
tween.stop(player, {
x: true,
y: true
});
// Slower and more controlled movement to target position
tween(player, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut
});
}
game.move = handleTouch;
game.down = function (x, y, obj) {
// Move player to touch position immediately
handleTouch(x, y, obj);
player.shoot();
};
game.up = function (x, y, obj) {
// Continue moving to last touch position on release
handleTouch(x, y, obj);
};
game.update = function () {
// Static background - no scrolling logic needed
// Check if rapid fire is active
var isRapidFire = LK.ticks < rapidFireEndTime;
if (isRapidFire) {
player.shootDelay = 5;
} else {
player.shootDelay = 15;
}
// Auto shoot every 1 second
playerAutoShootTimer++;
if (playerAutoShootTimer >= playerAutoShootInterval) {
playerAutoShootTimer = 0;
player.shoot();
}
// Update 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 >= -10 && bullet.y < -10) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
if (bullet.intersects(enemies[j]) && !enemies[j].isDying) {
var enemyDestroyed = enemies[j].takeDamage();
if (enemyDestroyed) {
LK.setScore(LK.getScore() + enemies[j].points);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('enemyHit').play();
enemiesKilledThisLevel++;
// Check for level up
if (enemiesKilledThisLevel >= enemiesNeededForNextLevel) {
currentLevel++;
enemiesKilledThisLevel = 0;
enemiesNeededForNextLevel += 5; // Need 5 more enemies each level
levelText.setText('Level: ' + currentLevel);
// Show level change notice with animation
levelChangeNotice.setText('LEVEL ' + currentLevel);
levelChangeNotice.alpha = 0;
tween(levelChangeNotice, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(levelChangeNotice, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeIn
});
}
});
}
// Chance to drop power-up
if (Math.random() < 0.1) {
var powerup = new PowerUp();
powerup.x = enemies[j].x;
powerup.y = enemies[j].y;
powerups.push(powerup);
game.addChild(powerup);
}
// Chance to drop life power-up (lower chance)
if (Math.random() < 0.05) {
var lifePowerup = new LifePowerUp();
lifePowerup.x = enemies[j].x;
lifePowerup.y = enemies[j].y;
lifePowerups.push(lifePowerup);
game.addChild(lifePowerup);
}
// Don't destroy immediately - wait for animation
}
hitEnemy = true;
break;
}
}
if (hitEnemy) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Update 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 <= 2742 && bullet.y > 2742) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
player.takeDamage();
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Handle alternating enemy shooting
enemyShootTimer++;
if (enemyShootTimer >= enemyShootInterval && enemies.length > 0) {
// Reset timer
enemyShootTimer = 0;
// Find next valid enemy to shoot
var attempts = 0;
var maxAttempts = enemies.length;
while (attempts < maxAttempts) {
// Make sure index is within bounds
if (currentShootingEnemyIndex >= enemies.length) {
currentShootingEnemyIndex = 0;
}
var shootingEnemy = enemies[currentShootingEnemyIndex];
if (shootingEnemy && shootingEnemy.y < 2000) {
// Only shoot if enemy is not too low
// Create bullet from this enemy
var bullet = new EnemyBullet();
bullet.x = shootingEnemy.x;
bullet.y = shootingEnemy.y + 30;
// Calculate direction towards player
var deltaX = player.x - shootingEnemy.x;
var deltaY = player.y - shootingEnemy.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Normalize direction and apply speed
bullet.directionX = deltaX / distance * bullet.speed;
bullet.directionY = deltaY / distance * bullet.speed;
enemyBullets.push(bullet);
game.addChild(bullet);
break;
}
// Move to next enemy
currentShootingEnemyIndex = (currentShootingEnemyIndex + 1) % enemies.length;
attempts++;
}
// Move to next enemy for next turn
currentShootingEnemyIndex = (currentShootingEnemyIndex + 1) % enemies.length;
}
// Spawn new enemies continuously with level-based spawn rate
enemySpawnTimer++;
var adjustedSpawnInterval = Math.max(60, enemySpawnInterval - (currentLevel - 1) * 5); // Faster spawning at higher levels
if (enemySpawnTimer >= adjustedSpawnInterval) {
enemySpawnTimer = 0;
spawnEnemy();
}
// Update enemies and remove off-screen ones
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that finished exploding
if (enemy.readyForDestroy) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Remove enemies that go off bottom of screen
if (enemy.lastY <= 2800 && enemy.y > 2800) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check if enemies reached player (only if not dying)
if (enemy.y > 2300 && enemy.intersects(player) && !enemy.isDying) {
player.takeDamage();
}
enemy.lastY = enemy.y;
}
// Update power-ups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.lastY === undefined) powerup.lastY = powerup.y;
// Remove power-ups that go off screen
if (powerup.lastY <= 2742 && powerup.y > 2742) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with player
if (powerup.intersects(player)) {
if (powerup.type === 'rapidfire') {
rapidFireEndTime = LK.ticks + 300; // 5 seconds of rapid fire
}
LK.getSound('powerupCollect').play();
powerup.destroy();
powerups.splice(i, 1);
continue;
}
powerup.lastY = powerup.y;
}
// Update life power-ups
for (var i = lifePowerups.length - 1; i >= 0; i--) {
var lifePowerup = lifePowerups[i];
if (lifePowerup.lastY === undefined) lifePowerup.lastY = lifePowerup.y;
// Remove life power-ups that go off screen
if (lifePowerup.lastY <= 2742 && lifePowerup.y > 2742) {
lifePowerup.destroy();
lifePowerups.splice(i, 1);
continue;
}
// Check collision with player
if (lifePowerup.intersects(player)) {
if (lifePowerup.type === 'life') {
player.lives++;
livesText.setText('Lives: ' + player.lives);
}
LK.getSound('powerupCollect').play();
lifePowerup.destroy();
lifePowerups.splice(i, 1);
continue;
}
lifePowerup.lastY = lifePowerup.y;
}
};