User prompt
If I hold it down I can fire
User prompt
I want to move our main character with the right click of the mouse.
User prompt
The bullets fired by our main character should be effective and move faster.
User prompt
Let our main character be at the center of the game
User prompt
Let our main character and enemies be bigger. Let giant enemies come every now and then. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'cost')' in or related to this line: 'if (gamePoints >= weapon.cost && player.weapon.name !== weapon.name) {' Line Number: 335
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'weaponTexts[i].style.fill = color;' Line Number: 326
Code edit (1 edits merged)
Please save this source code
User prompt
Arsenal Defender
Initial prompt
I want to create a game where you eliminate incoming enemies one by one, and earn points for each enemy you eliminate. With those points, you can buy different weapons. I want to upload my own image for the shooting character and also the appearances of the enemies.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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.damage = 1;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 1;
self.points = 10;
self.isGiant = false;
self.velocityX = 0;
self.velocityY = 0;
self.update = function () {
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
}
}
self.x += self.velocityX;
self.y += self.velocityY;
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('enemyHit').play();
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
if (self.health <= 0) {
self.destroy();
return true;
}
return false;
};
self.makeGiant = function () {
self.isGiant = true;
self.health = self.health * 5;
self.maxHealth = self.health;
self.speed = self.speed * 0.7;
self.points = self.points * 4;
// Scale up with tween animation
tween(enemyGraphics, {
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 500,
easing: tween.bounceOut
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.weapon = {
damage: 1,
fireRate: 10,
name: 'Basic Gun'
};
self.lastShot = 0;
self.shoot = function (targetX, targetY) {
if (LK.ticks - self.lastShot < self.weapon.fireRate) return;
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.damage = self.weapon.damage;
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.velocityX = dx / distance * 8;
bullet.velocityY = dy / distance * 8;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game state variables
var player;
var enemies = [];
var bullets = [];
var gamePoints = storage.points || 0;
var wave = storage.wave || 1;
var enemiesKilled = 0;
var enemiesInWave = 5;
var waveComplete = false;
var shopOpen = false;
// Weapon shop data
var weapons = [{
name: 'Basic Gun',
damage: 1,
fireRate: 10,
cost: 0
}, {
name: 'Rapid Fire',
damage: 1,
fireRate: 5,
cost: 50
}, {
name: 'Heavy Cannon',
damage: 3,
fireRate: 20,
cost: 100
}, {
name: 'Sniper Rifle',
damage: 5,
fireRate: 30,
cost: 200
}, {
name: 'Plasma Gun',
damage: 2,
fireRate: 8,
cost: 150
}];
// UI Elements
var pointsText = new Text2('Points: 0', {
size: 40,
fill: 0xFFFFFF
});
pointsText.anchor.set(0, 0);
pointsText.x = 120;
pointsText.y = 20;
LK.gui.topLeft.addChild(pointsText);
var waveText = new Text2('Wave: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 0);
waveText.x = -20;
waveText.y = 20;
LK.gui.topRight.addChild(waveText);
var healthText = new Text2('Health: 100', {
size: 40,
fill: 0xFF4444
});
healthText.anchor.set(0.5, 1);
healthText.y = -20;
LK.gui.bottom.addChild(healthText);
// Shop button
var shopButton = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 120,
y: 2732 - 100
}));
var shopButtonText = new Text2('SHOP', {
size: 32,
fill: 0xFFFFFF
});
shopButtonText.anchor.set(0.5, 0.5);
shopButtonText.x = shopButton.x;
shopButtonText.y = shopButton.y;
game.addChild(shopButtonText);
// Shop UI
var shopContainer = new Container();
shopContainer.visible = false;
game.addChild(shopContainer);
var shopBackground = shopContainer.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 8,
scaleY: 12
}));
var shopTitle = new Text2('WEAPON SHOP', {
size: 60,
fill: 0xFFFFFF
});
shopTitle.anchor.set(0.5, 0.5);
shopTitle.x = 1024;
shopTitle.y = 800;
shopContainer.addChild(shopTitle);
var closeShopButton = shopContainer.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800,
scaleX: 2,
scaleY: 1
}));
var closeShopText = new Text2('CLOSE', {
size: 40,
fill: 0xFFFFFF
});
closeShopText.anchor.set(0.5, 0.5);
closeShopText.x = 1024;
closeShopText.y = 1800;
shopContainer.addChild(closeShopText);
// Weapon shop items
var weaponButtons = [];
var weaponTexts = [];
for (var i = 0; i < weapons.length; i++) {
var weapon = weapons[i];
var buttonY = 1000 + i * 120;
var weaponButton = shopContainer.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: buttonY,
scaleX: 3,
scaleY: 1
}));
weaponButton.weaponIndex = i;
weaponButtons.push(weaponButton);
var weaponText = new Text2(weapon.name + ' - ' + weapon.cost + ' pts', {
size: 32,
fill: 0xFFFFFF
});
weaponText.anchor.set(0.5, 0.5);
weaponText.x = 1024;
weaponText.y = buttonY;
shopContainer.addChild(weaponText);
weaponTexts.push(weaponText);
}
// Initialize player
player = game.addChild(new Player());
player.x = 1024;
player.y = 2200;
// Game functions
function spawnEnemy() {
var enemy = new Enemy();
// Spawn from random edge
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
// Scale enemy with wave
enemy.health = Math.floor(3 + wave * 0.5);
enemy.maxHealth = enemy.health;
enemy.speed = 1 + wave * 0.1;
enemy.points = 10 + wave * 2;
// 15% chance for giant enemy after wave 3
if (wave >= 3 && Math.random() < 0.15) {
enemy.makeGiant();
}
enemies.push(enemy);
game.addChild(enemy);
// Add spawn animation for all enemies
var enemyGraphics = enemy.children[0];
enemyGraphics.scaleX = 0.1;
enemyGraphics.scaleY = 0.1;
tween(enemyGraphics, {
scaleX: enemy.isGiant ? 2.5 : 1,
scaleY: enemy.isGiant ? 2.5 : 1
}, {
duration: 300,
easing: tween.elasticOut
});
}
function updateUI() {
pointsText.setText('Points: ' + gamePoints);
waveText.setText('Wave: ' + wave);
healthText.setText('Health: ' + player.health);
}
function openShop() {
shopOpen = true;
shopContainer.visible = true;
// Update weapon button states
for (var i = 0; i < weapons.length; i++) {
var weapon = weapons[i];
var canAfford = gamePoints >= weapon.cost;
var owned = player.weapon.name === weapon.name;
var colorHex = owned ? 0x00ff00 : canAfford ? 0xffffff : 0x666666;
var text = weapon.name + ' - ' + weapon.cost + ' pts';
if (owned) text = weapon.name + ' - EQUIPPED';
weaponTexts[i].setText(text);
weaponTexts[i].tint = colorHex;
}
}
function closeShop() {
shopOpen = false;
shopContainer.visible = false;
}
function buyWeapon(weaponIndex) {
var weapon = weapons[weaponIndex];
if (weapon && gamePoints >= weapon.cost && player.weapon.name !== weapon.name) {
gamePoints -= weapon.cost;
player.weapon = {
damage: weapon.damage,
fireRate: weapon.fireRate,
name: weapon.name
};
storage.points = gamePoints;
updateUI();
openShop(); // Refresh shop display
}
}
// Event handlers
shopButton.down = function (x, y, obj) {
openShop();
};
closeShopButton.down = function (x, y, obj) {
closeShop();
};
for (var i = 0; i < weaponButtons.length; i++) {
weaponButtons[i].down = function (x, y, obj) {
buyWeapon(obj.weaponIndex);
};
}
game.down = function (x, y, obj) {
if (!shopOpen && player) {
player.shoot(x, y);
}
};
// Spawn initial enemies
for (var i = 0; i < enemiesInWave; i++) {
LK.setTimeout(function () {
spawnEnemy();
}, i * 2000);
}
// Main game loop
game.update = function () {
if (shopOpen) return;
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
var destroyed = enemy.takeDamage(bullet.damage);
if (destroyed) {
gamePoints += enemy.points;
enemiesKilled++;
LK.getSound('enemyDestroy').play();
enemies.splice(j, 1);
}
bullet.destroy();
bullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (hitEnemy) continue;
}
// Check enemy-player collisions
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.intersects(player)) {
player.health -= 10;
enemy.destroy();
enemies.splice(i, 1);
if (player.health <= 0) {
// Game over
storage.points = gamePoints;
storage.wave = wave;
LK.showGameOver();
return;
}
}
}
// Check wave completion
if (enemiesKilled >= enemiesInWave && enemies.length === 0 && !waveComplete) {
waveComplete = true;
wave++;
enemiesKilled = 0;
enemiesInWave = Math.min(5 + wave, 15);
// Spawn next wave after delay
LK.setTimeout(function () {
waveComplete = false;
for (var i = 0; i < enemiesInWave; i++) {
LK.setTimeout(function () {
spawnEnemy();
}, i * 1500);
}
}, 3000);
}
// Periodic enemy spawning during wave
if (!waveComplete && enemies.length < Math.min(enemiesInWave, 8)) {
if (Math.random() < 0.01) {
spawnEnemy();
}
}
updateUI();
// Save progress
if (LK.ticks % 300 === 0) {
storage.points = gamePoints;
storage.wave = wave;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -31,8 +31,9 @@
self.health = 3;
self.maxHealth = 3;
self.speed = 1;
self.points = 10;
+ self.isGiant = false;
self.velocityX = 0;
self.velocityY = 0;
self.update = function () {
if (player) {
@@ -68,8 +69,23 @@
return true;
}
return false;
};
+ self.makeGiant = function () {
+ self.isGiant = true;
+ self.health = self.health * 5;
+ self.maxHealth = self.health;
+ self.speed = self.speed * 0.7;
+ self.points = self.points * 4;
+ // Scale up with tween animation
+ tween(enemyGraphics, {
+ scaleX: 2.5,
+ scaleY: 2.5
+ }, {
+ duration: 500,
+ easing: tween.bounceOut
+ });
+ };
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
@@ -287,10 +303,25 @@
enemy.health = Math.floor(3 + wave * 0.5);
enemy.maxHealth = enemy.health;
enemy.speed = 1 + wave * 0.1;
enemy.points = 10 + wave * 2;
+ // 15% chance for giant enemy after wave 3
+ if (wave >= 3 && Math.random() < 0.15) {
+ enemy.makeGiant();
+ }
enemies.push(enemy);
game.addChild(enemy);
+ // Add spawn animation for all enemies
+ var enemyGraphics = enemy.children[0];
+ enemyGraphics.scaleX = 0.1;
+ enemyGraphics.scaleY = 0.1;
+ tween(enemyGraphics, {
+ scaleX: enemy.isGiant ? 2.5 : 1,
+ scaleY: enemy.isGiant ? 2.5 : 1
+ }, {
+ duration: 300,
+ easing: tween.elasticOut
+ });
}
function updateUI() {
pointsText.setText('Points: ' + gamePoints);
waveText.setText('Wave: ' + wave);