User prompt
you remember that code you wrote for the randomized enemy speed? can you decrease the range? some of them are really fast
User prompt
alright
User prompt
option A sounds awesome, and i want you to add that "READY" text on it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
can you add another thing called "periscope"? i want you to add it as a text over the health text, its gonna show how much time its gonna take for the bullet to arrive
User prompt
make an arrow that points to the ground and i want it to appear on the place i click for a second, like a mark ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
can you check again? my shells always go up no matter where i aim
User prompt
wait, not the movement of the bullets, they should be normal
User prompt
shells that the enemies and i shoot are horizontal, can you fix it? and can you make a code so the enemy tanks are different? like, the current speed is x, make a code so their speed can be something random between x-5 and x+5?
User prompt
yes, those changes
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'cooldownText.style.fill = 0x00FF00;' Line Number: 279
User prompt
theres to many enemies, i want you to make a code so theres maximum 4 enemies at the same time, and add a timer so i can see my cooldown to shoot
User prompt
not only the player, do the same to the enemies
User prompt
decrease the damage to 5, its almost impossible, and make the delay of shooting 5 seconds
User prompt
make the enemy tanks colour more like cream, or sand, and enemies arent dying, i tested it
Code edit (1 edits merged)
Please save this source code
User prompt
Steel Thunder: 2D Tank Combat
Initial prompt
i want you to make me a game like doom, 2d but like its 3d, but its not gonna be doom, i want you to make a tank game, use japanese tanks like ho-ri for the tanks that the player can use, use american tanks like patton series or t49 for the enemy tanks. enemies will be AI, its gonna be single player
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.damage = 5;
self.directionX = 0;
self.directionY = 1;
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
};
return self;
});
var EnemyTank = Container.expand(function () {
var self = Container.call(this);
var hull = self.attachAsset('enemyTank', {
anchorX: 0.5,
anchorY: 0.5
});
var turret = self.attachAsset('enemyTurret', {
anchorX: 0.1,
anchorY: 0.5
});
self.health = 60;
self.maxHealth = 60;
self.speed = 1.5 + (Math.random() * 10 - 5); // Random speed between -3.5 and 6.5
self.lastFireTime = 0;
self.fireRate = 5000;
self.lastMoveTime = 0;
self.moveInterval = 2000;
self.targetX = self.x;
self.targetY = self.y;
// Create health bar
self.healthBarBg = self.attachAsset('enemyTank', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 8
});
self.healthBarBg.tint = 0xFF0000;
self.healthBarBg.x = 0;
self.healthBarBg.y = -50;
self.healthBarFg = self.attachAsset('enemyTank', {
anchorX: 0,
anchorY: 0.5,
width: 80,
height: 6
});
self.healthBarFg.tint = 0x00FF00;
self.healthBarFg.x = -40;
self.healthBarFg.y = -50;
self.update = function () {
// Move towards target position
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
hull.rotation = Math.atan2(dy, dx);
}
// Set new random target occasionally
if (Date.now() - self.lastMoveTime > self.moveInterval) {
self.lastMoveTime = Date.now();
self.targetX = Math.random() * 1800 + 124;
self.targetY = Math.random() * 2400 + 166;
}
// Aim at player
if (playerTank) {
var playerDx = playerTank.x - self.x;
var playerDy = playerTank.y - self.y;
var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy);
if (playerDistance < 800) {
turret.rotation = Math.atan2(playerDy, playerDx);
// Fire at player
if (Date.now() - self.lastFireTime > self.fireRate) {
self.lastFireTime = Date.now();
var bullet = new EnemyBullet();
// Position bullet at turret tip
var turretLength = 70;
bullet.x = self.x + Math.cos(turret.rotation) * turretLength;
bullet.y = self.y + Math.sin(turret.rotation) * turretLength;
// Set bullet direction towards player
bullet.directionX = playerDx / playerDistance;
bullet.directionY = playerDy / playerDistance;
enemyBullets.push(bullet);
game.addChild(bullet);
}
}
}
// Update health bar
var healthPercent = self.health / self.maxHealth;
self.healthBarFg.width = 80 * healthPercent;
if (healthPercent > 0.6) {
self.healthBarFg.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
self.healthBarFg.tint = 0xFFFF00; // Yellow
} else {
self.healthBarFg.tint = 0xFF0000; // Red
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
// Create explosion
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = self.x;
explosion.y = self.y;
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
explosion.destroy();
}
});
LK.getSound('explosion').play();
LK.setScore(LK.getScore() + 100);
scoreText.setText(LK.getScore());
// Remove from parent and mark for removal
self.destroy();
return true; // Tank destroyed
}
return false;
};
return self;
});
var GroundMarker = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 1.0
});
// Rotate to point downward
arrowGraphics.rotation = Math.PI;
// Start with full opacity
self.alpha = 1.0;
// Animate the marker to fade out over 1 second
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 25;
self.directionX = 0;
self.directionY = -1;
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
};
return self;
});
var PlayerTank = Container.expand(function () {
var self = Container.call(this);
var hull = self.attachAsset('playerTank', {
anchorX: 0.5,
anchorY: 0.5
});
var turret = self.attachAsset('playerTurret', {
anchorX: 0.1,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 3;
self.turretRotation = 0;
self.lastFireTime = 0;
self.fireRate = 5000; // milliseconds between shots
self.moveTo = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
// Rotate hull to face movement direction
hull.rotation = Math.atan2(dy, dx);
}
};
self.aimTurret = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
self.turretRotation = Math.atan2(dy, dx);
turret.rotation = self.turretRotation;
};
self.canFire = function () {
return Date.now() - self.lastFireTime > self.fireRate;
};
self.fire = function () {
if (self.canFire()) {
self.lastFireTime = Date.now();
var bullet = new PlayerBullet();
// Position bullet at turret tip
var turretLength = 80;
bullet.x = self.x + Math.cos(self.turretRotation) * turretLength;
bullet.y = self.y + Math.sin(self.turretRotation) * turretLength;
// Set bullet direction based on turret rotation
bullet.directionX = Math.cos(self.turretRotation);
bullet.directionY = Math.sin(self.turretRotation);
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('tankFire').play();
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.destroy();
LK.showGameOver();
}
};
return self;
});
var ReloadIndicator = Container.expand(function () {
var self = Container.call(this);
// Create background circle
self.bgCircle = self.attachAsset('enemyTank', {
anchorX: 0.5,
anchorY: 0.5,
width: 50,
height: 50
});
self.bgCircle.tint = 0x444444;
// Create progress circle
self.progressCircle = self.attachAsset('enemyTank', {
anchorX: 0.5,
anchorY: 0.5,
width: 46,
height: 46
});
self.progressCircle.tint = 0x00FF00;
// Create ready text
self.readyText = new Text2('READY', {
size: 20,
fill: 0x00FF00
});
self.readyText.anchor.set(0.5, 0.5);
self.addChild(self.readyText);
self.updateProgress = function (progress, isReady) {
if (isReady) {
self.progressCircle.visible = false;
self.readyText.visible = true;
self.bgCircle.tint = 0x00AA00;
} else {
self.progressCircle.visible = true;
self.readyText.visible = false;
self.bgCircle.tint = 0x444444;
// Scale progress circle based on reload progress
var scale = progress;
self.progressCircle.scaleX = scale;
self.progressCircle.scaleY = scale;
// Color transition from red to green
var red = Math.floor(255 * (1 - progress));
var green = Math.floor(255 * progress);
self.progressCircle.tint = red << 16 | green << 8 | 0;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x3d5a27
});
/****
* Game Code
****/
var playerTank = null;
var enemyTanks = [];
var playerBullets = [];
var enemyBullets = [];
var gameStartTime = Date.now();
var lastEnemySpawn = 0;
var enemySpawnRate = 3000;
var maxEnemies = 4;
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -200;
scoreText.y = 20;
var healthText = new Text2('Health: 100', {
size: 60,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(healthText);
healthText.x = 20;
healthText.y = -80;
// Reload indicator that follows cursor
var reloadIndicator = game.addChild(new ReloadIndicator());
var periscopeText = new Text2('Periscope: --', {
size: 50,
fill: 0x00FFFF
});
periscopeText.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(periscopeText);
periscopeText.x = 20;
periscopeText.y = -140;
// Create player tank
playerTank = game.addChild(new PlayerTank());
playerTank.x = 1024;
playerTank.y = 2200;
// Touch controls
var targetX = playerTank.x;
var targetY = playerTank.y;
var aimX = playerTank.x;
var aimY = playerTank.y;
game.down = function (x, y, obj) {
targetX = x;
targetY = y;
aimX = x;
aimY = y;
// Create ground marker at click position
var marker = new GroundMarker();
marker.x = x;
marker.y = y;
game.addChild(marker);
};
game.move = function (x, y, obj) {
aimX = x;
aimY = y;
};
game.up = function (x, y, obj) {
if (playerTank) {
playerTank.fire();
}
};
game.update = function () {
if (!playerTank) return;
// Update player tank
playerTank.moveTo(targetX, targetY);
playerTank.aimTurret(aimX, aimY);
// Update health display
healthText.setText('Health: ' + playerTank.health);
// Update reload indicator position and progress
reloadIndicator.x = aimX - 80; // Position to the left of cursor
reloadIndicator.y = aimY - 30; // Slightly above cursor
// Keep indicator within screen bounds
reloadIndicator.x = Math.max(50, Math.min(1998, reloadIndicator.x));
reloadIndicator.y = Math.max(50, Math.min(2682, reloadIndicator.y));
var timeSinceLastFire = Date.now() - playerTank.lastFireTime;
var remainingCooldown = Math.max(0, playerTank.fireRate - timeSinceLastFire);
var progress = 1 - remainingCooldown / playerTank.fireRate;
var isReady = remainingCooldown <= 0;
reloadIndicator.updateProgress(progress, isReady);
// Update periscope display - calculate bullet travel time to target
var distanceToTarget = Math.sqrt((aimX - playerTank.x) * (aimX - playerTank.x) + (aimY - playerTank.y) * (aimY - playerTank.y));
var bulletSpeed = 8; // PlayerBullet speed
var travelTime = distanceToTarget / bulletSpeed / 60; // Convert to seconds (60 FPS)
periscopeText.setText('Periscope: ' + travelTime.toFixed(1) + 's');
// Spawn enemies
if (Date.now() - lastEnemySpawn > enemySpawnRate && enemyTanks.length < maxEnemies) {
lastEnemySpawn = Date.now();
var enemy = new EnemyTank();
// Spawn at random edge
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 1800 + 124;
enemy.y = 100;
break;
case 1:
// Right
enemy.x = 1900;
enemy.y = Math.random() * 2400 + 166;
break;
case 2:
// Bottom
enemy.x = Math.random() * 1800 + 124;
enemy.y = 2600;
break;
case 3:
// Left
enemy.x = 148;
enemy.y = Math.random() * 2400 + 166;
break;
}
enemyTanks.push(enemy);
game.addChild(enemy);
// Increase difficulty over time
var timeElapsed = Date.now() - gameStartTime;
if (timeElapsed > 30000) {
// After 30 seconds
enemySpawnRate = Math.max(1500, enemySpawnRate - 50);
maxEnemies = Math.min(8, maxEnemies + 1);
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Check if bullet is off screen
if (bullet.x < 0 || bullet.x > 2048 || bullet.y < 0 || bullet.y > 2732) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemyTanks.length - 1; j >= 0; j--) {
var enemy = enemyTanks[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(bullet.damage)) {
enemyTanks.splice(j, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
hitEnemy = true;
break;
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet is off screen
if (bullet.x < 0 || bullet.x > 2048 || bullet.y < 0 || bullet.y > 2732) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(playerTank)) {
playerTank.takeDamage(bullet.damage);
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Remove destroyed enemy tanks
for (var i = enemyTanks.length - 1; i >= 0; i--) {
var enemy = enemyTanks[i];
if (!enemy.parent) {
enemyTanks.splice(i, 1);
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -240,8 +240,54 @@
}
};
return self;
});
+var ReloadIndicator = Container.expand(function () {
+ var self = Container.call(this);
+ // Create background circle
+ self.bgCircle = self.attachAsset('enemyTank', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 50,
+ height: 50
+ });
+ self.bgCircle.tint = 0x444444;
+ // Create progress circle
+ self.progressCircle = self.attachAsset('enemyTank', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 46,
+ height: 46
+ });
+ self.progressCircle.tint = 0x00FF00;
+ // Create ready text
+ self.readyText = new Text2('READY', {
+ size: 20,
+ fill: 0x00FF00
+ });
+ self.readyText.anchor.set(0.5, 0.5);
+ self.addChild(self.readyText);
+ self.updateProgress = function (progress, isReady) {
+ if (isReady) {
+ self.progressCircle.visible = false;
+ self.readyText.visible = true;
+ self.bgCircle.tint = 0x00AA00;
+ } else {
+ self.progressCircle.visible = true;
+ self.readyText.visible = false;
+ self.bgCircle.tint = 0x444444;
+ // Scale progress circle based on reload progress
+ var scale = progress;
+ self.progressCircle.scaleX = scale;
+ self.progressCircle.scaleY = scale;
+ // Color transition from red to green
+ var red = Math.floor(255 * (1 - progress));
+ var green = Math.floor(255 * progress);
+ self.progressCircle.tint = red << 16 | green << 8 | 0;
+ }
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -276,15 +322,10 @@
healthText.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(healthText);
healthText.x = 20;
healthText.y = -80;
-var cooldownText = new Text2('Ready to Fire', {
- size: 50,
- fill: 0x00FF00
-});
-cooldownText.anchor.set(0.5, 0);
-LK.gui.bottom.addChild(cooldownText);
-cooldownText.y = -120;
+// Reload indicator that follows cursor
+var reloadIndicator = game.addChild(new ReloadIndicator());
var periscopeText = new Text2('Periscope: --', {
size: 50,
fill: 0x00FFFF
});
@@ -327,19 +368,19 @@
playerTank.moveTo(targetX, targetY);
playerTank.aimTurret(aimX, aimY);
// Update health display
healthText.setText('Health: ' + playerTank.health);
- // Update cooldown display
+ // Update reload indicator position and progress
+ reloadIndicator.x = aimX - 80; // Position to the left of cursor
+ reloadIndicator.y = aimY - 30; // Slightly above cursor
+ // Keep indicator within screen bounds
+ reloadIndicator.x = Math.max(50, Math.min(1998, reloadIndicator.x));
+ reloadIndicator.y = Math.max(50, Math.min(2682, reloadIndicator.y));
var timeSinceLastFire = Date.now() - playerTank.lastFireTime;
var remainingCooldown = Math.max(0, playerTank.fireRate - timeSinceLastFire);
- if (remainingCooldown > 0) {
- var secondsLeft = Math.ceil(remainingCooldown / 1000);
- cooldownText.setText('Reload: ' + secondsLeft + 's');
- cooldownText.fill = 0xFF4444;
- } else {
- cooldownText.setText('Ready to Fire');
- cooldownText.fill = 0x00FF00;
- }
+ var progress = 1 - remainingCooldown / playerTank.fireRate;
+ var isReady = remainingCooldown <= 0;
+ reloadIndicator.updateProgress(progress, isReady);
// Update periscope display - calculate bullet travel time to target
var distanceToTarget = Math.sqrt((aimX - playerTank.x) * (aimX - playerTank.x) + (aimY - playerTank.y) * (aimY - playerTank.y));
var bulletSpeed = 8; // PlayerBullet speed
var travelTime = distanceToTarget / bulletSpeed / 60; // Convert to seconds (60 FPS)
its the view of a tank turret, but from its top. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
its a tanks hulls top view. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
cartoony explosion effect . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a turretless tank, colour:#f5deb3. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat