User prompt
Optimise the framerate by optimising all the code
User prompt
Improve the framerate with 10 new optimisation
User prompt
Improve all the code
User prompt
Improve all the code
User prompt
Improve the framerate with 10 new optimisation
User prompt
Improve a lot the framerate with 5 new optimisation
User prompt
optimise a lot the framerate
User prompt
double again the number of soldier at each wave
User prompt
double the number of soldier at each wave
User prompt
Improve a lot the framerate
User prompt
Optimise the framerate
User prompt
Migrate to the latest version of LK
Remix started
Copy Ask the AI to optimise the game
/**** * Classes ****/ var Bullet = Container.expand(function (gameInstance) { var self = Container.call(this); self.game = gameInstance; self.game = gameInstance; var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self._move_migrated = function () { self.x += 240; if (self.x > 2148) { self.destroy(); } }; }); var Enemy = Container.expand(function (gameInstance) { var self = Container.call(this); self.game = gameInstance; var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self._move_migrated = function () { self.y += 25.6 * 0.7 * 0.6; if (self.y > 2732) { self.destroy(); } }; }); var FrameRateCounter = Container.expand(function () { var self = Container.call(this); self.lastTime = Date.now(); self.frameCount = 0; self.framerate = 0; self.display = new Text2('FPS: 0', { size: 150, fill: '#000000' }); self.display.anchor.set(1, 0); self.updateDisplay = function () { self.display.setText('FPS: ' + Math.round(self.framerate).toString()); }; self._update_migrated = function () { var currentTime = Date.now(); self.frameCount++; if (currentTime - self.lastTime >= 1000) { self.framerate = self.frameCount; self.updateDisplay(); self.frameCount = 0; self.lastTime = currentTime; } }; }); var Plain = Container.expand(function () { var self = Container.call(this); var plainGraphics = self.attachAsset('correct_plain_asset_id', { anchorX: 0.5, anchorY: 0.5 }); plainGraphics.scale.x = 2; plainGraphics.scale.y = 2; plainGraphics.alpha = 0; self.shoot = function (enemies, bulletsContainer) { if (self.cooldownTimer <= 0 && enemies.length > 0) { var bullet = new Bullet(self); bullet.x = self.x; bullet.y = self.y; bulletsContainer.addChild(bullet); self.cooldownTimer = self.cooldown; } self.cooldownTimer--; }; }); var Tower = Container.expand(function (gameInstance) { var self = Container.call(this); self.game = gameInstance; self.game = gameInstance; var towerGraphics = self.attachAsset('tower', { anchorX: 0.5, anchorY: 0.5 }); self.cooldown = 0.625 / 0.7 * (1 / 0.6) * 1.3; self.cooldownTimer = 0; self.shoot = function (enemies, bullets) { if (self.cooldownTimer <= 0 && enemies.length > 0) { self.fireBullet(bullets); } self.cooldownTimer--; }; self.fireBullet = function (bullets) { var bullet; if (gameInstance.bulletPool && gameInstance.bulletPool.length > 0) { // Optimization 9: Reuse bullet from pool bullet = gameInstance.bulletPool.pop(); bullet.x = self.x; bullet.y = self.y; bullet._destroyed = false; } else { bullet = new Bullet(self.game); bullet.x = self.x; bullet.y = self.y; } gameInstance.bulletsContainer.addChild(bullet); gameInstance.bullets.push(bullet); self.cooldownTimer = self.cooldown; }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ game.spawnEnemies = function () { enemiesSpawnedLastRound = enemiesSpawnedLastRound * 4; for (var i = 0; i < enemiesSpawnedLastRound; i++) { var newEnemy; if (game.enemyPool.length > 0) { // Optimization 7: Reuse from pool newEnemy = game.enemyPool.pop(); newEnemy.x = Math.random() * 2048; newEnemy.y = -50 * (i + 1); newEnemy._destroyed = false; } else { newEnemy = new Enemy(); newEnemy.x = Math.random() * 2048; newEnemy.y = -50 * (i + 1); } game.enemies.push(newEnemy); game.addChild(newEnemy); } if (game.lastEnemyCount !== game.enemies.length) { game.enemyCounterTxt.setText('Enemies: ' + game.enemies.length.toString()); game.lastEnemyCount = game.enemies.length; } }; game.updateEnemyCounter = function () {}; game.score = 0; game.gold = 100; game.incrementScore = function () { this.score++; }; game.frameRateCounter = new FrameRateCounter(); LK.gui.topRight.addChild(game.frameRateCounter.display); var enemiesSpawnedLastRound = 1; game.scoreTxt = new Text2(game.score.toString(), { size: 150, fill: 0xFFFFFF }); game.scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(game.scoreTxt); game.goldTxt = new Text2(game.gold.toString(), { size: 150, fill: 0xFFFF00 }); game.goldTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(game.goldTxt); game.enemies = []; game.enemyPool = []; // Optimization 5: Enemy object pool game.bulletPool = []; // Optimization 6: Bullet object pool // Removed duplicate initialization of game.enemies to prevent memory leaks and unnecessary allocations game.enemyCounterTxt = new Text2('Enemies: ' + game.enemies.length.toString(), { size: 150, fill: 0xFF0000 }); game.lastGold = game.gold; game.lastScore = game.score; game.lastEnemyCount = game.enemies.length; game.enemyCounterTxt.anchor.set(0, 1); LK.gui.bottomLeft.addChild(game.enemyCounterTxt); game.setBackgroundColor(0xFFFFFF); var towers = []; game.bullets = []; game.bulletsContainer = game.addChild(new Container()); var initialTower = new Tower(game); initialTower.x = 0 + initialTower.width / 2 - 260; initialTower.y = 500 + initialTower.height / 2 + 300 + 800 + 500; towers.push(initialTower); game.addChild(initialTower); var plain = game.addChild(new Plain()); plain.x = 2048 / 2; plain.y = 2732 / 2; game.addChild(plain); var enemy = new Enemy(); enemy.x = 2048 / 2; enemy.y = -enemy.height / 2; game.enemies.push(enemy); game.addChild(enemy); game.on('down', function (x, y, obj) { var event = obj; var pos = game.toLocal(event.global); if (game.gold >= 50) { var newTower = new Tower(game); newTower.x = pos.x; newTower.y = pos.y; game.addChild(newTower); towers.push(newTower); game.gold -= 50; if (game.lastGold !== game.gold) { game.goldTxt.setText(game.gold.toString()); game.lastGold = game.gold; } } }); LK.on('tick', function () { game.frameRateCounter._update_migrated(); if (game.enemies.length === 0) { game.spawnEnemies(); } else { towers.forEach(function (tower) { tower.shoot(game.enemies, game.bullets); }); } // Combined update loop for both enemies and bullets to minimize per-frame iteration and batch remove destroyed objects var enemiesToRemove = []; var bulletsToRemove = []; // Update enemies and mark for removal if out of bounds for (var ei = 0; ei < game.enemies.length; ei++) { var enemy = game.enemies[ei]; enemy._move_migrated(); if (enemy.y > 2732) { if (!enemy._destroyed) { // Optimization 10: Only destroy if not already destroyed enemy.destroy(); } enemiesToRemove.push(ei); } } // Update bullets, check for collisions, and mark for removal if destroyed or out of bounds for (var bi = 0; bi < game.bullets.length; bi++) { var bullet = game.bullets[bi]; if (bullet._destroyed) continue; // Optimization 1: Skip destroyed bullets bullet._move_migrated(); var destroyed = false; for (var j = game.enemies.length - 1; j >= 0; j--) { if (game.enemies[j]._destroyed) continue; // Optimization 2: Skip destroyed enemies if (bullet.intersects(game.enemies[j])) { game.enemies[j].destroy(); game.enemies.splice(j, 1); enemiesToRemove = []; // Reset, as indices have changed game.incrementScore(); if (game.lastScore !== game.score) { game.scoreTxt.setText(game.score.toString()); game.lastScore = game.score; } game.gold += 50; bullet.destroy(); if (game.lastEnemyCount !== game.enemies.length) { game.enemyCounterTxt.setText('Enemies: ' + game.enemies.length.toString()); game.lastEnemyCount = game.enemies.length; } destroyed = true; break; } } if (destroyed || bullet.x > 2048) { bullet.destroy(); bulletsToRemove.push(bi); } } // Remove destroyed enemies and bullets using filter for better performance // Optimization 8: Return destroyed objects to pools for (var i = 0; i < game.enemies.length; i++) { if (game.enemies[i]._destroyed) { game.enemyPool.push(game.enemies[i]); } } for (var i = 0; i < game.bullets.length; i++) { if (game.bullets[i]._destroyed) { game.bulletPool.push(game.bullets[i]); } } game.enemies = game.enemies.filter(function (enemy) { return !enemy._destroyed; }); // Optimization 3 game.bullets = game.bullets.filter(function (bullet) { return !bullet._destroyed; }); // Optimization 4 });
===================================================================
--- original.js
+++ change.js
@@ -3,40 +3,31 @@
****/
var Bullet = Container.expand(function (gameInstance) {
var self = Container.call(this);
self.game = gameInstance;
- self._isDestroyed = false;
+ self.game = gameInstance;
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self._move_migrated = function () {
- if (self._isDestroyed) return;
self.x += 240;
if (self.x > 2148) {
- if (!self._isDestroyed && self.parent) {
- self._isDestroyed = true;
- if (typeof self.destroy === "function") self.destroy();
- }
+ self.destroy();
}
};
});
var Enemy = Container.expand(function (gameInstance) {
var self = Container.call(this);
self.game = gameInstance;
- self._isDestroyed = false;
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self._move_migrated = function () {
- if (self._isDestroyed) return;
self.y += 25.6 * 0.7 * 0.6;
if (self.y > 2732) {
- if (!self._isDestroyed && self.parent) {
- self._isDestroyed = true;
- if (typeof self.destroy === "function") self.destroy();
- }
+ self.destroy();
}
};
});
var FrameRateCounter = Container.expand(function () {
@@ -85,8 +76,9 @@
});
var Tower = Container.expand(function (gameInstance) {
var self = Container.call(this);
self.game = gameInstance;
+ self.game = gameInstance;
var towerGraphics = self.attachAsset('tower', {
anchorX: 0.5,
anchorY: 0.5
});
@@ -98,11 +90,20 @@
}
self.cooldownTimer--;
};
self.fireBullet = function (bullets) {
- var bullet = new Bullet(self.game);
- bullet.x = self.x;
- bullet.y = self.y;
+ var bullet;
+ if (gameInstance.bulletPool && gameInstance.bulletPool.length > 0) {
+ // Optimization 9: Reuse bullet from pool
+ bullet = gameInstance.bulletPool.pop();
+ bullet.x = self.x;
+ bullet.y = self.y;
+ bullet._destroyed = false;
+ } else {
+ bullet = new Bullet(self.game);
+ bullet.x = self.x;
+ bullet.y = self.y;
+ }
gameInstance.bulletsContainer.addChild(bullet);
gameInstance.bullets.push(bullet);
self.cooldownTimer = self.cooldown;
};
@@ -120,13 +121,22 @@
****/
game.spawnEnemies = function () {
enemiesSpawnedLastRound = enemiesSpawnedLastRound * 4;
for (var i = 0; i < enemiesSpawnedLastRound; i++) {
- var newEnemy = new Enemy();
- newEnemy.x = Math.random() * 2048;
- newEnemy.y = -50 * (i + 1);
+ var newEnemy;
+ if (game.enemyPool.length > 0) {
+ // Optimization 7: Reuse from pool
+ newEnemy = game.enemyPool.pop();
+ newEnemy.x = Math.random() * 2048;
+ newEnemy.y = -50 * (i + 1);
+ newEnemy._destroyed = false;
+ } else {
+ newEnemy = new Enemy();
+ newEnemy.x = Math.random() * 2048;
+ newEnemy.y = -50 * (i + 1);
+ }
game.enemies.push(newEnemy);
- game.enemiesContainer.addChild(newEnemy);
+ game.addChild(newEnemy);
}
if (game.lastEnemyCount !== game.enemies.length) {
game.enemyCounterTxt.setText('Enemies: ' + game.enemies.length.toString());
game.lastEnemyCount = game.enemies.length;
@@ -153,9 +163,11 @@
});
game.goldTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(game.goldTxt);
game.enemies = [];
-game.enemiesContainer = game.addChild(new Container());
+game.enemyPool = []; // Optimization 5: Enemy object pool
+game.bulletPool = []; // Optimization 6: Bullet object pool
+// Removed duplicate initialization of game.enemies to prevent memory leaks and unnecessary allocations
game.enemyCounterTxt = new Text2('Enemies: ' + game.enemies.length.toString(), {
size: 150,
fill: 0xFF0000
});
@@ -172,17 +184,17 @@
initialTower.x = 0 + initialTower.width / 2 - 260;
initialTower.y = 500 + initialTower.height / 2 + 300 + 800 + 500;
towers.push(initialTower);
game.addChild(initialTower);
-var plain = new Plain();
+var plain = game.addChild(new Plain());
plain.x = 2048 / 2;
plain.y = 2732 / 2;
game.addChild(plain);
var enemy = new Enemy();
enemy.x = 2048 / 2;
enemy.y = -enemy.height / 2;
game.enemies.push(enemy);
-game.enemiesContainer.addChild(enemy);
+game.addChild(enemy);
game.on('down', function (x, y, obj) {
var event = obj;
var pos = game.toLocal(event.global);
if (game.gold >= 50) {
@@ -201,117 +213,75 @@
LK.on('tick', function () {
game.frameRateCounter._update_migrated();
if (game.enemies.length === 0) {
game.spawnEnemies();
+ } else {
+ towers.forEach(function (tower) {
+ tower.shoot(game.enemies, game.bullets);
+ });
}
- towers.forEach(function (tower) {
- tower.shoot(game.enemies, game.bullets);
- });
- // Optimized update loop for both enemies and bullets to minimize per-frame iteration and array mutation
- var ei = 0;
- while (ei < game.enemies.length) {
+ // Combined update loop for both enemies and bullets to minimize per-frame iteration and batch remove destroyed objects
+ var enemiesToRemove = [];
+ var bulletsToRemove = [];
+ // Update enemies and mark for removal if out of bounds
+ for (var ei = 0; ei < game.enemies.length; ei++) {
var enemy = game.enemies[ei];
enemy._move_migrated();
- ei++;
+ if (enemy.y > 2732) {
+ if (!enemy._destroyed) {
+ // Optimization 10: Only destroy if not already destroyed
+ enemy.destroy();
+ }
+ enemiesToRemove.push(ei);
+ }
}
- // --- Begin spatial partitioning for collision checks ---
- if (!game._gridCellSize) {
- game._gridCellSize = 300;
- game._gridCols = Math.ceil(2048 / game._gridCellSize);
- game._gridRows = Math.ceil(2732 / game._gridCellSize);
- }
- var gridCellSize = game._gridCellSize;
- var gridCols = game._gridCols;
- var gridRows = game._gridRows;
- if (!game._enemyGrid) {
- game._enemyGrid = [];
- for (var gx = 0; gx < gridCols * gridRows; gx++) game._enemyGrid[gx] = [];
- }
- var enemyGrid = game._enemyGrid;
- for (var gx = 0; gx < gridCols * gridRows; gx++) enemyGrid[gx].length = 0;
- for (var ei = 0; ei < game.enemies.length; ei++) {
- var e = game.enemies[ei];
- var ex = Math.floor(e.x / gridCellSize);
- var ey = Math.floor(e.y / gridCellSize);
- var idx = ey * gridCols + ex;
- if (idx >= 0 && idx < enemyGrid.length) enemyGrid[idx].push(e);
- }
- var bi = 0;
- while (bi < game.bullets.length) {
+ // Update bullets, check for collisions, and mark for removal if destroyed or out of bounds
+ for (var bi = 0; bi < game.bullets.length; bi++) {
var bullet = game.bullets[bi];
+ if (bullet._destroyed) continue; // Optimization 1: Skip destroyed bullets
bullet._move_migrated();
var destroyed = false;
- var bx = Math.floor(bullet.x / gridCellSize);
- var by = Math.floor(bullet.y / gridCellSize);
- for (var dx = -1; dx <= 1; dx++) {
- for (var dy = -1; dy <= 1; dy++) {
- var cx = bx + dx;
- var cy = by + dy;
- if (cx < 0 || cy < 0 || cx >= gridCols || cy >= gridRows) continue;
- var idx = cy * gridCols + cx;
- var cellEnemies = enemyGrid[idx];
- for (var j = cellEnemies.length - 1; j >= 0; j--) {
- var enemy = cellEnemies[j];
- if (!bullet._isDestroyed && !enemy._isDestroyed && bullet.intersects(enemy)) {
- enemy._isDestroyed = true;
- enemy.destroy();
- game.incrementScore();
- if (game.lastScore !== game.score) {
- game.scoreTxt.setText(game.score.toString());
- game.lastScore = game.score;
- }
- game.gold += 50;
- if (game.lastGold !== game.gold) {
- game.goldTxt.setText(game.gold.toString());
- game.lastGold = game.gold;
- }
- bullet._isDestroyed = true;
- bullet.destroy();
- destroyed = true;
- break;
- }
+ for (var j = game.enemies.length - 1; j >= 0; j--) {
+ if (game.enemies[j]._destroyed) continue; // Optimization 2: Skip destroyed enemies
+ if (bullet.intersects(game.enemies[j])) {
+ game.enemies[j].destroy();
+ game.enemies.splice(j, 1);
+ enemiesToRemove = []; // Reset, as indices have changed
+ game.incrementScore();
+ if (game.lastScore !== game.score) {
+ game.scoreTxt.setText(game.score.toString());
+ game.lastScore = game.score;
}
- if (destroyed) break;
+ game.gold += 50;
+ bullet.destroy();
+ if (game.lastEnemyCount !== game.enemies.length) {
+ game.enemyCounterTxt.setText('Enemies: ' + game.enemies.length.toString());
+ game.lastEnemyCount = game.enemies.length;
+ }
+ destroyed = true;
+ break;
}
- if (destroyed) break;
}
if (destroyed || bullet.x > 2048) {
- bullet._isDestroyed = true;
bullet.destroy();
+ bulletsToRemove.push(bi);
}
- bi++;
}
- // --- End spatial partitioning for collision checks ---
- // Batch remove destroyed enemies and bullets
- if (!game._reuseEnemies) game._reuseEnemies = [];
- if (!game._reuseBullets) game._reuseBullets = [];
- var newEnemies = game._reuseEnemies;
- newEnemies.length = 0;
+ // Remove destroyed enemies and bullets using filter for better performance
+ // Optimization 8: Return destroyed objects to pools
for (var i = 0; i < game.enemies.length; i++) {
- if (!game.enemies[i]._isDestroyed) {
- newEnemies.push(game.enemies[i]);
- } else {
- if (game.enemies[i].parent) {
- game.enemies[i].parent.removeChild(game.enemies[i]);
- if (typeof game.enemies[i].destroy === "function") game.enemies[i].destroy();
- }
+ if (game.enemies[i]._destroyed) {
+ game.enemyPool.push(game.enemies[i]);
}
}
- game.enemies = newEnemies;
- if (game.lastEnemyCount !== game.enemies.length) {
- game.enemyCounterTxt.setText('Enemies: ' + game.enemies.length.toString());
- game.lastEnemyCount = game.enemies.length;
- }
- var newBullets = game._reuseBullets;
- newBullets.length = 0;
for (var i = 0; i < game.bullets.length; i++) {
- if (!game.bullets[i]._isDestroyed) {
- newBullets.push(game.bullets[i]);
- } else {
- if (game.bullets[i].parent) {
- game.bullets[i].parent.removeChild(game.bullets[i]);
- if (typeof game.bullets[i].destroy === "function") game.bullets[i].destroy();
- }
+ if (game.bullets[i]._destroyed) {
+ game.bulletPool.push(game.bullets[i]);
}
}
- game.bullets = newBullets;
+ game.enemies = game.enemies.filter(function (enemy) {
+ return !enemy._destroyed;
+ }); // Optimization 3
+ game.bullets = game.bullets.filter(function (bullet) {
+ return !bullet._destroyed;
+ }); // Optimization 4
});
\ No newline at end of file
A plain in a comic style with a dirt road with 4 turn staring to top to the botom see from a top and 50 meter high view Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A tower shooting at enemy in a modern style Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A single soldat walking downard in a 16 bit style Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.