Code edit (1 edits merged)
Please save this source code
User prompt
don't let space between grounds and mountains
User prompt
Replace mountain with new assets topmountain and bottommountain
User prompt
Reduce it to 1min
User prompt
in each ground put mountain or groundEnemy. "no empty grounds"! Redus the time to change to space from 5min to 2min.
User prompt
Add continuous shooting for the UFO.
User prompt
Change groundEnemy shooting diagonal left and for airEnemy and the boss to shoot to the left.
Code edit (1 edits merged)
Please save this source code
User prompt
UFO Sky Gauntlet
Initial prompt
The game is about a Ufo moving in the air space to the right side the bottom and the top sides have moving grounds to the left side, there's enemies in both grounds shooting 3 shots no much time between shots, add some obstacles like mountains on the grounds time on top time on bottom, after a while like 5min shooting and dodging enemies there will be no grounds only space and respawning of chain of 7 enemies airships shooting and moving up and down like snake while shooting, at the last add a boss have laser gun and shooting by 5 directions on the UFO player.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Air Enemy Class (Snake Segment - Simplified for MVP) var AirEnemy = Container.expand(function (startX, startY) { var self = Container.call(this); var enemyGraphics = self.attachAsset('airEnemy', { anchorX: 0.5, anchorY: 0.5 }); self.x = startX; self.y = startY; self.speedX = 4 + Math.random() * 2; // Horizontal speed self.amplitudeY = 100 + Math.random() * 100; // Vertical movement range self.frequencyY = 0.01 + Math.random() * 0.01; // Vertical movement speed self.fireRate = 150; // Ticks between shots self.fireCooldown = Math.random() * self.fireRate; self.update = function () { // Basic horizontal and sinusoidal vertical movement self.x -= self.speedX; self.y = startY + Math.sin(LK.ticks * self.frequencyY + startX) * self.amplitudeY; // Use startX for phase offset // Firing logic self.fireCooldown++; if (self.fireCooldown >= self.fireRate) { self.fireCooldown = 0; // Fire a single bullet straight left var bulletSpeed = 8; fireEnemyBullet(self.x, self.y, -bulletSpeed, 0); // vx = -speed, vy = 0 } // Boundary check (simple respawn logic) if (self.x < -enemyGraphics.width) { self.x = 2048 + enemyGraphics.width; // Respawn on the right startY = Math.random() * (2732 - 400) + 200; // Random Y position } }; return self; }); // Boss Class (Basic structure for future) var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.x = 2048 - 300; // Position on the right self.y = 2732 / 2; // Center vertically self.fireRate = 180; // Ticks between laser bursts self.fireCooldown = 0; self.health = 100; // Example health self.update = function () { // Add movement logic if needed self.fireCooldown++; if (self.fireCooldown >= self.fireRate) { self.fireCooldown = 0; fireBossLasers(self.x, self.y); } }; return self; }); // Boss Laser Class (Basic structure for future) var BossLaser = Container.expand(function (startX, startY, vx, vy) { var self = Container.call(this); var laserGraphics = self.attachAsset('bossLaser', { anchorX: 0.5, anchorY: 0.5 // Anchor center }); self.x = startX; self.y = startY; self.vx = vx; self.vy = vy; // Set rotation based on velocity direction self.rotation = Math.atan2(vy, vx) + Math.PI / 2; // Point laser in direction of travel (+90deg adjustment needed depending on asset orientation) self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Enemy Bullet Class var EnemyBullet = Container.expand(function (startX, startY, vx, vy) { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.x = startX; self.y = startY; self.vx = vx; // Horizontal velocity self.vy = vy; // Vertical velocity self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Ground Enemy Class var GroundEnemy = Container.expand(function (isTop) { var self = Container.call(this); var enemyGraphics = self.attachAsset('groundEnemy', { anchorX: 0.5, anchorY: isTop ? 0 : 1 // Anchor base at terrain edge }); self.isTop = isTop; self.speed = 5; // Should match terrain speed self.fireRate = 120; // Ticks between firing sequences (2 seconds) self.fireCooldown = Math.random() * self.fireRate; // Random initial delay self.shotsInBurst = 3; self.burstDelay = 10; // Ticks between shots in a burst self.update = function () { self.x -= self.speed; self.fireCooldown++; if (self.fireCooldown >= self.fireRate) { self.fireCooldown = 0; // Reset cooldown // Fire burst for (var i = 0; i < self.shotsInBurst; i++) { LK.setTimeout(function () { // Check if enemy still exists before firing if (!self.destroyed) { var bulletSpeed = 8; var vx = -bulletSpeed * 0.707; // Move left var vy = self.isTop ? bulletSpeed * 0.707 : -bulletSpeed * 0.707; // Move down if top, up if bottom fireEnemyBullet(self.x, self.y, vx, vy); } }, i * self.burstDelay); } } }; return self; }); // Mountain Obstacle Class var Mountain = Container.expand(function (isTop) { var self = Container.call(this); var mountainGraphics = self.attachAsset('mountain', { anchorX: 0.5, anchorY: isTop ? 0 : 1 // Anchor base at terrain edge }); self.speed = 5; // Should match terrain speed self.update = function () { self.x -= self.speed; }; return self; }); // Player Bullet Class var PlayerBullet = Container.expand(function (startX, startY) { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.x = startX; self.y = startY; self.speed = 20; // Moves to the right self.update = function () { self.x += self.speed; }; return self; }); // Terrain Segment Class var TerrainSegment = Container.expand(function (isTop) { var self = Container.call(this); var terrainGraphics = self.attachAsset('terrain', { anchorX: 0, anchorY: isTop ? 0 : 1 // Anchor at top for top terrain, bottom for bottom terrain }); self.isTop = isTop; self.speed = 5; // Horizontal scroll speed self.update = function () { self.x -= self.speed; }; return self; }); // Player UFO Class var UFO = Container.expand(function () { var self = Container.call(this); var ufoGraphics = self.attachAsset('ufo', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; // Movement speed multiplier, adjust as needed // Keep UFO within game boundaries self.clampPosition = function () { var halfWidth = ufoGraphics.width / 2; var halfHeight = ufoGraphics.height / 2; if (self.x < halfWidth) { self.x = halfWidth; } if (self.x > 2048 - halfWidth) { self.x = 2048 - halfWidth; } if (self.y < halfHeight + 100) { self.y = halfHeight + 100; } // Avoid top-left menu area if (self.y > 2732 - halfHeight) { self.y = 2732 - halfHeight; } // Adjust based on terrain phase if (gamePhase === 0) { // Find the current terrain height at the UFO's x position (simplified) var terrainHeight = 200; // Assuming constant terrain height for now if (self.y < terrainHeight + halfHeight) { self.y = terrainHeight + halfHeight; } if (self.y > 2732 - terrainHeight - halfHeight) { self.y = 2732 - terrainHeight - halfHeight; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x101030 // Dark space blue background }); /**** * Game Code ****/ // Minimalistic tween library which should be used for animations over time // Boss Laser Beam // Boss // Air Enemy (Placeholder shape) // Enemy Bullet // Ground Enemy // Mountain Obstacle (simplified) // Ground/Ceiling // Player UFO // Initialize assets used in this game. Scale them according to what is needed for the game. /**** * Assets * Assets are automatically created and loaded either dynamically during gameplay * or via static code analysis based on their usage in the code. ****/ // Game State var gamePhase = 0; // 0: Terrain, 1: Space, 2: Boss var phaseStartTime = LK.ticks; var phaseDuration = 18000; // Approx 5 minutes (300 seconds * 60 fps = 18000 ticks) - Reduced for testing: 3600 (1 min) var terrainSpeed = 5; var scoreIncrementTimer = 0; // Game Objects var player = null; var terrainSegmentsTop = []; var terrainSegmentsBottom = []; var mountains = []; var groundEnemies = []; var enemyBullets = []; var airEnemies = []; // Simple air enemies for MVP phase 2 var boss = null; var bossLasers = []; var playerBullets = []; // Array for player bullets // Player Control var dragNode = null; var playerFireRate = 15; // Ticks between shots (4 shots per second) var playerFireCooldown = 0; // Score Display var scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Position score at top center // Helper function to create terrain segments function createTerrainSegment(isTop, xPos) { var segment = new TerrainSegment(isTop); segment.x = xPos; segment.y = isTop ? 0 : 2732; segment.speed = terrainSpeed; game.addChild(segment); if (isTop) { terrainSegmentsTop.push(segment); } else { terrainSegmentsBottom.push(segment); } return segment; } // Helper function to spawn mountains on terrain function spawnMountain(terrainSegment) { var mountain = new Mountain(terrainSegment.isTop); // Position relative to the terrain segment mountain.x = terrainSegment.x + Math.random() * terrainSegment.width; mountain.y = terrainSegment.isTop ? terrainSegment.height : 2732 - terrainSegment.height; mountain.speed = terrainSpeed; game.addChild(mountain); mountains.push(mountain); } // Helper function to spawn ground enemies on terrain function spawnGroundEnemy(terrainSegment) { var enemy = new GroundEnemy(terrainSegment.isTop); // Position relative to the terrain segment enemy.x = terrainSegment.x + Math.random() * terrainSegment.width; enemy.y = terrainSegment.isTop ? terrainSegment.height : 2732 - terrainSegment.height; enemy.speed = terrainSpeed; game.addChild(enemy); groundEnemies.push(enemy); } // Helper function to fire enemy bullets function fireEnemyBullet(x, y, vx, vy) { var bullet = new EnemyBullet(x, y, vx, vy); game.addChild(bullet); enemyBullets.push(bullet); LK.getSound('enemyShoot').play(); } // Helper function to spawn air enemies (simple version) function spawnAirEnemy() { var startY = Math.random() * (2732 - 400) + 200; // Avoid edges var enemy = new AirEnemy(2048 + 100, startY); // Start off-screen right game.addChild(enemy); airEnemies.push(enemy); } // Helper function to fire boss lasers function fireBossLasers(x, y) { var directions = 5; var laserSpeed = 12; var verticalSpread = 4; // Max vertical speed component for (var i = 0; i < directions; i++) { // Calculate vertical velocity component for spread // Example: i=0 -> -4, i=1 -> -2, i=2 -> 0, i=3 -> 2, i=4 -> 4 var vy = -verticalSpread + verticalSpread * 2 / (directions - 1) * i; // Keep horizontal speed constant (moving left) var vx = -laserSpeed; var laser = new BossLaser(x, y, vx, vy); game.addChild(laser); bossLasers.push(laser); } // Add sound effect for laser fire (consider adding one e.g., LK.getSound('bossShoot').play(); if asset exists) } // Initialize Game Elements function initGame() { // Reset state LK.setScore(0); scoreTxt.setText('0'); gamePhase = 0; phaseStartTime = LK.ticks; dragNode = null; playerBullets = []; // Clear player bullets playerFireCooldown = 0; // Reset fire cooldown // Clear existing elements from previous game (if any) // Note: LK engine handles full reset on GameOver/YouWin, but manual cleanup might be needed if restarting mid-game (not typical) // Let's assume full reset is handled by LK. // Create Player player = new UFO(); player.x = 300; player.y = 2732 / 2; game.addChild(player); // Create initial terrain var terrainWidth = LK.getAsset('terrain', {}).width; // Get width from asset for (var i = 0; i < Math.ceil(2048 / terrainWidth) + 1; i++) { createTerrainSegment(true, i * terrainWidth); createTerrainSegment(false, i * terrainWidth); } // Start Phase 1 Music LK.playMusic('phase1Music'); } // Call initGame to set up the initial state initGame(); // Event Handlers game.down = function (x, y, obj) { // Check if touch is on the player UFO var localPos = player.toLocal(game.toGlobal({ x: x, y: y })); // Convert game coords to player's local coords // Use a slightly larger hit area for easier dragging var hitWidth = player.width * 1.5; var hitHeight = player.height * 1.5; if (Math.abs(localPos.x) < hitWidth / 2 && Math.abs(localPos.y) < hitHeight / 2) { dragNode = player; // Instantly move player to touch position for responsive feel var gamePos = game.toLocal(obj.global); // Use obj.global for precise position player.x = gamePos.x; player.y = gamePos.y; player.clampPosition(); } else { dragNode = null; } }; game.move = function (x, y, obj) { if (dragNode) { var gamePos = game.toLocal(obj.global); // Convert event global position to game coordinates dragNode.x = gamePos.x; dragNode.y = gamePos.y; // Clamp player position within bounds immediately after move if (dragNode === player) { player.clampPosition(); } } }; game.up = function (x, y, obj) { dragNode = null; }; // Game Update Logic game.update = function () { // --- Global Updates --- if (!player || player.destroyed) { // Check if player exists and is not destroyed return; } // Stop updates if player is destroyed // Player Shooting playerFireCooldown++; if (dragNode === player && playerFireCooldown >= playerFireRate) { // Only shoot while dragging/controlling playerFireCooldown = 0; var bullet = new PlayerBullet(player.x + player.width / 2, player.y); game.addChild(bullet); playerBullets.push(bullet); LK.getSound('playerShoot').play(); } // Score increases over time scoreIncrementTimer++; if (scoreIncrementTimer >= 60) { // Add 10 points every second scoreIncrementTimer = 0; LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); } // --- Phase Management --- var elapsedTicks = LK.ticks - phaseStartTime; if (gamePhase === 0 && elapsedTicks >= phaseDuration) { // Transition to Phase 1 (Space) gamePhase = 1; phaseStartTime = LK.ticks; // Reset timer for next phase if needed console.log("Transitioning to Phase 1: Space"); // Clean up terrain-specific elements terrainSegmentsTop.forEach(function (s) { return s.destroy(); }); terrainSegmentsBottom.forEach(function (s) { return s.destroy(); }); mountains.forEach(function (m) { return m.destroy(); }); groundEnemies.forEach(function (ge) { return ge.destroy(); }); terrainSegmentsTop = []; terrainSegmentsBottom = []; mountains = []; groundEnemies = []; // Spawn initial air enemies for (var i = 0; i < 5; i++) { // Start with 5 air enemies spawnAirEnemy(); } LK.playMusic('phase2Music'); // Switch music } else if (gamePhase === 1 && elapsedTicks >= phaseDuration * 1.5) { // Example: Boss after 1.5x phase duration // Transition to Phase 2 (Boss) if (!boss) { // Ensure boss only spawns once gamePhase = 2; phaseStartTime = LK.ticks; console.log("Transitioning to Phase 2: Boss"); // Clean up air enemies airEnemies.forEach(function (ae) { return ae.destroy(); }); airEnemies = []; // Spawn Boss boss = new Boss(); game.addChild(boss); LK.playMusic('bossMusic'); // Boss music } } // --- Phase 1: Terrain Logic --- if (gamePhase === 0) { // Update and manage terrain segments var terrainWidth = LK.getAsset('terrain', {}).width; for (var i = terrainSegmentsTop.length - 1; i >= 0; i--) { var segment = terrainSegmentsTop[i]; if (segment.x < -terrainWidth) { // Reposition segment to the right var maxX = 0; terrainSegmentsTop.forEach(function (s) { if (s.x > maxX) { maxX = s.x; } }); segment.x = maxX + terrainWidth; // Potentially spawn new obstacles/enemies on the reused segment if (Math.random() < 0.3) { spawnMountain(segment); } // 30% chance to spawn mountain if (Math.random() < 0.2) { spawnGroundEnemy(segment); } // 20% chance } } // Repeat for bottom terrain for (var i = terrainSegmentsBottom.length - 1; i >= 0; i--) { var segment = terrainSegmentsBottom[i]; if (segment.x < -terrainWidth) { var maxX = 0; terrainSegmentsBottom.forEach(function (s) { if (s.x > maxX) { maxX = s.x; } }); segment.x = maxX + terrainWidth; if (Math.random() < 0.3) { spawnMountain(segment); } if (Math.random() < 0.2) { spawnGroundEnemy(segment); } } } // Update mountains & check collision for (var i = mountains.length - 1; i >= 0; i--) { var mountain = mountains[i]; if (mountain.x < -mountain.width) { mountain.destroy(); mountains.splice(i, 1); } else { if (player.intersects(mountain)) { LK.getSound('playerExplosion').play(); LK.effects.flashObject(player, 0xFF0000, 500); // Flash player red LK.showGameOver(); return; // Stop update processing } } } // Update ground enemies & check collision for (var i = groundEnemies.length - 1; i >= 0; i--) { var enemy = groundEnemies[i]; if (enemy.x < -enemy.width) { enemy.destroy(); groundEnemies.splice(i, 1); } else { // Collision check: Player vs Ground Enemy if (player.intersects(enemy)) { LK.getSound('playerExplosion').play(); LK.effects.flashObject(player, 0xFF0000, 500); enemy.destroy(); // Destroy enemy on collision too groundEnemies.splice(i, 1); LK.showGameOver(); return; } } } // Re-clamp player position based on potentially moving terrain (simple clamp for now) player.clampPosition(); } // --- Phase 1/2: Air Enemy Logic --- if (gamePhase === 1) { // Add more air enemies periodically? if (LK.ticks % 180 === 0 && airEnemies.length < 10) { // Spawn if less than 10, every 3 seconds spawnAirEnemy(); } // Update air enemies & check collision for (var i = airEnemies.length - 1; i >= 0; i--) { var enemy = airEnemies[i]; // Air enemies handle their own off-screen logic (respawn) in their update // Collision check: Player vs Air Enemy if (player.intersects(enemy)) { LK.getSound('playerExplosion').play(); LK.effects.flashObject(player, 0xFF0000, 500); enemy.destroy(); // Destroy enemy on collision airEnemies.splice(i, 1); LK.getSound('enemyExplosion').play(); LK.setScore(LK.getScore() + 50); // Score for destroying enemy scoreTxt.setText(LK.getScore()); LK.showGameOver(); return; } } } // --- Phase 3: Boss Logic --- if (gamePhase === 2 && boss) { // Check collision: Player vs Boss if (player.intersects(boss)) { LK.getSound('playerExplosion').play(); LK.effects.flashObject(player, 0xFF0000, 500); // Don't destroy boss on collision, just game over LK.showGameOver(); return; } // Update boss lasers & check collision for (var i = bossLasers.length - 1; i >= 0; i--) { var laser = bossLasers[i]; // Check if laser is off-screen if (laser.x < -laser.width || laser.x > 2048 + laser.width || laser.y < -laser.height || laser.y > 2732 + laser.height) { laser.destroy(); bossLasers.splice(i, 1); } else { // Collision check: Player vs Boss Laser if (player.intersects(laser)) { LK.getSound('playerExplosion').play(); LK.effects.flashObject(player, 0xFF0000, 500); laser.destroy(); // Destroy laser bossLasers.splice(i, 1); LK.showGameOver(); return; } } } // Note: Boss defeat condition is now handled within the player bullet collision check loop. } // --- Update Enemy Bullets & Check Collision (All Phases) --- for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; // Check if bullet is off-screen if (bullet.y < -bullet.height || bullet.y > 2732 + bullet.height) { bullet.destroy(); enemyBullets.splice(i, 1); } else { // Collision check: Player vs Enemy Bullet if (player.intersects(bullet)) { LK.getSound('playerExplosion').play(); LK.effects.flashObject(player, 0xFF0000, 500); bullet.destroy(); // Destroy bullet enemyBullets.splice(i, 1); LK.showGameOver(); return; // Stop update processing } } } // --- Update Player Bullets & Check Collision --- for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; // Check if bullet is off-screen (right side) if (bullet.x > 2048 + bullet.width) { bullet.destroy(); playerBullets.splice(i, 1); continue; // Skip collision checks if off-screen } // Collision Check: Player Bullet vs Ground Enemy (Phase 0) if (gamePhase === 0) { for (var j = groundEnemies.length - 1; j >= 0; j--) { var enemy = groundEnemies[j]; if (bullet.intersects(enemy)) { LK.getSound('enemyExplosion').play(); LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white enemy.destroy(); groundEnemies.splice(j, 1); bullet.destroy(); playerBullets.splice(i, 1); LK.setScore(LK.getScore() + 100); // Score for destroying ground enemy scoreTxt.setText(LK.getScore()); break; // Bullet can only hit one enemy } } if (!bullet.exists) { continue; } // Check if bullet was destroyed in previous loop } // Collision Check: Player Bullet vs Air Enemy (Phase 1) if (gamePhase === 1) { for (var j = airEnemies.length - 1; j >= 0; j--) { var enemy = airEnemies[j]; if (bullet.intersects(enemy)) { LK.getSound('enemyExplosion').play(); LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white enemy.destroy(); airEnemies.splice(j, 1); bullet.destroy(); playerBullets.splice(i, 1); LK.setScore(LK.getScore() + 150); // Score for destroying air enemy scoreTxt.setText(LK.getScore()); break; // Bullet can only hit one enemy } } if (!bullet.exists) { continue; } // Check if bullet was destroyed in previous loop } // Collision Check: Player Bullet vs Boss (Phase 2) if (gamePhase === 2 && boss) { if (bullet.intersects(boss)) { LK.getSound('enemyExplosion').play(); // Use enemy explosion for hit sound LK.effects.flashObject(boss, 0xFFFFFF, 100); // Flash boss white bullet.destroy(); playerBullets.splice(i, 1); boss.health -= 1; // Decrease boss health LK.setScore(LK.getScore() + 10); // Small score for hitting boss scoreTxt.setText(LK.getScore()); // Boss defeat check is now inside the bullet loop if (boss.health <= 0) { LK.getSound('enemyExplosion').play(); // Big explosion boss.destroy(); boss = null; // Cleanup remaining lasers bossLasers.forEach(function (l) { return l.destroy(); }); bossLasers = []; LK.setScore(LK.getScore() + 5000); // Big score bonus scoreTxt.setText(LK.getScore()); LK.showYouWin(); return; // Stop update processing } break; // Bullet is destroyed after hitting boss } } } // End of playerBullets loop };
===================================================================
--- original.js
+++ change.js
@@ -144,8 +144,23 @@
self.x -= self.speed;
};
return self;
});
+// Player Bullet Class
+var PlayerBullet = Container.expand(function (startX, startY) {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('playerBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.x = startX;
+ self.y = startY;
+ self.speed = 20; // Moves to the right
+ self.update = function () {
+ self.x += self.speed;
+ };
+ return self;
+});
// Terrain Segment Class
var TerrainSegment = Container.expand(function (isTop) {
var self = Container.call(this);
var terrainGraphics = self.attachAsset('terrain', {
@@ -207,24 +222,24 @@
/****
* Game Code
****/
-// Game State
+// Minimalistic tween library which should be used for animations over time
+// Boss Laser Beam
+// Boss
+// Air Enemy (Placeholder shape)
+// Enemy Bullet
+// Ground Enemy
+// Mountain Obstacle (simplified)
+// Ground/Ceiling
+// Player UFO
+// Initialize assets used in this game. Scale them according to what is needed for the game.
/****
* Assets
* Assets are automatically created and loaded either dynamically during gameplay
* or via static code analysis based on their usage in the code.
****/
-// Initialize assets used in this game. Scale them according to what is needed for the game.
-// Player UFO
-// Ground/Ceiling
-// Mountain Obstacle (simplified)
-// Ground Enemy
-// Enemy Bullet
-// Air Enemy (Placeholder shape)
-// Boss
-// Boss Laser Beam
-// Minimalistic tween library which should be used for animations over time
+// Game State
var gamePhase = 0; // 0: Terrain, 1: Space, 2: Boss
var phaseStartTime = LK.ticks;
var phaseDuration = 18000; // Approx 5 minutes (300 seconds * 60 fps = 18000 ticks) - Reduced for testing: 3600 (1 min)
var terrainSpeed = 5;
@@ -238,10 +253,13 @@
var enemyBullets = [];
var airEnemies = []; // Simple air enemies for MVP phase 2
var boss = null;
var bossLasers = [];
+var playerBullets = []; // Array for player bullets
// Player Control
var dragNode = null;
+var playerFireRate = 15; // Ticks between shots (4 shots per second)
+var playerFireCooldown = 0;
// Score Display
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
@@ -320,8 +338,10 @@
scoreTxt.setText('0');
gamePhase = 0;
phaseStartTime = LK.ticks;
dragNode = null;
+ playerBullets = []; // Clear player bullets
+ playerFireCooldown = 0; // Reset fire cooldown
// Clear existing elements from previous game (if any)
// Note: LK engine handles full reset on GameOver/YouWin, but manual cleanup might be needed if restarting mid-game (not typical)
// Let's assume full reset is handled by LK.
// Create Player
@@ -377,11 +397,22 @@
};
// Game Update Logic
game.update = function () {
// --- Global Updates ---
- if (player.destroyed) {
+ if (!player || player.destroyed) {
+ // Check if player exists and is not destroyed
return;
} // Stop updates if player is destroyed
+ // Player Shooting
+ playerFireCooldown++;
+ if (dragNode === player && playerFireCooldown >= playerFireRate) {
+ // Only shoot while dragging/controlling
+ playerFireCooldown = 0;
+ var bullet = new PlayerBullet(player.x + player.width / 2, player.y);
+ game.addChild(bullet);
+ playerBullets.push(bullet);
+ LK.getSound('playerShoot').play();
+ }
// Score increases over time
scoreIncrementTimer++;
if (scoreIncrementTimer >= 60) {
// Add 10 points every second
@@ -570,21 +601,9 @@
return;
}
}
}
- // Boss defeat condition (placeholder - needs player bullets to hit boss)
- // if (boss.health <= 0) {
- // LK.getSound('enemyExplosion').play(); // Big explosion
- // boss.destroy();
- // boss = null;
- // // Cleanup remaining lasers
- // bossLasers.forEach(l => l.destroy());
- // bossLasers = [];
- // LK.setScore(LK.getScore() + 1000); // Big score bonus
- // scoreTxt.setText(LK.getScore());
- // LK.showYouWin();
- // return;
- // }
+ // Note: Boss defeat condition is now handled within the player bullet collision check loop.
}
// --- Update Enemy Bullets & Check Collision (All Phases) ---
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
@@ -603,5 +622,83 @@
return; // Stop update processing
}
}
}
+ // --- Update Player Bullets & Check Collision ---
+ for (var i = playerBullets.length - 1; i >= 0; i--) {
+ var bullet = playerBullets[i];
+ // Check if bullet is off-screen (right side)
+ if (bullet.x > 2048 + bullet.width) {
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ continue; // Skip collision checks if off-screen
+ }
+ // Collision Check: Player Bullet vs Ground Enemy (Phase 0)
+ if (gamePhase === 0) {
+ for (var j = groundEnemies.length - 1; j >= 0; j--) {
+ var enemy = groundEnemies[j];
+ if (bullet.intersects(enemy)) {
+ LK.getSound('enemyExplosion').play();
+ LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white
+ enemy.destroy();
+ groundEnemies.splice(j, 1);
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ LK.setScore(LK.getScore() + 100); // Score for destroying ground enemy
+ scoreTxt.setText(LK.getScore());
+ break; // Bullet can only hit one enemy
+ }
+ }
+ if (!bullet.exists) {
+ continue;
+ } // Check if bullet was destroyed in previous loop
+ }
+ // Collision Check: Player Bullet vs Air Enemy (Phase 1)
+ if (gamePhase === 1) {
+ for (var j = airEnemies.length - 1; j >= 0; j--) {
+ var enemy = airEnemies[j];
+ if (bullet.intersects(enemy)) {
+ LK.getSound('enemyExplosion').play();
+ LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white
+ enemy.destroy();
+ airEnemies.splice(j, 1);
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ LK.setScore(LK.getScore() + 150); // Score for destroying air enemy
+ scoreTxt.setText(LK.getScore());
+ break; // Bullet can only hit one enemy
+ }
+ }
+ if (!bullet.exists) {
+ continue;
+ } // Check if bullet was destroyed in previous loop
+ }
+ // Collision Check: Player Bullet vs Boss (Phase 2)
+ if (gamePhase === 2 && boss) {
+ if (bullet.intersects(boss)) {
+ LK.getSound('enemyExplosion').play(); // Use enemy explosion for hit sound
+ LK.effects.flashObject(boss, 0xFFFFFF, 100); // Flash boss white
+ bullet.destroy();
+ playerBullets.splice(i, 1);
+ boss.health -= 1; // Decrease boss health
+ LK.setScore(LK.getScore() + 10); // Small score for hitting boss
+ scoreTxt.setText(LK.getScore());
+ // Boss defeat check is now inside the bullet loop
+ if (boss.health <= 0) {
+ LK.getSound('enemyExplosion').play(); // Big explosion
+ boss.destroy();
+ boss = null;
+ // Cleanup remaining lasers
+ bossLasers.forEach(function (l) {
+ return l.destroy();
+ });
+ bossLasers = [];
+ LK.setScore(LK.getScore() + 5000); // Big score bonus
+ scoreTxt.setText(LK.getScore());
+ LK.showYouWin();
+ return; // Stop update processing
+ }
+ break; // Bullet is destroyed after hitting boss
+ }
+ }
+ } // End of playerBullets loop
};
\ No newline at end of file
Alien Airships of boss, HD colors. In-Game asset. 2d. High contrast. No shadows
gunTurret. yellow, HD colors. In-Game asset. 2d. High contrast. No shadows
pack mountain, yellow, HD colors. In-Game asset. 2d. High contrast. No shadows.no black lines
shot circle. blur, light, HD colors In-Game asset. 2d. High contrast. No shadows