User prompt
When the player reaches 70 points, a shield will appear on her for 3 seconds and she will not take damage.
User prompt
Player must look in the direction he is shooting
User prompt
After the 2nd background, when you reach 100 points, 3 more backgrounds will appear and in the same way, the enemies in the new background will be replaced by other enemies.
User prompt
When you switch to the new background, the enemies will disappear
User prompt
reset the scoreboard and leveler when it goes to the new background
User prompt
When you win the game, the game does not end and continues in another background
User prompt
add seconds and minutes signs
User prompt
enemies should come less in 2 levels, level 3 should start at 70 score and enemies should increase
User prompt
enemies should come less in 2 levels, level 3 should start at 70 score and enemies should increase
User prompt
HealthPickup ShieldPickup add
User prompt
extra health and shield coming from the surroundings, when you take health, your health increases by 1, when you take a shield, you do not take damage for 5 seconds
User prompt
Die in 3 damage
User prompt
glows red when taking damage from enemies and kills enemies in 3 hits
User prompt
100 score game over
User prompt
The second stage will come after 30 scores.
User prompt
In the second stage, the enemies will come faster and more, and our fire rate will increase.
User prompt
enemies move slower
User prompt
shoot where you click
Code edit (1 edits merged)
Please save this source code
User prompt
Bullet Clash: Enemy Onslaught
User prompt
add enemy variety
Initial prompt
Make me a 3D war game set in space
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Enemy base class var Enemy = Container.expand(function () { var self = Container.call(this); self.type = 'base'; self.speed = 4; self.health = 3; self.isFlashing = false; self.flashTimeout = null; self.update = function () {}; self.takeDamage = function () { if (self.isFlashing) return; self.health--; self.isFlashing = true; // Flash red for 200ms LK.effects.flashObject(self, 0xff0000, 200); if (self.flashTimeout) LK.clearTimeout(self.flashTimeout); self.flashTimeout = LK.setTimeout(function () { self.isFlashing = false; }, 200); }; return self; }); // Enemy: Spinner (orbits the central target) var EnemySpinner = Enemy.expand(function () { var self = Enemy.call(this); var asset = self.attachAsset('enemySpinner', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'spinner'; self.radius = 400 + Math.random() * 200; self.angle = Math.random() * Math.PI * 2; self.speed = 0.012 + Math.random() * 0.005; self.update = function () { self.angle += self.speed; self.x = centralTarget.x + Math.cos(self.angle) * self.radius; self.y = centralTarget.y + Math.sin(self.angle) * self.radius; }; return self; }); // Enemy: Seeker (moves toward player) var EnemySeeker = Enemy.expand(function () { var self = Enemy.call(this); var asset = self.attachAsset('enemySeeker', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'seeker'; self.speed = 3; self.update = function () { // Move toward player if (!player) return; var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); // Enemy: Dasher (dashes horizontally or vertically) var EnemyDasher = Enemy.expand(function () { var self = Enemy.call(this); var asset = self.attachAsset('enemyDasher', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'dasher'; self.axis = Math.random() < 0.5 ? 'x' : 'y'; self.speed = 9 + Math.random() * 3; self.direction = Math.random() < 0.5 ? 1 : -1; self.update = function () { if (self.axis === 'x') { self.x += self.speed * self.direction; } else { self.y += self.speed * self.direction; } }; return self; }); // Health Pickup var HealthPickup = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: 0x2ecc71 // green tint for health }); self.type = 'health'; self.update = function () {}; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.radius = 700; self.angle = -Math.PI / 2; self.x = 0; self.y = 0; self.updatePosition = function () { self.x = centralTarget.x + Math.cos(self.angle) * self.radius; self.y = centralTarget.y + Math.sin(self.angle) * self.radius; }; self.updatePosition(); return self; }); // Player bullet var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); // vx, vy will be set on creation self.vx = 0; self.vy = -32; self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Shield Pickup var ShieldPickup = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: 0xf1c40f // yellow tint for shield }); self.type = 'shield'; self.update = function () {}; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c20 }); /**** * Game Code ****/ // Central target // Player character // Player bullet // Central target // Enemy type 1: Seeker // Enemy type 2: Spinner // Enemy type 3: Dasher // Sound for shooting // Sound for enemy destroyed // Sound for hit target // Music var centralTarget = LK.getAsset('centralTarget', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(centralTarget); // Player var player = new Player(); player.updatePosition(); game.addChild(player); // Player health (3 hits to die) var playerHealth = 3; // Shield state var playerShieldActive = false; var playerShieldTimer = 0; // Bullets and enemies arrays var playerBullets = []; var enemies = []; // Score var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Track background state for multi-background progression game.backgroundChanged = 0; // Timer text (minutes:seconds) var timerTxt = new Text2('0:00', { size: 90, fill: 0xFFFFFF }); timerTxt.anchor.set(0.5, 0); timerTxt.y = 110; // Place below score, avoid top 100px LK.gui.top.addChild(timerTxt); // Track elapsed time in frames var elapsedFrames = 0; // Difficulty and spawn control var spawnTimer = 0; var spawnInterval = 90; // frames var enemyTypes = ['seeker']; var difficultyTimer = 0; // Stage control var stage = 1; var fireTimer = 0; var fireInterval = 18; // frames between shots, default for stage 1 // Drag control var dragging = false; var dragStartAngle = 0; var dragStartX = 0; var dragStartY = 0; // Helper: get angle from center to (x, y) function getAngleToCenter(x, y) { var dx = x - centralTarget.x; var dy = y - centralTarget.y; return Math.atan2(dy, dx); } // Move handler: drag around the central target function handleMove(x, y, obj) { if (!dragging) return; var angle = getAngleToCenter(x, y); player.angle = angle; player.updatePosition(); } game.move = handleMove; game.down = function (x, y, obj) { // Only start drag if not on top left 100x100 if (x < 100 && y < 100) return; dragging = true; handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragging = false; }; // Shoot on tap anywhere (except top left) game.down = function (x, y, obj) { if (x < 100 && y < 100) return; // Fire bullet toward tap/click var bullet = new PlayerBullet(); bullet.x = player.x; bullet.y = player.y; bullet.lastY = bullet.y; bullet.lastIntersecting = false; // Calculate direction from player to tap/click var dx = x - player.x; var dy = y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var speed = 32; bullet.vx = dx / dist * speed; bullet.vy = dy / dist * speed; // Rotate player to face shooting direction player.angle = Math.atan2(dy, dx); player.updatePosition(); } else { bullet.vx = 0; bullet.vy = -32; } playerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); // Also allow drag dragging = true; handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragging = false; }; // Enemy spawn logic function spawnEnemy() { var type = enemyTypes[Math.floor(Math.random() * enemyTypes.length)]; var enemy; if (type === 'seeker') { enemy = new EnemySeeker(); // Spawn at random edge var edge = Math.floor(Math.random() * 4); if (edge === 0) { // top enemy.x = Math.random() * 2048; enemy.y = -100; } else if (edge === 1) { // right enemy.x = 2048 + 100; enemy.y = Math.random() * 2732; } else if (edge === 2) { // bottom enemy.x = Math.random() * 2048; enemy.y = 2732 + 100; } else { // left enemy.x = -100; enemy.y = Math.random() * 2732; } } else if (type === 'spinner') { enemy = new EnemySpinner(); // Place at random angle enemy.angle = Math.random() * Math.PI * 2; enemy.radius = 400 + Math.random() * 400; enemy.x = centralTarget.x + Math.cos(enemy.angle) * enemy.radius; enemy.y = centralTarget.y + Math.sin(enemy.angle) * enemy.radius; } else if (type === 'dasher') { enemy = new EnemyDasher(); // Start at random edge if (enemy.axis === 'x') { enemy.x = enemy.direction > 0 ? -100 : 2048 + 100; enemy.y = Math.random() * 2732; } else { enemy.x = Math.random() * 2048; enemy.y = enemy.direction > 0 ? -100 : 2732 + 100; } } if (enemy) { enemy.lastIntersectingPlayer = false; enemy.lastIntersectingTarget = false; enemies.push(enemy); game.addChild(enemy); } } // Main update loop game.update = function () { // Update timer elapsedFrames++; var totalSeconds = Math.floor(elapsedFrames / 60); var minutes = Math.floor(totalSeconds / 60); var seconds = totalSeconds % 60; var secondsStr = seconds < 10 ? '0' + seconds : '' + seconds; timerTxt.setText(minutes + ':' + secondsStr); // Difficulty scaling difficultyTimer++; if (difficultyTimer % 600 === 0 && enemyTypes.length < 3) { if (enemyTypes.length === 1) { enemyTypes.push('spinner'); } else if (enemyTypes.length === 2) { enemyTypes.push('dasher'); } if (spawnInterval > 40) spawnInterval -= 10; } // Stage progression: switch to stage 2 at score 30, and to stage 3 at score 70 if (stage === 1 && LK.getScore() >= 30) { stage = 2; spawnInterval = 90; // slower spawn for stage 2 fireInterval = 7; // faster fire rate } if (stage === 2 && LK.getScore() >= 70) { stage = 3; spawnInterval = 30; // much faster enemy spawn in stage 3 fireInterval = 4; // even faster fire rate // Activate shield for 3 seconds (180 frames) if (!playerShieldActive) { playerShieldActive = true; playerShieldTimer = 180; // Optional: flash player or add effect LK.effects.flashObject(player, 0xf1c40f, 3000); } } // Handle shield timer if (playerShieldActive) { playerShieldTimer--; if (playerShieldTimer <= 0) { playerShieldActive = false; playerShieldTimer = 0; } } // Spawn enemies spawnTimer++; if (spawnTimer >= spawnInterval) { // In stage 1, spawn 1 enemy per interval if (stage === 1) { spawnEnemy(); } else if (stage === 2) { // In stage 2, spawn 1 enemy per interval (less than before) spawnEnemy(); } else if (stage === 3) { // In stage 3, spawn 4 enemies per interval (increase) spawnEnemy(); spawnEnemy(); spawnEnemy(); spawnEnemy(); } spawnTimer = 0; } // Automatic fire logic (increased fire rate in stage 2 and 3) fireTimer++; if (fireTimer >= fireInterval && dragging) { // Fire bullet toward current player angle (in direction player is facing) var bullet = new PlayerBullet(); bullet.x = player.x; bullet.y = player.y; bullet.lastY = bullet.y; bullet.lastIntersecting = false; // Fire toward central target var dx = centralTarget.x - player.x; var dy = centralTarget.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var speed = 32; bullet.vx = dx / dist * speed; bullet.vy = dy / dist * speed; } else { bullet.vx = 0; bullet.vy = -32; } playerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); fireTimer = 0; } // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; bullet.update(); // Remove if off screen if (bullet.y < -60 || bullet.y > 2732 + 60 || bullet.x < -60 || bullet.x > 2048 + 60) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check hit on central target var hitTarget = bullet.intersects(centralTarget); if (!bullet.lastIntersecting && hitTarget) { LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); LK.getSound('targetHit').play(); bullet.destroy(); playerBullets.splice(i, 1); // Win condition: Instead of ending, change background and continue if (LK.getScore() >= 100) { if (!game.backgroundChanged) { // First background change (after 100 points) game.setBackgroundColor(0x1a1a40); // 2nd background color game.backgroundChanged = 1; // Remove all enemies from the game for (var ei = enemies.length - 1; ei >= 0; ei--) { enemies[ei].destroy(); } enemies = []; // Reset score, stage, and timer LK.setScore(0); scoreTxt.setText('0'); stage = 1; spawnInterval = 90; fireInterval = 18; elapsedFrames = 0; difficultyTimer = 0; // Set new enemy types for 2nd background enemyTypes = ['spinner', 'dasher']; // Optionally, you could add a visual effect or message here } else if (game.backgroundChanged === 1 && LK.getScore() >= 100) { // Second background change (after 2nd 100 points) game.setBackgroundColor(0x1a4020); // 3rd background color game.backgroundChanged = 2; for (var ei = enemies.length - 1; ei >= 0; ei--) { enemies[ei].destroy(); } enemies = []; LK.setScore(0); scoreTxt.setText('0'); stage = 1; spawnInterval = 90; fireInterval = 18; elapsedFrames = 0; difficultyTimer = 0; // Set new enemy types for 3rd background enemyTypes = ['seeker', 'dasher']; } else if (game.backgroundChanged === 2 && LK.getScore() >= 100) { // Third background change (after 3rd 100 points) game.setBackgroundColor(0x40201a); // 4th background color game.backgroundChanged = 3; for (var ei = enemies.length - 1; ei >= 0; ei--) { enemies[ei].destroy(); } enemies = []; LK.setScore(0); scoreTxt.setText('0'); stage = 1; spawnInterval = 90; fireInterval = 18; elapsedFrames = 0; difficultyTimer = 0; // Set new enemy types for 4th background enemyTypes = ['seeker', 'spinner']; } else if (game.backgroundChanged === 3 && LK.getScore() >= 100) { // Fourth background change (after 4th 100 points) game.setBackgroundColor(0x204040); // 5th background color game.backgroundChanged = 4; for (var ei = enemies.length - 1; ei >= 0; ei--) { enemies[ei].destroy(); } enemies = []; LK.setScore(0); scoreTxt.setText('0'); stage = 1; spawnInterval = 90; fireInterval = 18; elapsedFrames = 0; difficultyTimer = 0; // Set new enemy types for 5th background enemyTypes = ['dasher', 'spinner']; } } continue; } bullet.lastIntersecting = hitTarget; // Check hit on enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { LK.getSound('enemyDown').play(); bullet.destroy(); playerBullets.splice(i, 1); enemy.takeDamage(); if (enemy.health <= 0) { enemy.destroy(); enemies.splice(j, 1); } break; } } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); // Remove if off screen (for dashers) if (enemy.x < -200 || enemy.x > 2048 + 200 || enemy.y < -200 || enemy.y > 2732 + 200) { enemy.destroy(); enemies.splice(i, 1); continue; } // Check collision with player var hitPlayer = enemy.intersects(player); if (!enemy.lastIntersectingPlayer && hitPlayer) { if (!playerShieldActive) { playerHealth--; LK.effects.flashScreen(0xff0000, 800); if (playerHealth <= 0) { LK.showGameOver(); return; } } } enemy.lastIntersectingPlayer = hitPlayer; // Check collision with central target (optional: could penalize or just remove) var hitTarget = enemy.intersects(centralTarget); if (!enemy.lastIntersectingTarget && hitTarget) { // Remove enemy enemy.destroy(); enemies.splice(i, 1); continue; } enemy.lastIntersectingTarget = hitTarget; } }; // Play background music LK.playMusic('bgmusic', { fade: { start: 0, end: 1, duration: 1200 } });
===================================================================
--- original.js
+++ change.js
@@ -184,8 +184,11 @@
player.updatePosition();
game.addChild(player);
// Player health (3 hits to die)
var playerHealth = 3;
+// Shield state
+var playerShieldActive = false;
+var playerShieldTimer = 0;
// Bullets and enemies arrays
var playerBullets = [];
var enemies = [];
// Score
@@ -356,9 +359,24 @@
if (stage === 2 && LK.getScore() >= 70) {
stage = 3;
spawnInterval = 30; // much faster enemy spawn in stage 3
fireInterval = 4; // even faster fire rate
+ // Activate shield for 3 seconds (180 frames)
+ if (!playerShieldActive) {
+ playerShieldActive = true;
+ playerShieldTimer = 180;
+ // Optional: flash player or add effect
+ LK.effects.flashObject(player, 0xf1c40f, 3000);
+ }
}
+ // Handle shield timer
+ if (playerShieldActive) {
+ playerShieldTimer--;
+ if (playerShieldTimer <= 0) {
+ playerShieldActive = false;
+ playerShieldTimer = 0;
+ }
+ }
// Spawn enemies
spawnTimer++;
if (spawnTimer >= spawnInterval) {
// In stage 1, spawn 1 enemy per interval
@@ -526,13 +544,15 @@
}
// Check collision with player
var hitPlayer = enemy.intersects(player);
if (!enemy.lastIntersectingPlayer && hitPlayer) {
- playerHealth--;
- LK.effects.flashScreen(0xff0000, 800);
- if (playerHealth <= 0) {
- LK.showGameOver();
- return;
+ if (!playerShieldActive) {
+ playerHealth--;
+ LK.effects.flashScreen(0xff0000, 800);
+ if (playerHealth <= 0) {
+ LK.showGameOver();
+ return;
+ }
}
}
enemy.lastIntersectingPlayer = hitPlayer;
// Check collision with central target (optional: could penalize or just remove)