Code edit (1 edits merged)
Please save this source code
User prompt
Neon Arena: Top-Down Shooter
Initial prompt
"Act as a senior game developer. Create a polished 2D Top-Down Arena Shooter game using Python and the Pygame library. Core Mechanics: Player: A neon-green triangle in the center. Movement with WASD, but add inertia/friction physics (the ship should drift slightly when keys are released, not stop instantly). Aiming: The player ship must strictly rotate to face the mouse cursor. Shooting: Left Mouse Button shoots fast glowing projectiles in the direction of the mouse. Enemies: Red neon squares spawn randomly outside the screen borders and constantly move towards the player. Combat: If a bullet hits an enemy, the enemy is destroyed and the score increases. If an enemy touches the player, player health decreases. Advanced "Juice" Features (Important): Particle System: When an enemy dies, create a 'particle explosion' effect (small colorful pixels flying out and fading away). Screen Constraints: The player cannot go outside the screen. Difficulty: Increase enemy spawn rate as the score gets higher. UI: Show Score and a Health Bar at the top. Keep the code in a single file if possible and make the graphics drawn by shapes (no external image assets needed)."
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 15;
self.lifetime = 0;
self.maxLifetime = 150;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime++;
if (self.lifetime > self.maxLifetime) {
self.destroy();
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 2;
self.health = 1;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 0;
self.maxLifetime = 60;
self.color = 0xffff00;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime++;
var alpha = 1 - self.lifetime / self.maxLifetime;
particleGraphics.alpha = alpha;
if (self.lifetime > self.maxLifetime) {
self.destroy();
}
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
shipGraphics.rotation = -Math.PI / 2;
self.velocityX = 0;
self.velocityY = 0;
self.acceleration = 0.8;
self.friction = 0.92;
self.maxSpeed = 8;
self.rotation = 0;
self.health = 100;
self.canShoot = true;
self.shootCooldown = 0;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityX *= self.friction;
self.velocityY *= self.friction;
var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
if (speed > self.maxSpeed) {
var ratio = self.maxSpeed / speed;
self.velocityX *= ratio;
self.velocityY *= ratio;
}
if (self.x < 40) self.x = 40;
if (self.x > 2008) self.x = 2008;
if (self.y < 40) self.y = 40;
if (self.y > 2692) self.y = 2692;
shipGraphics.rotation = self.rotation + Math.PI / 2;
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0e27
});
/****
* Game Code
****/
var playerShip = game.addChild(new PlayerShip());
playerShip.x = 1024;
playerShip.y = 1366;
var enemies = [];
var bullets = [];
var particles = [];
var score = 0;
var health = 100;
var spawnRate = 60;
var spawnCounter = 0;
var scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0x00FF00
});
scoreTxt.anchor.set(0, 0);
LK.gui.top.addChild(scoreTxt);
var healthTxt = new Text2('Health: 100', {
size: 100,
fill: 0xFF0000
});
healthTxt.anchor.set(1, 0);
LK.gui.top.addChild(healthTxt);
var keysPressed = {
w: false,
a: false,
s: false,
d: false
};
var mouseX = 1024;
var mouseY = 1366;
function createParticleExplosion(x, y) {
var particleCount = 12;
for (var i = 0; i < particleCount; i++) {
var particle = game.addChild(new Particle());
particle.x = x;
particle.y = y;
var angle = i / particleCount * Math.PI * 2;
var speed = 3 + Math.random() * 2;
particle.velocityX = Math.cos(angle) * speed;
particle.velocityY = Math.sin(angle) * speed;
var colors = [0xff0000, 0xff00ff, 0x00ffff, 0xffff00];
particle.color = colors[Math.floor(Math.random() * colors.length)];
particle.children[0].tint = particle.color;
particles.push(particle);
}
LK.getSound('explosion').play();
}
function spawnEnemy() {
var enemy = game.addChild(new Enemy());
var side = Math.floor(Math.random() * 4);
if (side === 0) {
enemy.x = Math.random() * 2048;
enemy.y = -30;
} else if (side === 1) {
enemy.x = 2048 + 30;
enemy.y = Math.random() * 2732;
} else if (side === 2) {
enemy.x = Math.random() * 2048;
enemy.y = 2732 + 30;
} else {
enemy.x = -30;
enemy.y = Math.random() * 2732;
}
var dx = playerShip.x - enemy.x;
var dy = playerShip.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
enemy.velocityX = dx / distance * enemy.speed;
enemy.velocityY = dy / distance * enemy.speed;
}
enemies.push(enemy);
}
game.move = function (x, y, obj) {
mouseX = x;
mouseY = y;
var dx = mouseX - playerShip.x;
var dy = mouseY - playerShip.y;
playerShip.rotation = Math.atan2(dy, dx);
};
game.down = function (x, y, obj) {
if (playerShip.shootCooldown <= 0) {
var bullet = game.addChild(new Bullet());
bullet.x = playerShip.x;
bullet.y = playerShip.y;
bullet.velocityX = Math.cos(playerShip.rotation) * bullet.speed;
bullet.velocityY = Math.sin(playerShip.rotation) * bullet.speed;
bullets.push(bullet);
playerShip.shootCooldown = 8;
LK.getSound('shoot').play();
}
};
game.update = function () {
spawnCounter++;
if (spawnCounter > spawnRate) {
spawnEnemy();
spawnCounter = 0;
if (spawnRate > 15) {
spawnRate = Math.max(15, 60 - Math.floor(score / 5));
}
}
if (keysPressed.w) {
playerShip.velocityX += Math.cos(playerShip.rotation) * playerShip.acceleration;
playerShip.velocityY += Math.sin(playerShip.rotation) * playerShip.acceleration;
}
if (keysPressed.a) {
playerShip.velocityX += Math.cos(playerShip.rotation - Math.PI / 2) * playerShip.acceleration;
playerShip.velocityY += Math.sin(playerShip.rotation - Math.PI / 2) * playerShip.acceleration;
}
if (keysPressed.s) {
playerShip.velocityX += Math.cos(playerShip.rotation + Math.PI) * playerShip.acceleration;
playerShip.velocityY += Math.sin(playerShip.rotation + Math.PI) * playerShip.acceleration;
}
if (keysPressed.d) {
playerShip.velocityX += Math.cos(playerShip.rotation + Math.PI / 2) * playerShip.acceleration;
playerShip.velocityY += Math.sin(playerShip.rotation + Math.PI / 2) * playerShip.acceleration;
}
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
if (bullet.lifetime === undefined) bullet.lifetime = 0;
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (bullet.intersects(enemy)) {
createParticleExplosion(enemy.x, enemy.y);
LK.setScore(LK.getScore() + 1);
score = LK.getScore();
scoreTxt.setText('Score: ' + score);
enemy.destroy();
enemies.splice(e, 1);
bullet.destroy();
bullets.splice(b, 1);
break;
}
}
}
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (enemy.lastIntersecting === undefined) enemy.lastIntersecting = false;
var currentIntersecting = enemy.intersects(playerShip);
if (!enemy.lastIntersecting && currentIntersecting) {
health -= 10;
playerShip.health = health;
healthTxt.setText('Health: ' + health);
if (health <= 0) {
LK.showGameOver();
}
LK.effects.flashObject(playerShip, 0xff0000, 300);
}
enemy.lastIntersecting = currentIntersecting;
if (enemy.x < -100 || enemy.x > 2148 || enemy.y < -100 || enemy.y > 2832) {
enemy.destroy();
enemies.splice(e, 1);
}
}
for (var p = particles.length - 1; p >= 0; p--) {
var particle = particles[p];
if (particle.lifetime > particle.maxLifetime) {
particle.destroy();
particles.splice(p, 1);
}
}
};
document.addEventListener('keydown', function (e) {
var key = String.fromCharCode(e.keyCode).toLowerCase();
if (key === 'w') keysPressed.w = true;
if (key === 'a') keysPressed.a = true;
if (key === 's') keysPressed.s = true;
if (key === 'd') keysPressed.d = true;
});
document.addEventListener('keyup', function (e) {
var key = String.fromCharCode(e.keyCode).toLowerCase();
if (key === 'w') keysPressed.w = false;
if (key === 'a') keysPressed.a = false;
if (key === 's') keysPressed.s = false;
if (key === 'd') keysPressed.d = false;
});
LK.playMusic('bgmusic', {
loop: true
}); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,296 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.velocityX = 0;
+ self.velocityY = 0;
+ self.speed = 15;
+ self.lifetime = 0;
+ self.maxLifetime = 150;
+ self.update = function () {
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ self.lifetime++;
+ if (self.lifetime > self.maxLifetime) {
+ self.destroy();
+ }
+ };
+ return self;
+});
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemyGraphics = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.velocityX = 0;
+ self.velocityY = 0;
+ self.speed = 2;
+ self.health = 1;
+ self.update = function () {
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ };
+ return self;
+});
+var Particle = Container.expand(function () {
+ var self = Container.call(this);
+ var particleGraphics = self.attachAsset('particle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.velocityX = 0;
+ self.velocityY = 0;
+ self.lifetime = 0;
+ self.maxLifetime = 60;
+ self.color = 0xffff00;
+ self.update = function () {
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ self.lifetime++;
+ var alpha = 1 - self.lifetime / self.maxLifetime;
+ particleGraphics.alpha = alpha;
+ if (self.lifetime > self.maxLifetime) {
+ self.destroy();
+ }
+ };
+ return self;
+});
+var PlayerShip = Container.expand(function () {
+ var self = Container.call(this);
+ var shipGraphics = self.attachAsset('playerShip', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ shipGraphics.rotation = -Math.PI / 2;
+ self.velocityX = 0;
+ self.velocityY = 0;
+ self.acceleration = 0.8;
+ self.friction = 0.92;
+ self.maxSpeed = 8;
+ self.rotation = 0;
+ self.health = 100;
+ self.canShoot = true;
+ self.shootCooldown = 0;
+ self.update = function () {
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ self.velocityX *= self.friction;
+ self.velocityY *= self.friction;
+ var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
+ if (speed > self.maxSpeed) {
+ var ratio = self.maxSpeed / speed;
+ self.velocityX *= ratio;
+ self.velocityY *= ratio;
+ }
+ if (self.x < 40) self.x = 40;
+ if (self.x > 2008) self.x = 2008;
+ if (self.y < 40) self.y = 40;
+ if (self.y > 2692) self.y = 2692;
+ shipGraphics.rotation = self.rotation + Math.PI / 2;
+ if (self.shootCooldown > 0) {
+ self.shootCooldown--;
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x0a0e27
+});
+
+/****
+* Game Code
+****/
+var playerShip = game.addChild(new PlayerShip());
+playerShip.x = 1024;
+playerShip.y = 1366;
+var enemies = [];
+var bullets = [];
+var particles = [];
+var score = 0;
+var health = 100;
+var spawnRate = 60;
+var spawnCounter = 0;
+var scoreTxt = new Text2('Score: 0', {
+ size: 100,
+ fill: 0x00FF00
+});
+scoreTxt.anchor.set(0, 0);
+LK.gui.top.addChild(scoreTxt);
+var healthTxt = new Text2('Health: 100', {
+ size: 100,
+ fill: 0xFF0000
+});
+healthTxt.anchor.set(1, 0);
+LK.gui.top.addChild(healthTxt);
+var keysPressed = {
+ w: false,
+ a: false,
+ s: false,
+ d: false
+};
+var mouseX = 1024;
+var mouseY = 1366;
+function createParticleExplosion(x, y) {
+ var particleCount = 12;
+ for (var i = 0; i < particleCount; i++) {
+ var particle = game.addChild(new Particle());
+ particle.x = x;
+ particle.y = y;
+ var angle = i / particleCount * Math.PI * 2;
+ var speed = 3 + Math.random() * 2;
+ particle.velocityX = Math.cos(angle) * speed;
+ particle.velocityY = Math.sin(angle) * speed;
+ var colors = [0xff0000, 0xff00ff, 0x00ffff, 0xffff00];
+ particle.color = colors[Math.floor(Math.random() * colors.length)];
+ particle.children[0].tint = particle.color;
+ particles.push(particle);
+ }
+ LK.getSound('explosion').play();
+}
+function spawnEnemy() {
+ var enemy = game.addChild(new Enemy());
+ var side = Math.floor(Math.random() * 4);
+ if (side === 0) {
+ enemy.x = Math.random() * 2048;
+ enemy.y = -30;
+ } else if (side === 1) {
+ enemy.x = 2048 + 30;
+ enemy.y = Math.random() * 2732;
+ } else if (side === 2) {
+ enemy.x = Math.random() * 2048;
+ enemy.y = 2732 + 30;
+ } else {
+ enemy.x = -30;
+ enemy.y = Math.random() * 2732;
+ }
+ var dx = playerShip.x - enemy.x;
+ var dy = playerShip.y - enemy.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ enemy.velocityX = dx / distance * enemy.speed;
+ enemy.velocityY = dy / distance * enemy.speed;
+ }
+ enemies.push(enemy);
+}
+game.move = function (x, y, obj) {
+ mouseX = x;
+ mouseY = y;
+ var dx = mouseX - playerShip.x;
+ var dy = mouseY - playerShip.y;
+ playerShip.rotation = Math.atan2(dy, dx);
+};
+game.down = function (x, y, obj) {
+ if (playerShip.shootCooldown <= 0) {
+ var bullet = game.addChild(new Bullet());
+ bullet.x = playerShip.x;
+ bullet.y = playerShip.y;
+ bullet.velocityX = Math.cos(playerShip.rotation) * bullet.speed;
+ bullet.velocityY = Math.sin(playerShip.rotation) * bullet.speed;
+ bullets.push(bullet);
+ playerShip.shootCooldown = 8;
+ LK.getSound('shoot').play();
+ }
+};
+game.update = function () {
+ spawnCounter++;
+ if (spawnCounter > spawnRate) {
+ spawnEnemy();
+ spawnCounter = 0;
+ if (spawnRate > 15) {
+ spawnRate = Math.max(15, 60 - Math.floor(score / 5));
+ }
+ }
+ if (keysPressed.w) {
+ playerShip.velocityX += Math.cos(playerShip.rotation) * playerShip.acceleration;
+ playerShip.velocityY += Math.sin(playerShip.rotation) * playerShip.acceleration;
+ }
+ if (keysPressed.a) {
+ playerShip.velocityX += Math.cos(playerShip.rotation - Math.PI / 2) * playerShip.acceleration;
+ playerShip.velocityY += Math.sin(playerShip.rotation - Math.PI / 2) * playerShip.acceleration;
+ }
+ if (keysPressed.s) {
+ playerShip.velocityX += Math.cos(playerShip.rotation + Math.PI) * playerShip.acceleration;
+ playerShip.velocityY += Math.sin(playerShip.rotation + Math.PI) * playerShip.acceleration;
+ }
+ if (keysPressed.d) {
+ playerShip.velocityX += Math.cos(playerShip.rotation + Math.PI / 2) * playerShip.acceleration;
+ playerShip.velocityY += Math.sin(playerShip.rotation + Math.PI / 2) * playerShip.acceleration;
+ }
+ for (var b = bullets.length - 1; b >= 0; b--) {
+ var bullet = bullets[b];
+ if (bullet.lifetime === undefined) bullet.lifetime = 0;
+ if (bullet.lastY === undefined) bullet.lastY = bullet.y;
+ for (var e = enemies.length - 1; e >= 0; e--) {
+ var enemy = enemies[e];
+ if (bullet.intersects(enemy)) {
+ createParticleExplosion(enemy.x, enemy.y);
+ LK.setScore(LK.getScore() + 1);
+ score = LK.getScore();
+ scoreTxt.setText('Score: ' + score);
+ enemy.destroy();
+ enemies.splice(e, 1);
+ bullet.destroy();
+ bullets.splice(b, 1);
+ break;
+ }
+ }
+ }
+ for (var e = enemies.length - 1; e >= 0; e--) {
+ var enemy = enemies[e];
+ if (enemy.lastIntersecting === undefined) enemy.lastIntersecting = false;
+ var currentIntersecting = enemy.intersects(playerShip);
+ if (!enemy.lastIntersecting && currentIntersecting) {
+ health -= 10;
+ playerShip.health = health;
+ healthTxt.setText('Health: ' + health);
+ if (health <= 0) {
+ LK.showGameOver();
+ }
+ LK.effects.flashObject(playerShip, 0xff0000, 300);
+ }
+ enemy.lastIntersecting = currentIntersecting;
+ if (enemy.x < -100 || enemy.x > 2148 || enemy.y < -100 || enemy.y > 2832) {
+ enemy.destroy();
+ enemies.splice(e, 1);
+ }
+ }
+ for (var p = particles.length - 1; p >= 0; p--) {
+ var particle = particles[p];
+ if (particle.lifetime > particle.maxLifetime) {
+ particle.destroy();
+ particles.splice(p, 1);
+ }
+ }
+};
+document.addEventListener('keydown', function (e) {
+ var key = String.fromCharCode(e.keyCode).toLowerCase();
+ if (key === 'w') keysPressed.w = true;
+ if (key === 'a') keysPressed.a = true;
+ if (key === 's') keysPressed.s = true;
+ if (key === 'd') keysPressed.d = true;
+});
+document.addEventListener('keyup', function (e) {
+ var key = String.fromCharCode(e.keyCode).toLowerCase();
+ if (key === 'w') keysPressed.w = false;
+ if (key === 'a') keysPressed.a = false;
+ if (key === 's') keysPressed.s = false;
+ if (key === 'd') keysPressed.d = false;
+});
+LK.playMusic('bgmusic', {
+ loop: true
});
\ No newline at end of file
"A funny 2D game character concept art. A glass fishbowl filled with water serving as the head. Inside the bowl, a small confused orange goldfish is swimming. The body is an extremely muscular mechanical robot body wearing a tight formal business suit. The character is holding a giant fish landing net as a weapon. Cartoon style, absurd, vibrant colors, clean vector lines.". In-Game asset. 2d. High contrast. No shadows
: Water bubble. In-Game asset. 2d. High contrast. No shadows
Red crab enemy. In-Game asset. 2d. High contrast. No shadows
red heart. In-Game asset. 2d. High contrast. No shadows
sungerbob benzerı ama aynısı degıl. In-Game asset. 2d. High contrast. No shadows
her renkten noktalar. In-Game asset. 2d. High contrast. No shadows
ICI BOS SARI DAIRE SADECE KENALARINDA SARI CIZGI OLACAK. In-Game asset. 2d. High contrast. No shadows