User prompt
The character is still very fast
User prompt
The character is very fast
User prompt
Remove the shop
User prompt
I can't leave the store, fix this
User prompt
I can't get anything from the store and I can't leave
User prompt
Enlarge text in the shop
User prompt
Make the buttons in the shop functional instead of non-functional
User prompt
Have a shop somewhere on the map ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Remove all animations
User prompt
Update
User prompt
The game lags a lot
User prompt
Optimize the game
User prompt
Add grass to the ground and a black barrier at the end of the map
User prompt
Add and expand the map to the game
User prompt
Make the game open world
User prompt
After 5 waves, the game over message should appear.
User prompt
I can't start the game please fix this
User prompt
Make main menu
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(spawnParticle, {' Line Number: 244 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Update 1000 lines
User prompt
Correct the trajectory of bullets
User prompt
Add weapon to character
User prompt
Make it harder
User prompt
Make it harder
Code edit (1 edits merged)
Please save this source code
/****
* 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.speed = 12;
self.directionX = 0;
self.directionY = 0;
self.update = function () {
// Store previous position for trail effect
if (self.lastX === undefined) {
self.lastX = self.x;
self.lastY = self.y;
}
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Create trail particle
if (Math.random() < 0.7) {
var trailParticle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: 0xFFFF88,
alpha: 0.6
});
trailParticle.x = self.lastX;
trailParticle.y = self.lastY;
game.addChild(trailParticle);
// Fade out trail particle
tween(trailParticle, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 200,
onFinish: function onFinish() {
trailParticle.destroy();
}
});
}
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Add weapon to player
var weaponGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
weaponGraphics.x = 25; // Position weapon to the right of player
weaponGraphics.y = 0;
self.speed = 4;
self.health = 1;
self.lastShootTime = 0;
self.shootInterval = 500; // milliseconds
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 1;
self.maxHealth = 1;
// Create health bar background
var healthBarBg = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 0.5,
tint: 0x333333
});
healthBarBg.y = -140;
self.addChild(healthBarBg);
// Create health bar fill
var healthBarFill = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 0.5,
tint: 0xFF0000
});
healthBarFill.y = -140;
self.addChild(healthBarFill);
self.healthBarFill = healthBarFill;
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.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Add pulsing effect based on distance to player
var pulseIntensity = Math.max(0.1, 1 - distance / 500);
var pulseSpeed = self.speed * 0.1;
self.scaleX = 1 + Math.sin(gameTime * pulseSpeed) * pulseIntensity * 0.2;
self.scaleY = 1 + Math.sin(gameTime * pulseSpeed) * pulseIntensity * 0.2;
// Add red tint when close to player
if (distance < 200) {
self.tint = 0xFF6666;
} else {
self.tint = 0xFFFFFF;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E2E2E
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'playing', 'gameOver'
var menuContainer;
var playButton;
// Game variables
var player;
var zombies = [];
var bullets = [];
var dragNode = null;
var gameTime = 0;
var zombieSpawnRate = 50; // frames between spawns
var zombieSpeed = 4;
var zombiesKilled = 0;
var waveNumber = 1;
var comboCount = 0;
var comboTimer = 0;
var comboDecayTime = 180; // 3 seconds at 60fps
var scoreMultiplier = 1;
// Create main menu
menuContainer = new Container();
game.addChild(menuContainer);
// Menu title
var titleTxt = new Text2('ZOMBIE SHOOTER', {
size: 120,
fill: 0xFF4444
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 2048 / 2;
titleTxt.y = 2732 / 2 - 200;
menuContainer.addChild(titleTxt);
// Play button background
var playButtonBg = LK.getAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8,
tint: 0x44AA44
});
playButtonBg.x = 2048 / 2;
playButtonBg.y = 2732 / 2 + 50;
menuContainer.addChild(playButtonBg);
// Play button text
var playButtonTxt = new Text2('PLAY', {
size: 80,
fill: 0xFFFFFF
});
playButtonTxt.anchor.set(0.5, 0.5);
playButtonTxt.x = 2048 / 2;
playButtonTxt.y = 2732 / 2 + 50;
menuContainer.addChild(playButtonTxt);
// Store reference to play button for event handling
playButton = playButtonBg;
// Game UI Elements (initially hidden)
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
waveTxt.x = 20;
waveTxt.y = 20;
waveTxt.visible = false;
LK.gui.topLeft.addChild(waveTxt);
var timeTxt = new Text2('Time: 0s', {
size: 50,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
timeTxt.x = -20;
timeTxt.y = 20;
timeTxt.visible = false;
LK.gui.topRight.addChild(timeTxt);
var comboTxt = new Text2('', {
size: 80,
fill: 0xFFAA00
});
comboTxt.anchor.set(0.5, 0.5);
comboTxt.visible = false;
LK.gui.center.addChild(comboTxt);
// Game initialization function
function initializeGame() {
// Reset game variables
gameTime = 0;
zombiesKilled = 0;
waveNumber = 1;
comboCount = 0;
comboTimer = 0;
scoreMultiplier = 1;
zombieSpawnRate = 50;
zombieSpeed = 4;
// Clear existing game objects
if (player) {
player.destroy();
}
for (var i = 0; i < zombies.length; i++) {
zombies[i].destroy();
}
for (var j = 0; j < bullets.length; j++) {
bullets[j].destroy();
}
zombies = [];
bullets = [];
// Initialize player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 / 2;
// Reset score
LK.setScore(0);
scoreTxt.setText('Score: 0');
// Show game UI
scoreTxt.visible = true;
waveTxt.visible = true;
timeTxt.visible = true;
comboTxt.visible = true;
// Hide menu
menuContainer.visible = false;
// Set game state
gameState = 'playing';
}
// Don't initialize player immediately - wait for menu interaction
// Helper functions
function spawnZombie() {
var zombie = new Zombie();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// top
zombie.x = Math.random() * 2048;
zombie.y = -50;
break;
case 1:
// right
zombie.x = 2048 + 50;
zombie.y = Math.random() * 2732;
break;
case 2:
// bottom
zombie.x = Math.random() * 2048;
zombie.y = 2732 + 50;
break;
case 3:
// left
zombie.x = -50;
zombie.y = Math.random() * 2732;
break;
}
zombie.speed = zombieSpeed;
// Add spawn effect - start small and grow
zombie.scaleX = 0.1;
zombie.scaleY = 0.1;
zombie.alpha = 0.3;
// Create spawn particles
for (var sp = 0; sp < 6; sp++) {
var spawnParticle = LK.getAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0x00FF00,
alpha: 0.8
});
spawnParticle.x = zombie.x;
spawnParticle.y = zombie.y;
var angle = sp / 6 * Math.PI * 2;
spawnParticle.velocityX = Math.cos(angle) * 3;
spawnParticle.velocityY = Math.sin(angle) * 3;
game.addChild(spawnParticle);
// Animate spawn particles
tween(spawnParticle, {
alpha: 0,
scaleX: 0.05,
scaleY: 0.05,
x: spawnParticle.x + spawnParticle.velocityX * 20,
y: spawnParticle.y + spawnParticle.velocityY * 20
}, {
duration: 400,
onFinish: function onFinish() {
spawnParticle.destroy();
}
});
}
// Animate zombie growth
tween(zombie, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 500
});
zombies.push(zombie);
game.addChild(zombie);
}
function findNearestZombie() {
var nearestZombie = null;
var nearestDistance = Infinity;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var dx = zombie.x - player.x;
var dy = zombie.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestZombie = zombie;
}
}
return nearestZombie;
}
function shootBullet() {
var target = findNearestZombie();
if (!target) return;
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
// Calculate zombie's movement direction
var zombieDx = player.x - target.x;
var zombieDy = player.y - target.y;
var zombieDistance = Math.sqrt(zombieDx * zombieDx + zombieDy * zombieDy);
var zombieDirectionX = zombieDistance > 0 ? zombieDx / zombieDistance : 0;
var zombieDirectionY = zombieDistance > 0 ? zombieDy / zombieDistance : 0;
// Predict where zombie will be
var timeToTarget = zombieDistance / bullet.speed;
var predictedX = target.x + zombieDirectionX * target.speed * timeToTarget;
var predictedY = target.y + zombieDirectionY * target.speed * timeToTarget;
// Aim at predicted position
var dx = predictedX - player.x;
var dy = predictedY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.directionX = dx / distance;
bullet.directionY = dy / distance;
}
// Create muzzle flash effect
var muzzleFlash = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3,
tint: 0xFFFF00,
alpha: 0.8
});
muzzleFlash.x = player.x + 25; // Position at weapon location
muzzleFlash.y = player.y;
game.addChild(muzzleFlash);
// Animate muzzle flash fade out
tween(muzzleFlash, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
muzzleFlash.destroy();
}
});
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
function updateDifficulty() {
waveNumber = Math.floor(gameTime / 1200) + 1; // New wave every 20 seconds
zombieSpawnRate = Math.max(15, 50 - waveNumber * 8);
zombieSpeed = 4 + (waveNumber - 1) * 1.2;
waveTxt.setText('Wave: ' + waveNumber);
}
// Event handlers
function handleMove(x, y, obj) {
if (dragNode) {
// Keep player within screen bounds
dragNode.x = Math.max(30, Math.min(2048 - 30, x));
dragNode.y = Math.max(30, Math.min(2732 - 30, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if play button was clicked
var localPos = menuContainer.toLocal({
x: x,
y: y
});
if (playButton.getBounds().contains(localPos.x, localPos.y)) {
initializeGame();
}
} else if (gameState === 'playing') {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game loop
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') {
return;
}
gameTime++;
// Update UI
timeTxt.setText('Time: ' + Math.floor(gameTime / 60) + 's');
// Update combo system
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0) {
comboCount = 0;
scoreMultiplier = 1;
comboTxt.setText('');
}
}
// Update difficulty
updateDifficulty();
// Spawn zombies
if (gameTime % zombieSpawnRate === 0) {
spawnZombie();
// Spawn additional zombies in later waves
if (waveNumber >= 2 && gameTime % (zombieSpawnRate * 2) === 0) {
spawnZombie();
}
if (waveNumber >= 3 && gameTime % (zombieSpawnRate * 3) === 0) {
spawnZombie();
}
if (waveNumber >= 4 && gameTime % (zombieSpawnRate * 4) === 0) {
spawnZombie();
}
}
// Auto-shoot
if (gameTime % 60 === 0) {
// Shoot every 1 second
shootBullet();
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Remove bullets that are off screen
if (bullet.x < -100 || bullet.x > 2148 || bullet.y < -100 || bullet.y > 2832) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-zombie collisions
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (bullet.intersects(zombie)) {
// Zombie hit
LK.getSound('zombieHit').play();
// Update combo system
comboCount++;
comboTimer = comboDecayTime;
scoreMultiplier = Math.min(5, 1 + Math.floor(comboCount / 3));
// Show combo text
if (comboCount > 2) {
comboTxt.setText('COMBO x' + scoreMultiplier);
comboTxt.alpha = 1;
comboTxt.scaleX = 1.5;
comboTxt.scaleY = 1.5;
// Animate combo text
tween(comboTxt, {
scaleX: 1,
scaleY: 1,
alpha: 0.7
}, {
duration: 300
});
}
// Create explosion effect at zombie position
var explosionParticles = [];
for (var p = 0; p < 8; p++) {
var particle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFF4444
});
particle.x = zombie.x;
particle.y = zombie.y;
var angle = p / 8 * Math.PI * 2;
particle.velocityX = Math.cos(angle) * 8;
particle.velocityY = Math.sin(angle) * 8;
particle.life = 30;
explosionParticles.push(particle);
game.addChild(particle);
}
// Animate explosion particles
var _animateExplosion = function animateExplosion() {
for (var ep = explosionParticles.length - 1; ep >= 0; ep--) {
var particle = explosionParticles[ep];
particle.x += particle.velocityX;
particle.y += particle.velocityY;
particle.velocityX *= 0.9;
particle.velocityY *= 0.9;
particle.alpha = particle.life / 30;
particle.life--;
if (particle.life <= 0) {
particle.destroy();
explosionParticles.splice(ep, 1);
}
}
if (explosionParticles.length > 0) {
LK.setTimeout(_animateExplosion, 16);
}
};
_animateExplosion();
zombie.destroy();
zombies.splice(j, 1);
bullet.destroy();
bullets.splice(i, 1);
zombiesKilled++;
LK.setScore(LK.getScore() + 10 * scoreMultiplier + Math.floor(gameTime / 60));
scoreTxt.setText('Score: ' + LK.getScore());
// Flash effect
LK.effects.flashObject(zombie, 0xFF0000, 200);
break;
}
}
}
// Check player-zombie collisions
for (var k = 0; k < zombies.length; k++) {
var zombie = zombies[k];
if (player.intersects(zombie)) {
// Player hit - game over
// Add screen shake effect
var shakeIntensity = 20;
var shakeDuration = 60;
var shakeFrames = 0;
var originalX = game.x;
var originalY = game.y;
var _shakeEffect = function shakeEffect() {
if (shakeFrames < shakeDuration) {
game.x = originalX + (Math.random() - 0.5) * shakeIntensity;
game.y = originalY + (Math.random() - 0.5) * shakeIntensity;
shakeFrames++;
LK.setTimeout(_shakeEffect, 16);
} else {
game.x = originalX;
game.y = originalY;
}
};
_shakeEffect();
LK.effects.flashScreen(0xFF0000, 1000);
// Reset to menu state
gameState = 'menu';
menuContainer.visible = true;
scoreTxt.visible = false;
waveTxt.visible = false;
timeTxt.visible = false;
comboTxt.visible = false;
LK.showGameOver();
return;
}
}
// Remove zombies that are too far off screen (cleanup)
for (var l = zombies.length - 1; l >= 0; l--) {
var zombie = zombies[l];
if (zombie.x < -200 || zombie.x > 2248 || zombie.y < -200 || zombie.y > 2932) {
zombie.destroy();
zombies.splice(l, 1);
}
}
};
// Start background music
LK.playMusic('bgmusic'); ===================================================================
--- original.js
+++ change.js
@@ -138,8 +138,12 @@
/****
* Game Code
****/
+// Game state management
+var gameState = 'menu'; // 'menu', 'playing', 'gameOver'
+var menuContainer;
+var playButton;
// Game variables
var player;
var zombies = [];
var bullets = [];
@@ -152,41 +156,116 @@
var comboCount = 0;
var comboTimer = 0;
var comboDecayTime = 180; // 3 seconds at 60fps
var scoreMultiplier = 1;
-// UI Elements
+// Create main menu
+menuContainer = new Container();
+game.addChild(menuContainer);
+// Menu title
+var titleTxt = new Text2('ZOMBIE SHOOTER', {
+ size: 120,
+ fill: 0xFF4444
+});
+titleTxt.anchor.set(0.5, 0.5);
+titleTxt.x = 2048 / 2;
+titleTxt.y = 2732 / 2 - 200;
+menuContainer.addChild(titleTxt);
+// Play button background
+var playButtonBg = LK.getAsset('zombie', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1.5,
+ scaleY: 0.8,
+ tint: 0x44AA44
+});
+playButtonBg.x = 2048 / 2;
+playButtonBg.y = 2732 / 2 + 50;
+menuContainer.addChild(playButtonBg);
+// Play button text
+var playButtonTxt = new Text2('PLAY', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+playButtonTxt.anchor.set(0.5, 0.5);
+playButtonTxt.x = 2048 / 2;
+playButtonTxt.y = 2732 / 2 + 50;
+menuContainer.addChild(playButtonTxt);
+// Store reference to play button for event handling
+playButton = playButtonBg;
+// Game UI Elements (initially hidden)
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
+scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
waveTxt.x = 20;
waveTxt.y = 20;
+waveTxt.visible = false;
LK.gui.topLeft.addChild(waveTxt);
var timeTxt = new Text2('Time: 0s', {
size: 50,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
timeTxt.x = -20;
timeTxt.y = 20;
+timeTxt.visible = false;
LK.gui.topRight.addChild(timeTxt);
var comboTxt = new Text2('', {
size: 80,
fill: 0xFFAA00
});
comboTxt.anchor.set(0.5, 0.5);
+comboTxt.visible = false;
LK.gui.center.addChild(comboTxt);
-// Initialize player
-player = game.addChild(new Player());
-player.x = 2048 / 2;
-player.y = 2732 / 2;
+// Game initialization function
+function initializeGame() {
+ // Reset game variables
+ gameTime = 0;
+ zombiesKilled = 0;
+ waveNumber = 1;
+ comboCount = 0;
+ comboTimer = 0;
+ scoreMultiplier = 1;
+ zombieSpawnRate = 50;
+ zombieSpeed = 4;
+ // Clear existing game objects
+ if (player) {
+ player.destroy();
+ }
+ for (var i = 0; i < zombies.length; i++) {
+ zombies[i].destroy();
+ }
+ for (var j = 0; j < bullets.length; j++) {
+ bullets[j].destroy();
+ }
+ zombies = [];
+ bullets = [];
+ // Initialize player
+ player = game.addChild(new Player());
+ player.x = 2048 / 2;
+ player.y = 2732 / 2;
+ // Reset score
+ LK.setScore(0);
+ scoreTxt.setText('Score: 0');
+ // Show game UI
+ scoreTxt.visible = true;
+ waveTxt.visible = true;
+ timeTxt.visible = true;
+ comboTxt.visible = true;
+ // Hide menu
+ menuContainer.visible = false;
+ // Set game state
+ gameState = 'playing';
+}
+// Don't initialize player immediately - wait for menu interaction
// Helper functions
function spawnZombie() {
var zombie = new Zombie();
var side = Math.floor(Math.random() * 4);
@@ -339,16 +418,31 @@
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
- dragNode = player;
- handleMove(x, y, obj);
+ if (gameState === 'menu') {
+ // Check if play button was clicked
+ var localPos = menuContainer.toLocal({
+ x: x,
+ y: y
+ });
+ if (playButton.getBounds().contains(localPos.x, localPos.y)) {
+ initializeGame();
+ }
+ } else if (gameState === 'playing') {
+ dragNode = player;
+ handleMove(x, y, obj);
+ }
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game loop
game.update = function () {
+ // Only update game logic when playing
+ if (gameState !== 'playing') {
+ return;
+ }
gameTime++;
// Update UI
timeTxt.setText('Time: ' + Math.floor(gameTime / 60) + 's');
// Update combo system
@@ -490,8 +584,15 @@
}
};
_shakeEffect();
LK.effects.flashScreen(0xFF0000, 1000);
+ // Reset to menu state
+ gameState = 'menu';
+ menuContainer.visible = true;
+ scoreTxt.visible = false;
+ waveTxt.visible = false;
+ timeTxt.visible = false;
+ comboTxt.visible = false;
LK.showGameOver();
return;
}
}