/**** * Classes ****/ var Bullet = Container.expand(function (gameInstance) { var self = Container.call(this); 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; 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++; if (game.lastScore !== this.score) { game.scoreTxt.setText(this.score.toString()); game.lastScore = 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; // Removed unnecessary initial enemy creation for performance 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 if (!game._enemiesToRemove) game._enemiesToRemove = []; if (!game._bulletsToRemove) game._bulletsToRemove = []; var enemiesToRemove = game._enemiesToRemove; var bulletsToRemove = game._bulletsToRemove; enemiesToRemove.length = 0; bulletsToRemove.length = 0; // 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])) { if (!game.enemies[j]._destroyed) { game.enemies[j].destroy(); game.enemies.splice(j, 1); 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.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 });
/****
* Classes
****/
var Bullet = Container.expand(function (gameInstance) {
var self = Container.call(this);
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;
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++;
if (game.lastScore !== this.score) {
game.scoreTxt.setText(this.score.toString());
game.lastScore = 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;
// Removed unnecessary initial enemy creation for performance
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
if (!game._enemiesToRemove) game._enemiesToRemove = [];
if (!game._bulletsToRemove) game._bulletsToRemove = [];
var enemiesToRemove = game._enemiesToRemove;
var bulletsToRemove = game._bulletsToRemove;
enemiesToRemove.length = 0;
bulletsToRemove.length = 0;
// 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])) {
if (!game.enemies[j]._destroyed) {
game.enemies[j].destroy();
game.enemies.splice(j, 1);
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.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
});
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.