Code edit (1 edits merged)
Please save this source code
User prompt
Cowboy Rush: Shootout Road
Initial prompt
๐ฎ Game Title: Cowboy Rush: Shootout Road --- ๐ Game Description Welcome to Cowboy Rush, a fast-paced 2D arcade shooter where YOU are the last hope of the wild west! Dodge, shoot, and survive on a triple-lane desert road while enemy cowboys chase you down. --- ๐ฏ Game Objective Stay alive as long as you can. Switch between 3 lanes, avoid bullets, and shoot down enemies chasing you. The longer you survive, the faster the game gets! --- ๐น๏ธ Gameplay Mechanics You are a lone cowboy running forward endlessly. Behind you: a gang of enemy cowboys chasing you. There are 3 lanes โ left, middle, right. Use the Left and Right buttons to switch lanes. Enemies also change lanes randomly to match your position. Tap the Shoot button to fire your revolver. You can shoot once every 1.2 seconds. Enemies shoot once every 3 seconds. Both you and enemies die with a single hit. The game gets faster over time. Reaction time shortens! --- ๐ Game Over Conditions If an enemy bullet hits you โ Game Over. The longer you survive, the higher your Score (based on time + kills). --- ๐ Leaderboard Feature Enable global leaderboards so players can compete for the Highest Score: Survive longer = Higher score Kill enemies = Bonus points Leaderboard tracks: Username Top Score Kill Count --- ๐ UI Buttons โฌ ๏ธ Left: Move to the left lane โก๏ธ Right: Move to the right lane ๐ฏ Shoot: Fire a bullet (cooldown: 1.2 sec) ๐ Restart: Restart game after Game Over --- ๐ Score System Action Points Survive 1 sec +1 Kill 1 enemy +5 --- ๐จ Visual/Style Suggestions Pixel art or cartoon 2D Desert background with cacti and old western town in distance Enemies with cowboy hats and red bandanas Speed lines as difficulty increases
/**** * 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