/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Shell
var EnemyShell = Container.expand(function () {
var self = Container.call(this);
var shell = self.attachAsset('enemyShell', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shell.width;
self.height = shell.height;
self.speed = 22 + Math.random() * 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Tank
var EnemyTank = Container.expand(function () {
var self = Container.call(this);
var tank = self.attachAsset('enemyTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = tank.width;
self.height = tank.height;
self.speed = 6 + Math.random() * enemySpeedIncrease;
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
self.update = function () {
self.y += self.speed;
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shoot();
self.shootCooldown = 90 + Math.floor(Math.random() * 60);
}
};
self.shoot = function () {
var shell = new EnemyShell();
shell.x = self.x;
shell.y = self.y + self.height / 2 + shell.height / 2;
enemyShells.push(shell);
game.addChild(shell);
LK.getSound('enemyFire').play();
};
return self;
});
// Explosion (visual effect only)
var Explosion = Container.expand(function () {
var self = Container.call(this);
var exp = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.8
});
self.width = exp.width;
self.height = exp.height;
// Animate explosion
tween(exp, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Player Shell
var PlayerShell = Container.expand(function () {
var self = Container.call(this);
var shell = self.attachAsset('playerShell', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shell.width;
self.height = shell.height;
self.speed = -32;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Tank
var PlayerTank = Container.expand(function () {
var self = Container.call(this);
var tank = self.attachAsset('playerTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = tank.width;
self.height = tank.height;
self.shootCooldown = 0;
self.poweredUp = false;
self.powerupTimer = 0;
// Shoot method
self.shoot = function () {
if (self.shootCooldown > 0) return;
var shell = new PlayerShell();
shell.x = self.x;
shell.y = self.y - self.height / 2 - shell.height / 2;
playerShells.push(shell);
game.addChild(shell);
LK.getSound('fire').play();
self.shootCooldown = self.poweredUp ? 10 : 20; // Faster fire if powered up
};
// Powerup method
self.activatePowerup = function () {
self.poweredUp = true;
self.powerupTimer = 360; // 6 seconds at 60fps
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.elasticOut
});
};
self.deactivatePowerup = function () {
self.poweredUp = false;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.elasticIn
});
};
// Update
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
if (self.poweredUp) {
self.powerupTimer--;
if (self.powerupTimer <= 0) self.deactivatePowerup();
}
};
return self;
});
// Powerup
var Powerup = Container.expand(function () {
var self = Container.call(this);
var p = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = p.width;
self.height = p.height;
self.speed = 10;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x22272a
});
/****
* Game Code
****/
// Can bar assets
// Play music
// Player Tank
// Player Shell
// Enemy Tank
// Enemy Shell
// Powerup
// Explosion (for effect)
// Sounds
// Music
LK.playMusic('battleTheme');
// Score
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Player
var player = new PlayerTank();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// --- Can Bar (Health Bar) ---
var playerMaxHealth = 5;
var playerHealth = playerMaxHealth;
// Create can bar background (grey)
var canBarBg = LK.getAsset('canBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
canBarBg.width = 220;
canBarBg.height = 32;
canBarBg.x = player.x;
canBarBg.y = player.y - player.height / 2 - 40;
game.addChild(canBarBg);
// Create can bar fill (green)
var canBarFill = LK.getAsset('canBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
canBarFill.width = 200;
canBarFill.height = 20;
canBarFill.x = player.x;
canBarFill.y = player.y - player.height / 2 - 40;
game.addChild(canBarFill);
// Helper to update can bar position and fill
function updateCanBar() {
canBarBg.x = player.x;
canBarBg.y = player.y - player.height / 2 - 40;
canBarFill.x = player.x;
canBarFill.y = player.y - player.height / 2 - 40;
canBarFill.width = 200 * (playerHealth / playerMaxHealth);
if (playerHealth / playerMaxHealth <= 0.4) {
canBarFill.tint = 0xff3c00; // red if low
} else if (playerHealth / playerMaxHealth <= 0.7) {
canBarFill.tint = 0xffe000; // yellow if mid
} else {
canBarFill.tint = 0x4caf50; // green if healthy
}
}
updateCanBar();
// Arrays for game objects
var playerShells = [];
var enemyTanks = [];
var enemyShells = [];
var powerups = [];
var explosions = [];
// Difficulty
var enemySpawnTimer = 0;
var enemySpawnInterval = 90;
var enemySpeedIncrease = 0;
var powerupTimer = 0;
// Dragging
var dragNode = null;
// Move handler
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp tank inside game area (leave 100px margin at top for UI)
var minX = player.width / 2;
var maxX = 2048 - player.width / 2;
var minY = 100 + player.height / 2;
var maxY = 2732 - player.height / 2;
dragNode.x = Math.max(minX, Math.min(maxX, x));
dragNode.y = Math.max(minY, Math.min(maxY, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only start drag if touch/click is on player tank
var local = player.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(local.x) <= player.width / 2 && Math.abs(local.y) <= player.height / 2) {
dragNode = player;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Tap to shoot (anywhere)
game.tap = function (x, y, obj) {
player.shoot();
};
// For mobile: allow shooting by tapping anywhere except on UI
game.down = function (x, y, obj) {
// If tap is not on top UI, shoot
if (y > 180) player.shoot();
// Also allow drag
var local = player.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(local.x) <= player.width / 2 && Math.abs(local.y) <= player.height / 2) {
dragNode = player;
}
};
// Main update loop
game.update = function () {
// Player update
player.update();
updateCanBar();
// Player shells
for (var i = playerShells.length - 1; i >= 0; i--) {
var shell = playerShells[i];
shell.update();
// Remove if off screen
if (shell.y < -shell.height) {
shell.destroy();
playerShells.splice(i, 1);
continue;
}
// Check collision with enemy tanks
for (var j = enemyTanks.length - 1; j >= 0; j--) {
var enemy = enemyTanks[j];
if (shell.intersects(enemy)) {
// Explosion
var exp = new Explosion();
exp.x = enemy.x;
exp.y = enemy.y;
game.addChild(exp);
explosions.push(exp);
LK.getSound('explode').play();
// Remove both
enemy.destroy();
shell.destroy();
enemyTanks.splice(j, 1);
playerShells.splice(i, 1);
// Score
score++;
scoreTxt.setText(score);
// Increase difficulty
if (score % 10 === 0) {
enemySpeedIncrease += 2;
if (enemySpawnInterval > 30) enemySpawnInterval -= 5;
}
// Win condition
if (score >= 50) {
LK.showYouWin();
return;
}
break;
}
}
}
// Enemy tanks
for (var i = enemyTanks.length - 1; i >= 0; i--) {
var enemy = enemyTanks[i];
enemy.update();
// Remove if off screen
if (enemy.y > 2732 + enemy.height) {
enemy.destroy();
enemyTanks.splice(i, 1);
continue;
}
// Collision with player
if (enemy.intersects(player)) {
LK.effects.flashScreen(0xff0000, 800);
playerHealth--;
updateCanBar();
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
// Remove enemy tank on collision
enemy.destroy();
enemyTanks.splice(i, 1);
continue;
}
}
// Enemy shells
for (var i = enemyShells.length - 1; i >= 0; i--) {
var shell = enemyShells[i];
shell.update();
// Remove if off screen
if (shell.y > 2732 + shell.height) {
shell.destroy();
enemyShells.splice(i, 1);
continue;
}
// Collision with player
if (shell.intersects(player)) {
LK.effects.flashScreen(0xff0000, 800);
playerHealth--;
updateCanBar();
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
// Remove shell on hit
shell.destroy();
enemyShells.splice(i, 1);
continue;
}
}
// Powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
// Remove if off screen
if (p.y > 2732 + p.height) {
p.destroy();
powerups.splice(i, 1);
continue;
}
// Collision with player
if (p.intersects(player)) {
LK.getSound('powerup').play();
player.activatePowerup();
// Heal player by 1 can, up to max
if (playerHealth < playerMaxHealth) {
playerHealth++;
updateCanBar();
}
p.destroy();
powerups.splice(i, 1);
}
}
// Explosions (auto-destroyed by tween)
// Spawn enemy tanks
enemySpawnTimer--;
if (enemySpawnTimer <= 0) {
var enemy = new EnemyTank();
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -enemy.height / 2;
enemyTanks.push(enemy);
game.addChild(enemy);
enemySpawnTimer = enemySpawnInterval + Math.floor(Math.random() * 40);
}
// Spawn powerups
powerupTimer--;
if (powerupTimer <= 0) {
if (Math.random() < 0.25) {
// 25% chance
var p = new Powerup();
p.x = 200 + Math.random() * (2048 - 400);
p.y = -p.height / 2;
powerups.push(p);
game.addChild(p);
}
powerupTimer = 600 + Math.floor(Math.random() * 600); // 10-20 seconds
}
};
// Initial timers
enemySpawnTimer = 60;
powerupTimer = 900;
// Prevent UI overlap (top left 100x100 reserved)
scoreTxt.x = 2048 / 2;
scoreTxt.y = 20; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Shell
var EnemyShell = Container.expand(function () {
var self = Container.call(this);
var shell = self.attachAsset('enemyShell', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shell.width;
self.height = shell.height;
self.speed = 22 + Math.random() * 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Tank
var EnemyTank = Container.expand(function () {
var self = Container.call(this);
var tank = self.attachAsset('enemyTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = tank.width;
self.height = tank.height;
self.speed = 6 + Math.random() * enemySpeedIncrease;
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
self.update = function () {
self.y += self.speed;
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
self.shoot();
self.shootCooldown = 90 + Math.floor(Math.random() * 60);
}
};
self.shoot = function () {
var shell = new EnemyShell();
shell.x = self.x;
shell.y = self.y + self.height / 2 + shell.height / 2;
enemyShells.push(shell);
game.addChild(shell);
LK.getSound('enemyFire').play();
};
return self;
});
// Explosion (visual effect only)
var Explosion = Container.expand(function () {
var self = Container.call(this);
var exp = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.8
});
self.width = exp.width;
self.height = exp.height;
// Animate explosion
tween(exp, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Player Shell
var PlayerShell = Container.expand(function () {
var self = Container.call(this);
var shell = self.attachAsset('playerShell', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shell.width;
self.height = shell.height;
self.speed = -32;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Tank
var PlayerTank = Container.expand(function () {
var self = Container.call(this);
var tank = self.attachAsset('playerTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = tank.width;
self.height = tank.height;
self.shootCooldown = 0;
self.poweredUp = false;
self.powerupTimer = 0;
// Shoot method
self.shoot = function () {
if (self.shootCooldown > 0) return;
var shell = new PlayerShell();
shell.x = self.x;
shell.y = self.y - self.height / 2 - shell.height / 2;
playerShells.push(shell);
game.addChild(shell);
LK.getSound('fire').play();
self.shootCooldown = self.poweredUp ? 10 : 20; // Faster fire if powered up
};
// Powerup method
self.activatePowerup = function () {
self.poweredUp = true;
self.powerupTimer = 360; // 6 seconds at 60fps
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.elasticOut
});
};
self.deactivatePowerup = function () {
self.poweredUp = false;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.elasticIn
});
};
// Update
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
if (self.poweredUp) {
self.powerupTimer--;
if (self.powerupTimer <= 0) self.deactivatePowerup();
}
};
return self;
});
// Powerup
var Powerup = Container.expand(function () {
var self = Container.call(this);
var p = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = p.width;
self.height = p.height;
self.speed = 10;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x22272a
});
/****
* Game Code
****/
// Can bar assets
// Play music
// Player Tank
// Player Shell
// Enemy Tank
// Enemy Shell
// Powerup
// Explosion (for effect)
// Sounds
// Music
LK.playMusic('battleTheme');
// Score
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: '#fff'
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Player
var player = new PlayerTank();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// --- Can Bar (Health Bar) ---
var playerMaxHealth = 5;
var playerHealth = playerMaxHealth;
// Create can bar background (grey)
var canBarBg = LK.getAsset('canBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
canBarBg.width = 220;
canBarBg.height = 32;
canBarBg.x = player.x;
canBarBg.y = player.y - player.height / 2 - 40;
game.addChild(canBarBg);
// Create can bar fill (green)
var canBarFill = LK.getAsset('canBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
canBarFill.width = 200;
canBarFill.height = 20;
canBarFill.x = player.x;
canBarFill.y = player.y - player.height / 2 - 40;
game.addChild(canBarFill);
// Helper to update can bar position and fill
function updateCanBar() {
canBarBg.x = player.x;
canBarBg.y = player.y - player.height / 2 - 40;
canBarFill.x = player.x;
canBarFill.y = player.y - player.height / 2 - 40;
canBarFill.width = 200 * (playerHealth / playerMaxHealth);
if (playerHealth / playerMaxHealth <= 0.4) {
canBarFill.tint = 0xff3c00; // red if low
} else if (playerHealth / playerMaxHealth <= 0.7) {
canBarFill.tint = 0xffe000; // yellow if mid
} else {
canBarFill.tint = 0x4caf50; // green if healthy
}
}
updateCanBar();
// Arrays for game objects
var playerShells = [];
var enemyTanks = [];
var enemyShells = [];
var powerups = [];
var explosions = [];
// Difficulty
var enemySpawnTimer = 0;
var enemySpawnInterval = 90;
var enemySpeedIncrease = 0;
var powerupTimer = 0;
// Dragging
var dragNode = null;
// Move handler
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp tank inside game area (leave 100px margin at top for UI)
var minX = player.width / 2;
var maxX = 2048 - player.width / 2;
var minY = 100 + player.height / 2;
var maxY = 2732 - player.height / 2;
dragNode.x = Math.max(minX, Math.min(maxX, x));
dragNode.y = Math.max(minY, Math.min(maxY, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only start drag if touch/click is on player tank
var local = player.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(local.x) <= player.width / 2 && Math.abs(local.y) <= player.height / 2) {
dragNode = player;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Tap to shoot (anywhere)
game.tap = function (x, y, obj) {
player.shoot();
};
// For mobile: allow shooting by tapping anywhere except on UI
game.down = function (x, y, obj) {
// If tap is not on top UI, shoot
if (y > 180) player.shoot();
// Also allow drag
var local = player.toLocal(game.toGlobal({
x: x,
y: y
}));
if (Math.abs(local.x) <= player.width / 2 && Math.abs(local.y) <= player.height / 2) {
dragNode = player;
}
};
// Main update loop
game.update = function () {
// Player update
player.update();
updateCanBar();
// Player shells
for (var i = playerShells.length - 1; i >= 0; i--) {
var shell = playerShells[i];
shell.update();
// Remove if off screen
if (shell.y < -shell.height) {
shell.destroy();
playerShells.splice(i, 1);
continue;
}
// Check collision with enemy tanks
for (var j = enemyTanks.length - 1; j >= 0; j--) {
var enemy = enemyTanks[j];
if (shell.intersects(enemy)) {
// Explosion
var exp = new Explosion();
exp.x = enemy.x;
exp.y = enemy.y;
game.addChild(exp);
explosions.push(exp);
LK.getSound('explode').play();
// Remove both
enemy.destroy();
shell.destroy();
enemyTanks.splice(j, 1);
playerShells.splice(i, 1);
// Score
score++;
scoreTxt.setText(score);
// Increase difficulty
if (score % 10 === 0) {
enemySpeedIncrease += 2;
if (enemySpawnInterval > 30) enemySpawnInterval -= 5;
}
// Win condition
if (score >= 50) {
LK.showYouWin();
return;
}
break;
}
}
}
// Enemy tanks
for (var i = enemyTanks.length - 1; i >= 0; i--) {
var enemy = enemyTanks[i];
enemy.update();
// Remove if off screen
if (enemy.y > 2732 + enemy.height) {
enemy.destroy();
enemyTanks.splice(i, 1);
continue;
}
// Collision with player
if (enemy.intersects(player)) {
LK.effects.flashScreen(0xff0000, 800);
playerHealth--;
updateCanBar();
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
// Remove enemy tank on collision
enemy.destroy();
enemyTanks.splice(i, 1);
continue;
}
}
// Enemy shells
for (var i = enemyShells.length - 1; i >= 0; i--) {
var shell = enemyShells[i];
shell.update();
// Remove if off screen
if (shell.y > 2732 + shell.height) {
shell.destroy();
enemyShells.splice(i, 1);
continue;
}
// Collision with player
if (shell.intersects(player)) {
LK.effects.flashScreen(0xff0000, 800);
playerHealth--;
updateCanBar();
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
// Remove shell on hit
shell.destroy();
enemyShells.splice(i, 1);
continue;
}
}
// Powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
// Remove if off screen
if (p.y > 2732 + p.height) {
p.destroy();
powerups.splice(i, 1);
continue;
}
// Collision with player
if (p.intersects(player)) {
LK.getSound('powerup').play();
player.activatePowerup();
// Heal player by 1 can, up to max
if (playerHealth < playerMaxHealth) {
playerHealth++;
updateCanBar();
}
p.destroy();
powerups.splice(i, 1);
}
}
// Explosions (auto-destroyed by tween)
// Spawn enemy tanks
enemySpawnTimer--;
if (enemySpawnTimer <= 0) {
var enemy = new EnemyTank();
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -enemy.height / 2;
enemyTanks.push(enemy);
game.addChild(enemy);
enemySpawnTimer = enemySpawnInterval + Math.floor(Math.random() * 40);
}
// Spawn powerups
powerupTimer--;
if (powerupTimer <= 0) {
if (Math.random() < 0.25) {
// 25% chance
var p = new Powerup();
p.x = 200 + Math.random() * (2048 - 400);
p.y = -p.height / 2;
powerups.push(p);
game.addChild(p);
}
powerupTimer = 600 + Math.floor(Math.random() * 600); // 10-20 seconds
}
};
// Initial timers
enemySpawnTimer = 60;
powerupTimer = 900;
// Prevent UI overlap (top left 100x100 reserved)
scoreTxt.x = 2048 / 2;
scoreTxt.y = 20;
create explode. In-Game asset. 2d. High contrast. No shadows
friend tank. In-Game asset. 2d. High contrast. No shadows
enemy tank. In-Game asset. 2d. High contrast. No shadows
make a power up asest. In-Game asset. 2d. High contrast. No shadows
yellow bullet. In-Game asset. 2d. High contrast. No shadows
gray,light gray,black bullet Don't put white! Let him/her look behind. let there be no eye and arm. In-Game asset. 2d. High contrast. No shadows