/****
* 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 = 15;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyCowboy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyCowboy', {
anchorX: 0.5,
anchorY: 0.5
});
var weapon = self.attachAsset('enemyWeapon', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: 0
});
self.lane = 1;
self.speed = 3;
self.lastShot = 0;
self.shootCooldown = 180; // 3 seconds at 60fps
self.targetLane = 1;
self.laneChangeSpeed = 8;
self.aiType = 'A'; // A: stay same lane, B: random switch, C: track player
self.lastLaneChange = 0;
self.update = function () {
self.y += self.speed;
// Move towards target lane
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > self.laneChangeSpeed) {
if (self.x < targetX) {
self.x += self.laneChangeSpeed;
} else {
self.x -= self.laneChangeSpeed;
}
} else {
self.x = targetX;
self.lane = self.targetLane;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shootCooldown) {
self.lastShot = 0;
// Create enemy bullet
var bullet = new EnemyBullet();
var weaponPos = weapon.parent.toGlobal(weapon.position);
var gamePos = game.toLocal(weaponPos);
bullet.x = gamePos.x;
bullet.y = gamePos.y;
enemyBullets.push(bullet);
game.addChild(bullet);
// Animate weapon recoil
tween(weapon, {
scaleY: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(weapon, {
scaleY: 1
}, {
duration: 100
});
}
});
}
// AI behavior
self.lastLaneChange++;
if (self.lastLaneChange >= 120) {
// Every 2 seconds
self.lastLaneChange = 0;
if (self.aiType === 'B') {
// Random switch
self.targetLane = Math.floor(Math.random() * 3);
} else if (self.aiType === 'C') {
// Track player
if (player) {
self.targetLane = player.lane;
}
}
}
// Type A stays in same lane (no change needed)
};
return self;
});
var MiniBoss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('miniBoss', {
anchorX: 0.5,
anchorY: 0.5
});
var weapon = self.attachAsset('enemyWeapon', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 0
});
self.lane = 1;
self.speed = 4;
self.health = 3;
self.maxHealth = 3;
self.lastShot = 0;
self.shootCooldown = 120; // 2 seconds at 60fps
self.targetLane = 1;
self.laneChangeSpeed = 10;
self.update = function () {
self.y += self.speed;
// Move towards target lane
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > self.laneChangeSpeed) {
if (self.x < targetX) {
self.x += self.laneChangeSpeed;
} else {
self.x -= self.laneChangeSpeed;
}
} else {
self.x = targetX;
self.lane = self.targetLane;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shootCooldown) {
self.lastShot = 0;
var bullet = new EnemyBullet();
var weaponPos = weapon.parent.toGlobal(weapon.position);
var gamePos = game.toLocal(weaponPos);
bullet.x = gamePos.x;
bullet.y = gamePos.y;
enemyBullets.push(bullet);
game.addChild(bullet);
// Animate weapon recoil
tween(weapon, {
scaleY: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(weapon, {
scaleY: 1
}, {
duration: 100
});
}
});
}
// Random lane changing
if (LK.ticks % 120 === 0 && Math.random() < 0.5) {
self.targetLane = Math.floor(Math.random() * 3);
}
};
self.takeDamage = function () {
self.health--;
LK.getSound('miniBossHit').play();
// Flash red when hit
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(bossGraphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('cowboy', {
anchorX: 0.5,
anchorY: 0.5
});
var weapon = self.attachAsset('playerWeapon', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -10
});
self.lane = 1;
self.targetLane = 1;
self.laneChangeSpeed = 12;
self.lastShot = 0;
self.shootCooldown = 72; // 1.2 seconds at 60fps
self.update = function () {
// Move towards target lane
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > self.laneChangeSpeed) {
if (self.x < targetX) {
self.x += self.laneChangeSpeed;
} else {
self.x -= self.laneChangeSpeed;
}
} else {
self.x = targetX;
self.lane = self.targetLane;
}
self.lastShot++;
};
self.moveLeft = function () {
if (self.targetLane > 0) {
self.targetLane--;
}
};
self.moveRight = function () {
if (self.targetLane < 2) {
self.targetLane++;
}
};
self.shoot = function () {
var cooldown = playerRapidFire > 0 ? 30 : self.shootCooldown; // Rapid fire reduces cooldown
if (self.lastShot >= cooldown) {
self.lastShot = 0;
var bullet = new PlayerBullet();
var weaponPos = weapon.parent.toGlobal(weapon.position);
var gamePos = game.toLocal(weaponPos);
bullet.x = gamePos.x;
bullet.y = gamePos.y;
// Apply explosive shot if active
if (playerExplosiveShot) {
bullet.makeExplosive();
playerExplosiveShot = false; // One-time use
}
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
// Animate weapon recoil
tween(weapon, {
scaleY: 0.7
}, {
duration: 80,
onFinish: function onFinish() {
tween(weapon, {
scaleY: 1
}, {
duration: 120
});
}
});
}
};
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 = -20;
self.isExplosive = false;
self.update = function () {
self.y += self.speed;
};
// Make bullet explosive
self.makeExplosive = function () {
self.isExplosive = true;
bulletGraphics.tint = 0xFF4500; // Orange tint for explosive
bulletGraphics.scaleX = 1.5;
bulletGraphics.scaleY = 1.5;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'rapidFire'; // rapidFire, shield, explosive
self.speed = 5;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 250;
self.health = self.maxHealth;
self.isDestroyed = false;
self.takeDamage = function (damage) {
if (self.isDestroyed) {
return;
}
self.health -= damage;
LK.getSound('wallHit').play();
// Visual damage feedback
var damagePercent = 1 - self.health / self.maxHealth;
wallGraphics.tint = 0xFFFFFF - 0x444444 * damagePercent;
// Shake effect
tween(self, {
x: self.x + 10
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
x: self.x - 10
}, {
duration: 100
});
}
});
if (self.health <= 0) {
self.destroyWall();
}
};
self.destroyWall = function () {
if (self.isDestroyed) {
return;
}
self.isDestroyed = true;
LK.getSound('wallBreak').play();
// Destruction animation
tween(self, {
alpha: 0,
scaleY: 0.1
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xFF8C00
});
/****
* Game Code
****/
// Game variables
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var gameSpeed = 1;
var survivalTime = 0;
var killCount = 0;
var lastEnemySpawn = 0;
var enemySpawnRate = 200; // 5 seconds at 60fps
var speedIncreaseTimer = 0;
var wall;
var powerUps = [];
var miniBosses = [];
var lastMiniBossSpawn = 0;
var lastPowerUpSpawn = 0;
var lastExplosiveSpawn = 0;
var playerHasShield = false;
var playerRapidFire = 0;
var playerExplosiveShot = false;
var sandstormActive = false;
var sandstormTimer = 0;
var lastSandstorm = 0;
var repairBtn = null;
// Lane positions
function getLaneX(lane) {
var laneWidth = 2048 / 3;
return laneWidth * lane + laneWidth / 2;
}
// Add orange background
var orangeBackground = game.addChild(LK.getAsset('orangeBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create wall
wall = game.addChild(new Wall());
wall.x = 1024;
wall.y = 1800;
// Create player
player = game.addChild(new Player());
player.x = getLaneX(1);
player.y = 2200;
// Create UI
var scoreTxt = new Text2('SCORE: 0', {
size: 70,
fill: 0x00FF00
});
scoreTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreTxt);
scoreTxt.x = 120;
scoreTxt.y = 20;
var killsTxt = new Text2('KILLS: 0', {
size: 70,
fill: 0xFF0080
});
killsTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(killsTxt);
killsTxt.y = 20;
// Wall health bar
var wallHealthBar = new Text2('WALL: 100/100', {
size: 60,
fill: 0x00CCFF
});
wallHealthBar.anchor.set(0.5, 0);
LK.gui.top.addChild(wallHealthBar);
wallHealthBar.y = 80;
// Control buttons
var leftBtn = new Text2('◀', {
size: 130,
fill: 0xFFFF00
});
leftBtn.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(leftBtn);
leftBtn.x = 200;
leftBtn.y = -150;
var rightBtn = new Text2('▶', {
size: 130,
fill: 0xFFFF00
});
rightBtn.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(rightBtn);
rightBtn.x = -200;
rightBtn.y = -150;
var shootBtn = LK.getAsset('fireButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottom.addChild(shootBtn);
shootBtn.y = -150;
// Button event handlers
leftBtn.down = function () {
player.moveLeft();
};
rightBtn.down = function () {
player.moveRight();
};
shootBtn.down = function () {
player.shoot();
};
// Function to show/hide repair button
function updateRepairButton() {
if (LK.getScore() >= 50 && wall && !wall.isDestroyed && wall.health < wall.maxHealth) {
if (!repairBtn) {
repairBtn = LK.getAsset('repairButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.center.addChild(repairBtn);
repairBtn.y = 200;
repairBtn.down = function () {
if (LK.getScore() >= 50 && wall && wall.health < wall.maxHealth) {
LK.setScore(LK.getScore() - 50);
wall.health = Math.min(wall.health + 50, wall.maxHealth);
scoreTxt.setText('SCORE: ' + LK.getScore());
updateRepairButton();
}
};
}
} else if (repairBtn) {
repairBtn.destroy();
repairBtn = null;
}
}
// Game update loop
game.update = function () {
// Update power-up timers
if (playerRapidFire > 0) {
playerRapidFire--;
}
if (sandstormActive) {
sandstormTimer--;
if (sandstormTimer <= 0) {
sandstormActive = false;
game.alpha = 1; // Remove sandstorm effect
}
}
// Update survival time and score
survivalTime++;
if (survivalTime % 60 === 0) {
// Every second
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('SCORE: ' + LK.getScore());
}
// Update repair button
updateRepairButton();
// Spawn sandstorm event
lastSandstorm++;
if (lastSandstorm >= 2700 && !sandstormActive) {
// 45-60 seconds
if (Math.random() < 0.5) {
sandstormActive = true;
sandstormTimer = 600; // 10 seconds
game.alpha = 0.6; // Reduce visibility
lastSandstorm = 0;
}
}
// Spawn power-ups
lastPowerUpSpawn++;
if (lastPowerUpSpawn >= 1200) {
// 20-30 seconds for rapid fire
if (Math.random() < 0.7) {
var powerUp = new PowerUp();
powerUp.type = 'rapidFire';
var rapidFireGraphics = powerUp.attachAsset('rapidFire', {
anchorX: 0.5,
anchorY: 0.5
});
powerUp.x = getLaneX(Math.floor(Math.random() * 3));
powerUp.y = -100;
powerUps.push(powerUp);
game.addChild(powerUp);
lastPowerUpSpawn = 0;
}
}
// Spawn explosive shot power-up
lastExplosiveSpawn++;
if (lastExplosiveSpawn >= 3600) {
// 60 seconds
var powerUp = new PowerUp();
powerUp.type = 'explosive';
var explosiveGraphics = powerUp.attachAsset('explosive', {
anchorX: 0.5,
anchorY: 0.5
});
powerUp.x = getLaneX(Math.floor(Math.random() * 3));
powerUp.y = -100;
powerUps.push(powerUp);
game.addChild(powerUp);
lastExplosiveSpawn = 0;
}
// Spawn mini boss
lastMiniBossSpawn++;
if (lastMiniBossSpawn >= 1800) {
// 30 seconds
lastMiniBossSpawn = 0;
var miniBoss = new MiniBoss();
miniBoss.lane = Math.floor(Math.random() * 3);
miniBoss.targetLane = Math.floor(Math.random() * 3);
miniBoss.x = getLaneX(miniBoss.lane);
miniBoss.y = -150;
miniBoss.speed *= gameSpeed;
miniBosses.push(miniBoss);
game.addChild(miniBoss);
}
// Update wall health bar
if (wall && !wall.isDestroyed) {
var healthPercent = wall.health / wall.maxHealth;
if (healthPercent > 0.6) {
wallHealthBar.fill = 0x00FF00; // Green for healthy
} else if (healthPercent > 0.3) {
wallHealthBar.fill = 0xFFFF00; // Yellow for damaged
} else {
wallHealthBar.fill = 0xFF0000; // Red for critical
}
wallHealthBar.setText('WALL: ' + wall.health + '/' + wall.maxHealth);
} else {
wallHealthBar.fill = 0xFF0000;
wallHealthBar.setText('WALL: DESTROYED');
}
// Increase game speed over time
speedIncreaseTimer++;
if (speedIncreaseTimer % 600 === 0) {
// Every 10 seconds
gameSpeed += 0.2;
if (enemySpawnRate > 120) {
enemySpawnRate -= 20;
}
}
// Spawn enemies
lastEnemySpawn++;
if (lastEnemySpawn >= enemySpawnRate) {
lastEnemySpawn = 0;
var enemy = new EnemyCowboy();
enemy.lane = Math.floor(Math.random() * 3);
enemy.targetLane = Math.floor(Math.random() * 3);
// Set AI type
var aiRand = Math.random();
if (aiRand < 0.4) {
enemy.aiType = 'A';
} // Stay same lane
else if (aiRand < 0.7) {
enemy.aiType = 'B';
} // Random switch
else {
enemy.aiType = 'C';
} // Track player
enemy.x = getLaneX(enemy.lane);
enemy.y = -100;
enemy.speed *= gameSpeed;
// Sandstorm effect on enemies
if (sandstormActive) {
enemy.speed *= 1.25; // Move 25% faster
enemy.shootCooldown = 999999; // Cannot shoot
}
enemies.push(enemy);
game.addChild(enemy);
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
// Remove power-ups that went off screen
if (powerUp.y > 2800) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collision with player
if (powerUp.intersects(player)) {
LK.getSound('powerUp').play();
if (powerUp.type === 'rapidFire') {
playerRapidFire = 600; // 10 seconds at 60fps
} else if (powerUp.type === 'shield') {
playerHasShield = true;
} else if (powerUp.type === 'explosive') {
playerExplosiveShot = true;
}
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Update mini bosses
for (var i = miniBosses.length - 1; i >= 0; i--) {
var miniBoss = miniBosses[i];
// Remove mini bosses that went off screen
if (miniBoss.y > 2800) {
miniBoss.destroy();
miniBosses.splice(i, 1);
continue;
}
// Check collision with wall
if (wall && !wall.isDestroyed && miniBoss.intersects(wall)) {
miniBoss.speed = 0;
if (miniBoss.lastWallDamage === undefined) {
miniBoss.lastWallDamage = 0;
}
miniBoss.lastWallDamage++;
if (miniBoss.lastWallDamage >= 30) {
wall.takeDamage(20); // Mini boss deals more damage
miniBoss.lastWallDamage = 0;
}
} else if (wall && wall.isDestroyed) {
miniBoss.speed = 4 * gameSpeed;
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Remove enemies that went off screen
if (enemy.y > 2800) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with wall - enemies cannot pass through
if (wall && !wall.isDestroyed && enemy.intersects(wall)) {
// Stop enemy movement when hitting wall
enemy.speed = 0;
// Deal damage to wall when enemy touches it
if (enemy.lastWallDamage === undefined) {
enemy.lastWallDamage = 0;
}
enemy.lastWallDamage++;
if (enemy.lastWallDamage >= 30) {
// Damage every 0.5 seconds
wall.takeDamage(10);
enemy.lastWallDamage = 0;
}
} else if (wall && wall.isDestroyed) {
// If wall is destroyed, enemies can move normally
enemy.speed = 3 * gameSpeed;
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Remove bullets that went off screen
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var bulletHit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Enemy hit
LK.getSound('enemyHit').play();
killCount++;
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('SCORE: ' + LK.getScore());
killsTxt.setText('KILLS: ' + killCount);
// Drop shield power-up with 15% chance
if (Math.random() < 0.15) {
var shieldPowerUp = new PowerUp();
shieldPowerUp.type = 'shield';
var shieldGraphics = shieldPowerUp.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5
});
shieldPowerUp.x = enemy.x;
shieldPowerUp.y = enemy.y;
powerUps.push(shieldPowerUp);
game.addChild(shieldPowerUp);
}
// Remove enemy
enemy.destroy();
enemies.splice(j, 1);
if (!bullet.isExplosive) {
bulletHit = true;
break;
}
}
}
// Check collision with mini bosses
for (var j = miniBosses.length - 1; j >= 0; j--) {
var miniBoss = miniBosses[j];
if (bullet.intersects(miniBoss)) {
miniBoss.takeDamage();
if (miniBoss.health <= 0) {
killCount++;
LK.setScore(LK.getScore() + 20);
scoreTxt.setText('SCORE: ' + LK.getScore());
killsTxt.setText('KILLS: ' + killCount);
// Drop random power-up
var powerUp = new PowerUp();
var powerTypes = ['rapidFire', 'shield', 'explosive'];
powerUp.type = powerTypes[Math.floor(Math.random() * powerTypes.length)];
var powerGraphics = powerUp.attachAsset(powerUp.type, {
anchorX: 0.5,
anchorY: 0.5
});
powerUp.x = miniBoss.x;
powerUp.y = miniBoss.y;
powerUps.push(powerUp);
game.addChild(powerUp);
miniBoss.destroy();
miniBosses.splice(j, 1);
}
if (!bullet.isExplosive) {
bulletHit = true;
break;
}
}
}
// Handle explosive shots
if (bullet.isExplosive) {
// Explosive shot passes through wall and kills all enemies in lane
var bulletLane = Math.floor((bullet.x - getLaneX(0) + 2048 / 6) / (2048 / 3));
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (enemy.lane === bulletLane) {
LK.getSound('explosion').play();
killCount++;
LK.setScore(LK.getScore() + 5);
enemy.destroy();
enemies.splice(j, 1);
}
}
// Also kill mini bosses in same lane
for (var j = miniBosses.length - 1; j >= 0; j--) {
var miniBoss = miniBosses[j];
if (miniBoss.lane === bulletLane) {
LK.getSound('explosion').play();
killCount++;
LK.setScore(LK.getScore() + 20);
miniBoss.destroy();
miniBosses.splice(j, 1);
}
}
bulletHit = true;
}
// Remove bullet if it hit something (unless explosive)
if (bulletHit) {
bullet.destroy();
playerBullets.splice(i, 1);
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Remove bullets that went off screen
if (bullet.y > 2800) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with wall (bullets pass through but don't damage)
if (wall && !wall.isDestroyed && bullet.intersects(wall)) {
// Enemy bullets pass through wall without stopping
}
// Check collision with player
if (bullet.intersects(player)) {
if (playerHasShield) {
// Shield absorbs hit
playerHasShield = false;
LK.effects.flashObject(player, 0x00FF00, 500);
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
} else {
// Player hit - game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
}; /****
* 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 = 15;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyCowboy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyCowboy', {
anchorX: 0.5,
anchorY: 0.5
});
var weapon = self.attachAsset('enemyWeapon', {
anchorX: 0.5,
anchorY: 0.5,
x: 30,
y: 0
});
self.lane = 1;
self.speed = 3;
self.lastShot = 0;
self.shootCooldown = 180; // 3 seconds at 60fps
self.targetLane = 1;
self.laneChangeSpeed = 8;
self.aiType = 'A'; // A: stay same lane, B: random switch, C: track player
self.lastLaneChange = 0;
self.update = function () {
self.y += self.speed;
// Move towards target lane
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > self.laneChangeSpeed) {
if (self.x < targetX) {
self.x += self.laneChangeSpeed;
} else {
self.x -= self.laneChangeSpeed;
}
} else {
self.x = targetX;
self.lane = self.targetLane;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shootCooldown) {
self.lastShot = 0;
// Create enemy bullet
var bullet = new EnemyBullet();
var weaponPos = weapon.parent.toGlobal(weapon.position);
var gamePos = game.toLocal(weaponPos);
bullet.x = gamePos.x;
bullet.y = gamePos.y;
enemyBullets.push(bullet);
game.addChild(bullet);
// Animate weapon recoil
tween(weapon, {
scaleY: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(weapon, {
scaleY: 1
}, {
duration: 100
});
}
});
}
// AI behavior
self.lastLaneChange++;
if (self.lastLaneChange >= 120) {
// Every 2 seconds
self.lastLaneChange = 0;
if (self.aiType === 'B') {
// Random switch
self.targetLane = Math.floor(Math.random() * 3);
} else if (self.aiType === 'C') {
// Track player
if (player) {
self.targetLane = player.lane;
}
}
}
// Type A stays in same lane (no change needed)
};
return self;
});
var MiniBoss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('miniBoss', {
anchorX: 0.5,
anchorY: 0.5
});
var weapon = self.attachAsset('enemyWeapon', {
anchorX: 0.5,
anchorY: 0.5,
x: 40,
y: 0
});
self.lane = 1;
self.speed = 4;
self.health = 3;
self.maxHealth = 3;
self.lastShot = 0;
self.shootCooldown = 120; // 2 seconds at 60fps
self.targetLane = 1;
self.laneChangeSpeed = 10;
self.update = function () {
self.y += self.speed;
// Move towards target lane
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > self.laneChangeSpeed) {
if (self.x < targetX) {
self.x += self.laneChangeSpeed;
} else {
self.x -= self.laneChangeSpeed;
}
} else {
self.x = targetX;
self.lane = self.targetLane;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shootCooldown) {
self.lastShot = 0;
var bullet = new EnemyBullet();
var weaponPos = weapon.parent.toGlobal(weapon.position);
var gamePos = game.toLocal(weaponPos);
bullet.x = gamePos.x;
bullet.y = gamePos.y;
enemyBullets.push(bullet);
game.addChild(bullet);
// Animate weapon recoil
tween(weapon, {
scaleY: 0.8
}, {
duration: 100,
onFinish: function onFinish() {
tween(weapon, {
scaleY: 1
}, {
duration: 100
});
}
});
}
// Random lane changing
if (LK.ticks % 120 === 0 && Math.random() < 0.5) {
self.targetLane = Math.floor(Math.random() * 3);
}
};
self.takeDamage = function () {
self.health--;
LK.getSound('miniBossHit').play();
// Flash red when hit
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(bossGraphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('cowboy', {
anchorX: 0.5,
anchorY: 0.5
});
var weapon = self.attachAsset('playerWeapon', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -10
});
self.lane = 1;
self.targetLane = 1;
self.laneChangeSpeed = 12;
self.lastShot = 0;
self.shootCooldown = 72; // 1.2 seconds at 60fps
self.update = function () {
// Move towards target lane
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > self.laneChangeSpeed) {
if (self.x < targetX) {
self.x += self.laneChangeSpeed;
} else {
self.x -= self.laneChangeSpeed;
}
} else {
self.x = targetX;
self.lane = self.targetLane;
}
self.lastShot++;
};
self.moveLeft = function () {
if (self.targetLane > 0) {
self.targetLane--;
}
};
self.moveRight = function () {
if (self.targetLane < 2) {
self.targetLane++;
}
};
self.shoot = function () {
var cooldown = playerRapidFire > 0 ? 30 : self.shootCooldown; // Rapid fire reduces cooldown
if (self.lastShot >= cooldown) {
self.lastShot = 0;
var bullet = new PlayerBullet();
var weaponPos = weapon.parent.toGlobal(weapon.position);
var gamePos = game.toLocal(weaponPos);
bullet.x = gamePos.x;
bullet.y = gamePos.y;
// Apply explosive shot if active
if (playerExplosiveShot) {
bullet.makeExplosive();
playerExplosiveShot = false; // One-time use
}
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
// Animate weapon recoil
tween(weapon, {
scaleY: 0.7
}, {
duration: 80,
onFinish: function onFinish() {
tween(weapon, {
scaleY: 1
}, {
duration: 120
});
}
});
}
};
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 = -20;
self.isExplosive = false;
self.update = function () {
self.y += self.speed;
};
// Make bullet explosive
self.makeExplosive = function () {
self.isExplosive = true;
bulletGraphics.tint = 0xFF4500; // Orange tint for explosive
bulletGraphics.scaleX = 1.5;
bulletGraphics.scaleY = 1.5;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'rapidFire'; // rapidFire, shield, explosive
self.speed = 5;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 250;
self.health = self.maxHealth;
self.isDestroyed = false;
self.takeDamage = function (damage) {
if (self.isDestroyed) {
return;
}
self.health -= damage;
LK.getSound('wallHit').play();
// Visual damage feedback
var damagePercent = 1 - self.health / self.maxHealth;
wallGraphics.tint = 0xFFFFFF - 0x444444 * damagePercent;
// Shake effect
tween(self, {
x: self.x + 10
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
x: self.x - 10
}, {
duration: 100
});
}
});
if (self.health <= 0) {
self.destroyWall();
}
};
self.destroyWall = function () {
if (self.isDestroyed) {
return;
}
self.isDestroyed = true;
LK.getSound('wallBreak').play();
// Destruction animation
tween(self, {
alpha: 0,
scaleY: 0.1
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xFF8C00
});
/****
* Game Code
****/
// Game variables
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var gameSpeed = 1;
var survivalTime = 0;
var killCount = 0;
var lastEnemySpawn = 0;
var enemySpawnRate = 200; // 5 seconds at 60fps
var speedIncreaseTimer = 0;
var wall;
var powerUps = [];
var miniBosses = [];
var lastMiniBossSpawn = 0;
var lastPowerUpSpawn = 0;
var lastExplosiveSpawn = 0;
var playerHasShield = false;
var playerRapidFire = 0;
var playerExplosiveShot = false;
var sandstormActive = false;
var sandstormTimer = 0;
var lastSandstorm = 0;
var repairBtn = null;
// Lane positions
function getLaneX(lane) {
var laneWidth = 2048 / 3;
return laneWidth * lane + laneWidth / 2;
}
// Add orange background
var orangeBackground = game.addChild(LK.getAsset('orangeBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create wall
wall = game.addChild(new Wall());
wall.x = 1024;
wall.y = 1800;
// Create player
player = game.addChild(new Player());
player.x = getLaneX(1);
player.y = 2200;
// Create UI
var scoreTxt = new Text2('SCORE: 0', {
size: 70,
fill: 0x00FF00
});
scoreTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreTxt);
scoreTxt.x = 120;
scoreTxt.y = 20;
var killsTxt = new Text2('KILLS: 0', {
size: 70,
fill: 0xFF0080
});
killsTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(killsTxt);
killsTxt.y = 20;
// Wall health bar
var wallHealthBar = new Text2('WALL: 100/100', {
size: 60,
fill: 0x00CCFF
});
wallHealthBar.anchor.set(0.5, 0);
LK.gui.top.addChild(wallHealthBar);
wallHealthBar.y = 80;
// Control buttons
var leftBtn = new Text2('◀', {
size: 130,
fill: 0xFFFF00
});
leftBtn.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(leftBtn);
leftBtn.x = 200;
leftBtn.y = -150;
var rightBtn = new Text2('▶', {
size: 130,
fill: 0xFFFF00
});
rightBtn.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(rightBtn);
rightBtn.x = -200;
rightBtn.y = -150;
var shootBtn = LK.getAsset('fireButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottom.addChild(shootBtn);
shootBtn.y = -150;
// Button event handlers
leftBtn.down = function () {
player.moveLeft();
};
rightBtn.down = function () {
player.moveRight();
};
shootBtn.down = function () {
player.shoot();
};
// Function to show/hide repair button
function updateRepairButton() {
if (LK.getScore() >= 50 && wall && !wall.isDestroyed && wall.health < wall.maxHealth) {
if (!repairBtn) {
repairBtn = LK.getAsset('repairButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.center.addChild(repairBtn);
repairBtn.y = 200;
repairBtn.down = function () {
if (LK.getScore() >= 50 && wall && wall.health < wall.maxHealth) {
LK.setScore(LK.getScore() - 50);
wall.health = Math.min(wall.health + 50, wall.maxHealth);
scoreTxt.setText('SCORE: ' + LK.getScore());
updateRepairButton();
}
};
}
} else if (repairBtn) {
repairBtn.destroy();
repairBtn = null;
}
}
// Game update loop
game.update = function () {
// Update power-up timers
if (playerRapidFire > 0) {
playerRapidFire--;
}
if (sandstormActive) {
sandstormTimer--;
if (sandstormTimer <= 0) {
sandstormActive = false;
game.alpha = 1; // Remove sandstorm effect
}
}
// Update survival time and score
survivalTime++;
if (survivalTime % 60 === 0) {
// Every second
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('SCORE: ' + LK.getScore());
}
// Update repair button
updateRepairButton();
// Spawn sandstorm event
lastSandstorm++;
if (lastSandstorm >= 2700 && !sandstormActive) {
// 45-60 seconds
if (Math.random() < 0.5) {
sandstormActive = true;
sandstormTimer = 600; // 10 seconds
game.alpha = 0.6; // Reduce visibility
lastSandstorm = 0;
}
}
// Spawn power-ups
lastPowerUpSpawn++;
if (lastPowerUpSpawn >= 1200) {
// 20-30 seconds for rapid fire
if (Math.random() < 0.7) {
var powerUp = new PowerUp();
powerUp.type = 'rapidFire';
var rapidFireGraphics = powerUp.attachAsset('rapidFire', {
anchorX: 0.5,
anchorY: 0.5
});
powerUp.x = getLaneX(Math.floor(Math.random() * 3));
powerUp.y = -100;
powerUps.push(powerUp);
game.addChild(powerUp);
lastPowerUpSpawn = 0;
}
}
// Spawn explosive shot power-up
lastExplosiveSpawn++;
if (lastExplosiveSpawn >= 3600) {
// 60 seconds
var powerUp = new PowerUp();
powerUp.type = 'explosive';
var explosiveGraphics = powerUp.attachAsset('explosive', {
anchorX: 0.5,
anchorY: 0.5
});
powerUp.x = getLaneX(Math.floor(Math.random() * 3));
powerUp.y = -100;
powerUps.push(powerUp);
game.addChild(powerUp);
lastExplosiveSpawn = 0;
}
// Spawn mini boss
lastMiniBossSpawn++;
if (lastMiniBossSpawn >= 1800) {
// 30 seconds
lastMiniBossSpawn = 0;
var miniBoss = new MiniBoss();
miniBoss.lane = Math.floor(Math.random() * 3);
miniBoss.targetLane = Math.floor(Math.random() * 3);
miniBoss.x = getLaneX(miniBoss.lane);
miniBoss.y = -150;
miniBoss.speed *= gameSpeed;
miniBosses.push(miniBoss);
game.addChild(miniBoss);
}
// Update wall health bar
if (wall && !wall.isDestroyed) {
var healthPercent = wall.health / wall.maxHealth;
if (healthPercent > 0.6) {
wallHealthBar.fill = 0x00FF00; // Green for healthy
} else if (healthPercent > 0.3) {
wallHealthBar.fill = 0xFFFF00; // Yellow for damaged
} else {
wallHealthBar.fill = 0xFF0000; // Red for critical
}
wallHealthBar.setText('WALL: ' + wall.health + '/' + wall.maxHealth);
} else {
wallHealthBar.fill = 0xFF0000;
wallHealthBar.setText('WALL: DESTROYED');
}
// Increase game speed over time
speedIncreaseTimer++;
if (speedIncreaseTimer % 600 === 0) {
// Every 10 seconds
gameSpeed += 0.2;
if (enemySpawnRate > 120) {
enemySpawnRate -= 20;
}
}
// Spawn enemies
lastEnemySpawn++;
if (lastEnemySpawn >= enemySpawnRate) {
lastEnemySpawn = 0;
var enemy = new EnemyCowboy();
enemy.lane = Math.floor(Math.random() * 3);
enemy.targetLane = Math.floor(Math.random() * 3);
// Set AI type
var aiRand = Math.random();
if (aiRand < 0.4) {
enemy.aiType = 'A';
} // Stay same lane
else if (aiRand < 0.7) {
enemy.aiType = 'B';
} // Random switch
else {
enemy.aiType = 'C';
} // Track player
enemy.x = getLaneX(enemy.lane);
enemy.y = -100;
enemy.speed *= gameSpeed;
// Sandstorm effect on enemies
if (sandstormActive) {
enemy.speed *= 1.25; // Move 25% faster
enemy.shootCooldown = 999999; // Cannot shoot
}
enemies.push(enemy);
game.addChild(enemy);
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
// Remove power-ups that went off screen
if (powerUp.y > 2800) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collision with player
if (powerUp.intersects(player)) {
LK.getSound('powerUp').play();
if (powerUp.type === 'rapidFire') {
playerRapidFire = 600; // 10 seconds at 60fps
} else if (powerUp.type === 'shield') {
playerHasShield = true;
} else if (powerUp.type === 'explosive') {
playerExplosiveShot = true;
}
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Update mini bosses
for (var i = miniBosses.length - 1; i >= 0; i--) {
var miniBoss = miniBosses[i];
// Remove mini bosses that went off screen
if (miniBoss.y > 2800) {
miniBoss.destroy();
miniBosses.splice(i, 1);
continue;
}
// Check collision with wall
if (wall && !wall.isDestroyed && miniBoss.intersects(wall)) {
miniBoss.speed = 0;
if (miniBoss.lastWallDamage === undefined) {
miniBoss.lastWallDamage = 0;
}
miniBoss.lastWallDamage++;
if (miniBoss.lastWallDamage >= 30) {
wall.takeDamage(20); // Mini boss deals more damage
miniBoss.lastWallDamage = 0;
}
} else if (wall && wall.isDestroyed) {
miniBoss.speed = 4 * gameSpeed;
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Remove enemies that went off screen
if (enemy.y > 2800) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with wall - enemies cannot pass through
if (wall && !wall.isDestroyed && enemy.intersects(wall)) {
// Stop enemy movement when hitting wall
enemy.speed = 0;
// Deal damage to wall when enemy touches it
if (enemy.lastWallDamage === undefined) {
enemy.lastWallDamage = 0;
}
enemy.lastWallDamage++;
if (enemy.lastWallDamage >= 30) {
// Damage every 0.5 seconds
wall.takeDamage(10);
enemy.lastWallDamage = 0;
}
} else if (wall && wall.isDestroyed) {
// If wall is destroyed, enemies can move normally
enemy.speed = 3 * gameSpeed;
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Remove bullets that went off screen
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var bulletHit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Enemy hit
LK.getSound('enemyHit').play();
killCount++;
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('SCORE: ' + LK.getScore());
killsTxt.setText('KILLS: ' + killCount);
// Drop shield power-up with 15% chance
if (Math.random() < 0.15) {
var shieldPowerUp = new PowerUp();
shieldPowerUp.type = 'shield';
var shieldGraphics = shieldPowerUp.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5
});
shieldPowerUp.x = enemy.x;
shieldPowerUp.y = enemy.y;
powerUps.push(shieldPowerUp);
game.addChild(shieldPowerUp);
}
// Remove enemy
enemy.destroy();
enemies.splice(j, 1);
if (!bullet.isExplosive) {
bulletHit = true;
break;
}
}
}
// Check collision with mini bosses
for (var j = miniBosses.length - 1; j >= 0; j--) {
var miniBoss = miniBosses[j];
if (bullet.intersects(miniBoss)) {
miniBoss.takeDamage();
if (miniBoss.health <= 0) {
killCount++;
LK.setScore(LK.getScore() + 20);
scoreTxt.setText('SCORE: ' + LK.getScore());
killsTxt.setText('KILLS: ' + killCount);
// Drop random power-up
var powerUp = new PowerUp();
var powerTypes = ['rapidFire', 'shield', 'explosive'];
powerUp.type = powerTypes[Math.floor(Math.random() * powerTypes.length)];
var powerGraphics = powerUp.attachAsset(powerUp.type, {
anchorX: 0.5,
anchorY: 0.5
});
powerUp.x = miniBoss.x;
powerUp.y = miniBoss.y;
powerUps.push(powerUp);
game.addChild(powerUp);
miniBoss.destroy();
miniBosses.splice(j, 1);
}
if (!bullet.isExplosive) {
bulletHit = true;
break;
}
}
}
// Handle explosive shots
if (bullet.isExplosive) {
// Explosive shot passes through wall and kills all enemies in lane
var bulletLane = Math.floor((bullet.x - getLaneX(0) + 2048 / 6) / (2048 / 3));
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (enemy.lane === bulletLane) {
LK.getSound('explosion').play();
killCount++;
LK.setScore(LK.getScore() + 5);
enemy.destroy();
enemies.splice(j, 1);
}
}
// Also kill mini bosses in same lane
for (var j = miniBosses.length - 1; j >= 0; j--) {
var miniBoss = miniBosses[j];
if (miniBoss.lane === bulletLane) {
LK.getSound('explosion').play();
killCount++;
LK.setScore(LK.getScore() + 20);
miniBoss.destroy();
miniBosses.splice(j, 1);
}
}
bulletHit = true;
}
// Remove bullet if it hit something (unless explosive)
if (bulletHit) {
bullet.destroy();
playerBullets.splice(i, 1);
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Remove bullets that went off screen
if (bullet.y > 2800) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with wall (bullets pass through but don't damage)
if (wall && !wall.isDestroyed && bullet.intersects(wall)) {
// Enemy bullets pass through wall without stopping
}
// Check collision with player
if (bullet.intersects(player)) {
if (playerHasShield) {
// Shield absorbs hit
playerHasShield = false;
LK.effects.flashObject(player, 0x00FF00, 500);
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
} else {
// Player hit - game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
};
2d cowboy character head. In-Game asset. 2d. High contrast. No shadows
2d revolver bullet. In-Game asset. 2d. High contrast. No shadows
2d old concrete wall suitable for desert atmosphere. In-Game asset. 2d. High contrast. No shadows
2d edgy red themed hostile cowboy character head
A 2d fired revolver. In-Game asset. 2d. High contrast. No shadows
a 2d revolver without firing effect
Let it be red themed
2d simple repair button. In-Game asset. 2d. High contrast. No shadows
2d protection shield. In-Game asset. 2d. High contrast. No shadows
2d explosion effect. In-Game asset. 2d. High contrast. No shadows