User prompt
Play music file number 17 as background music at game start
User prompt
revolver sound file no. 16
User prompt
make game music file number 4
User prompt
Make the whip sound file number 11
User prompt
The background can be made a little more western and zombie themed.
User prompt
Let's add game time to the game
User prompt
Upgrades do not drop from enemies, you get 1 upgrade every 2 minutes
User prompt
Upgrades only drop from bosses, bosses die in 5 lashes
User prompt
Bosses can only be killed by revolver bullets. Revolver bullets give priority to them. Bosses are pushed back when they are hit with a whip.
User prompt
Dropped add-ons come directly to the character. 1 boss should be added. This boss comes every 1 minute and when it is killed, the upgrades are dropped. When the boss is killed, the game speed increases.
User prompt
The character will remain fixed, there will be no time limit for using the whip, the enemy will be thrown every time it is pressed and will die in a single hit. The monsters in the game are slow at the beginning, the game will speed up a little after every 1 minute, and 1 development will come at the end of 2 minutes. The game is endless, each monster you kill gives 1 point, the duration of the revovlers is 10 seconds, the developments received are reduced to at least 4 seconds, 5 must be purchased, the range of the whip will be a little longer.
User prompt
Shoot at the nearest opponent based on the revolver keys and have a joystick for movement in the game
Code edit (1 edits merged)
Please save this source code
User prompt
Cowboy Whip & Revolver: Forest Showdown
Initial prompt
square, we are in the middle, a map where we can move in all directions, the map is green and forested, enemies come from everywhere, we are cowboys, we hit the characters with a whip in our hands, we have 1 revolver, the firing time is 3 seconds, we can shorten the rewards that drop during the game, when we get 3 features, we switch to weapons, weapon features come as the level speeds up, if we get 3 weapons, a pump-action pistol comes, as the game progresses, the monsters that come speed up
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Cowboy (player) class
var Cowboy = Container.expand(function () {
var self = Container.call(this);
var cowboySprite = self.attachAsset('cowboy', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 60; // for collision
self.whipCooldown = 0;
self.revolverCooldown = 0;
self.pumpUnlocked = false;
self.upgrades = 0;
self.revolverBaseCooldown = 180; // 3 seconds at 60fps
self.revolverCooldownTime = self.revolverBaseCooldown;
self.pumpCooldown = 0;
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 50;
self.speed = 2;
self.dirX = 0;
self.dirY = 0;
self.hp = 1;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Pump-action bullet class (stronger, wider)
var PumpBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('pump_bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 20;
self.speed = 22;
self.dirX = 0;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Revolver bullet class
var RevolverBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('revolver_bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 15;
self.speed = 18;
self.dirX = 0;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Upgrade drop class
var UpgradeDrop = Container.expand(function () {
var self = Container.call(this);
var upgradeSprite = self.attachAsset('upgrade', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 30;
self.update = function () {};
return self;
});
// Whip attack class (short-lived, close range)
var WhipAttack = Container.expand(function () {
var self = Container.call(this);
var whipSprite = self.attachAsset('whip', {
anchorX: 0.0,
anchorY: 0.5
});
self.radius = 60;
self.dirX = 0;
self.dirY = 0;
self.lifetime = 10; // frames
self.update = function () {
self.lifetime--;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2e7d32 // Forest green
});
/****
* Game Code
****/
// Pump-action bullet
// Upgrade drop
// Enemy
// Revolver bullet
// Whip (short range attack)
// Cowboy (player)
// Game area
var GAME_W = 2048;
var GAME_H = 2732;
// Center position
var centerX = GAME_W / 2;
var centerY = GAME_H / 2;
// Player
var cowboy = new Cowboy();
cowboy.x = centerX;
cowboy.y = centerY;
game.addChild(cowboy);
// Arrays for game objects
var enemies = [];
var bullets = [];
var whipAttacks = [];
var upgrades = [];
// Score and UI
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Weapon cooldown UI
var revolverTxt = new Text2('Revolver: Ready', {
size: 60,
fill: "#fff"
});
revolverTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(revolverTxt);
revolverTxt.y = 130;
// Upgrade UI
var upgradeTxt = new Text2('Upgrades: 0/3', {
size: 60,
fill: 0xFFD700
});
upgradeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(upgradeTxt);
upgradeTxt.y = 200;
// Difficulty
var wave = 1;
var spawnTimer = 0;
var spawnInterval = 90; // frames
var enemySpeed = 2;
// Dragging
var dragNode = null;
// Helper: distance
function dist(ax, ay, bx, by) {
var dx = ax - bx;
var dy = ay - by;
return Math.sqrt(dx * dx + dy * dy);
}
// Helper: clamp
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
// Helper: get direction vector
function getDir(ax, ay, bx, by) {
var dx = bx - ax;
var dy = by - ay;
var len = Math.sqrt(dx * dx + dy * dy);
if (len === 0) return {
x: 0,
y: 0
};
return {
x: dx / len,
y: dy / len
};
}
// Helper: spawn enemy at random edge
function spawnEnemy() {
var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
var ex, ey;
if (edge === 0) {
// top
ex = Math.random() * (GAME_W - 200) + 100;
ey = -80;
} else if (edge === 1) {
// right
ex = GAME_W + 80;
ey = Math.random() * (GAME_H - 200) + 100;
} else if (edge === 2) {
// bottom
ex = Math.random() * (GAME_W - 200) + 100;
ey = GAME_H + 80;
} else {
// left
ex = -80;
ey = Math.random() * (GAME_H - 200) + 100;
}
var enemy = new Enemy();
enemy.x = ex;
enemy.y = ey;
var dir = getDir(ex, ey, cowboy.x, cowboy.y);
enemy.dirX = dir.x;
enemy.dirY = dir.y;
enemy.speed = enemySpeed + Math.random() * 0.5 + (wave - 1) * 0.2;
enemy.hp = 1 + Math.floor(wave / 5);
enemies.push(enemy);
game.addChild(enemy);
}
// Helper: spawn upgrade at (x, y)
function spawnUpgrade(x, y) {
var upg = new UpgradeDrop();
upg.x = x;
upg.y = y;
upgrades.push(upg);
game.addChild(upg);
}
// Handle movement (dragging cowboy)
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to game area, avoid top left 100x100
dragNode.x = clamp(x, 120, GAME_W - 120);
dragNode.y = clamp(y, 120, GAME_H - 120);
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is on cowboy
var dx = x - cowboy.x;
var dy = y - cowboy.y;
if (dx * dx + dy * dy < 80 * 80) {
dragNode = cowboy;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Handle tap/attack (whip or revolver)
game.tap = function (x, y, obj) {
// Not used, as LK does not have tap event
};
// Touch: whip (short range, no cooldown)
game.down2 = function (x, y, obj) {
// Not used, as LK does not have down2 event
};
// Touch: fire revolver (if ready)
game.doubletap = function (x, y, obj) {
// Not used, as LK does not have doubletap event
};
// Whip attack: on quick tap (simulate with up event if not dragging)
game.up = function (x, y, obj) {
if (!dragNode) {
// Whip attack in direction of tap
if (cowboy.whipCooldown <= 0) {
var dir = getDir(cowboy.x, cowboy.y, x, y);
var whip = new WhipAttack();
whip.x = cowboy.x + dir.x * 60;
whip.y = cowboy.y + dir.y * 60;
whip.dirX = dir.x;
whip.dirY = dir.y;
whip.rotation = Math.atan2(dir.y, dir.x);
whipAttacks.push(whip);
game.addChild(whip);
cowboy.whipCooldown = 20; // 1/3 second
// Animate whip
tween(whip, {
alpha: 0
}, {
duration: 200,
easing: tween.linear,
onFinish: function onFinish() {
whip.alpha = 1;
}
});
}
}
dragNode = null;
};
// Fire revolver: on long press (simulate with two-finger tap or hold, but here use a button)
var fireBtn = new Text2('REVOLVER', {
size: 80,
fill: "#fff"
});
fireBtn.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(fireBtn);
fireBtn.y = -120;
fireBtn.x = 0;
fireBtn.interactive = true;
fireBtn.down = function (x, y, obj) {
if (cowboy.pumpUnlocked) {
// Fire pump-action (spread shot)
if (cowboy.pumpCooldown <= 0) {
for (var i = -1; i <= 1; i++) {
var dir = getDir(cowboy.x, cowboy.y, cowboy.x + Math.cos(game.lastAimAngle + i * 0.18) * 100, cowboy.y + Math.sin(game.lastAimAngle + i * 0.18) * 100);
var bullet = new PumpBullet();
bullet.x = cowboy.x + dir.x * 70;
bullet.y = cowboy.y + dir.y * 70;
bullet.dirX = dir.x;
bullet.dirY = dir.y;
bullet.rotation = Math.atan2(dir.y, dir.x);
bullets.push(bullet);
game.addChild(bullet);
}
cowboy.pumpCooldown = 90; // 1.5s
}
} else {
// Fire revolver
if (cowboy.revolverCooldown <= 0) {
// Aim at last direction of movement or default right
var angle = game.lastAimAngle || 0;
var dir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
var bullet = new RevolverBullet();
bullet.x = cowboy.x + dir.x * 70;
bullet.y = cowboy.y + dir.y * 70;
bullet.dirX = dir.x;
bullet.dirY = dir.y;
bullet.rotation = Math.atan2(dir.y, dir.x);
bullets.push(bullet);
game.addChild(bullet);
cowboy.revolverCooldown = cowboy.revolverCooldownTime;
}
}
};
// Track last aim direction (for revolver)
game.lastAimAngle = 0;
game.move = function (x, y, obj) {
if (dragNode) {
dragNode.x = clamp(x, 120, GAME_W - 120);
dragNode.y = clamp(y, 120, GAME_H - 120);
}
// Update aim angle
var dx = x - cowboy.x;
var dy = y - cowboy.y;
if (dx * dx + dy * dy > 10 * 10) {
game.lastAimAngle = Math.atan2(dy, dx);
}
};
// Main update loop
game.update = function () {
// Cooldowns
if (cowboy.whipCooldown > 0) cowboy.whipCooldown--;
if (cowboy.revolverCooldown > 0) cowboy.revolverCooldown--;
if (cowboy.pumpCooldown > 0) cowboy.pumpCooldown--;
// Update UI
scoreTxt.setText(score);
if (cowboy.pumpUnlocked) {
revolverTxt.setText('Pump-Action: ' + (cowboy.pumpCooldown > 0 ? (cowboy.pumpCooldown / 60).toFixed(1) + 's' : 'Ready'));
} else {
revolverTxt.setText('Revolver: ' + (cowboy.revolverCooldown > 0 ? (cowboy.revolverCooldown / 60).toFixed(1) + 's' : 'Ready'));
}
upgradeTxt.setText('Upgrades: ' + cowboy.upgrades + '/3');
// Spawn enemies
spawnTimer--;
if (spawnTimer <= 0) {
spawnEnemy();
spawnTimer = Math.max(30, spawnInterval - wave * 2);
}
// Increase difficulty
if (LK.ticks % 600 === 0) {
// every 10s
wave++;
enemySpeed += 0.2;
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Re-aim at player
var dir = getDir(e.x, e.y, cowboy.x, cowboy.y);
e.dirX = dir.x;
e.dirY = dir.y;
// Out of bounds
if (e.x < -200 || e.x > GAME_W + 200 || e.y < -200 || e.y > GAME_H + 200) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Collide with player
if (dist(e.x, e.y, cowboy.x, cowboy.y) < e.radius + cowboy.radius - 10) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Out of bounds
if (b.x < -100 || b.x > GAME_W + 100 || b.y < -100 || b.y > GAME_H + 100) {
b.destroy();
bullets.splice(i, 1);
continue;
}
// Hit enemy
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (dist(b.x, b.y, e.x, e.y) < b.radius + e.radius) {
e.hp--;
if (e.hp <= 0) {
// Drop upgrade with 1/5 chance
if (Math.random() < 0.2) {
spawnUpgrade(e.x, e.y);
}
e.destroy();
enemies.splice(j, 1);
score++;
}
b.destroy();
bullets.splice(i, 1);
break;
}
}
}
// Update whip attacks
for (var i = whipAttacks.length - 1; i >= 0; i--) {
var w = whipAttacks[i];
w.update();
// Hit enemy
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (dist(w.x + w.dirX * 40, w.y + w.dirY * 40, e.x, e.y) < w.radius + e.radius) {
e.hp--;
if (e.hp <= 0) {
if (Math.random() < 0.2) {
spawnUpgrade(e.x, e.y);
}
e.destroy();
enemies.splice(j, 1);
score++;
}
}
}
// Lifetime
if (w.lifetime <= 0) {
w.destroy();
whipAttacks.splice(i, 1);
}
}
// Update upgrades
for (var i = upgrades.length - 1; i >= 0; i--) {
var u = upgrades[i];
// Move toward player if close
if (dist(u.x, u.y, cowboy.x, cowboy.y) < 300) {
var dir = getDir(u.x, u.y, cowboy.x, cowboy.y);
u.x += dir.x * 8;
u.y += dir.y * 8;
}
// Collect
if (dist(u.x, u.y, cowboy.x, cowboy.y) < u.radius + cowboy.radius) {
cowboy.upgrades++;
if (cowboy.upgrades === 1) {
cowboy.revolverCooldownTime = Math.max(90, cowboy.revolverCooldownTime - 60); // 2s
} else if (cowboy.upgrades === 2) {
cowboy.revolverCooldownTime = Math.max(60, cowboy.revolverCooldownTime - 60); // 1s
} else if (cowboy.upgrades >= 3) {
cowboy.pumpUnlocked = true;
}
u.destroy();
upgrades.splice(i, 1);
}
}
// Win condition: survive 5 minutes or reach 100 score
if (score >= 100 || LK.ticks > 60 * 60 * 5) {
LK.showYouWin();
return;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,486 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Cowboy (player) class
+var Cowboy = Container.expand(function () {
+ var self = Container.call(this);
+ var cowboySprite = self.attachAsset('cowboy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 60; // for collision
+ self.whipCooldown = 0;
+ self.revolverCooldown = 0;
+ self.pumpUnlocked = false;
+ self.upgrades = 0;
+ self.revolverBaseCooldown = 180; // 3 seconds at 60fps
+ self.revolverCooldownTime = self.revolverBaseCooldown;
+ self.pumpCooldown = 0;
+ return self;
+});
+// Enemy class
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemySprite = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 50;
+ self.speed = 2;
+ self.dirX = 0;
+ self.dirY = 0;
+ self.hp = 1;
+ self.update = function () {
+ self.x += self.dirX * self.speed;
+ self.y += self.dirY * self.speed;
+ };
+ return self;
+});
+// Pump-action bullet class (stronger, wider)
+var PumpBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletSprite = self.attachAsset('pump_bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 20;
+ self.speed = 22;
+ self.dirX = 0;
+ self.dirY = 0;
+ self.update = function () {
+ self.x += self.dirX * self.speed;
+ self.y += self.dirY * self.speed;
+ };
+ return self;
+});
+// Revolver bullet class
+var RevolverBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletSprite = self.attachAsset('revolver_bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 15;
+ self.speed = 18;
+ self.dirX = 0;
+ self.dirY = 0;
+ self.update = function () {
+ self.x += self.dirX * self.speed;
+ self.y += self.dirY * self.speed;
+ };
+ return self;
+});
+// Upgrade drop class
+var UpgradeDrop = Container.expand(function () {
+ var self = Container.call(this);
+ var upgradeSprite = self.attachAsset('upgrade', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 30;
+ self.update = function () {};
+ return self;
+});
+// Whip attack class (short-lived, close range)
+var WhipAttack = Container.expand(function () {
+ var self = Container.call(this);
+ var whipSprite = self.attachAsset('whip', {
+ anchorX: 0.0,
+ anchorY: 0.5
+ });
+ self.radius = 60;
+ self.dirX = 0;
+ self.dirY = 0;
+ self.lifetime = 10; // frames
+ self.update = function () {
+ self.lifetime--;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2e7d32 // Forest green
+});
+
+/****
+* Game Code
+****/
+// Pump-action bullet
+// Upgrade drop
+// Enemy
+// Revolver bullet
+// Whip (short range attack)
+// Cowboy (player)
+// Game area
+var GAME_W = 2048;
+var GAME_H = 2732;
+// Center position
+var centerX = GAME_W / 2;
+var centerY = GAME_H / 2;
+// Player
+var cowboy = new Cowboy();
+cowboy.x = centerX;
+cowboy.y = centerY;
+game.addChild(cowboy);
+// Arrays for game objects
+var enemies = [];
+var bullets = [];
+var whipAttacks = [];
+var upgrades = [];
+// Score and UI
+var score = 0;
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Weapon cooldown UI
+var revolverTxt = new Text2('Revolver: Ready', {
+ size: 60,
+ fill: "#fff"
+});
+revolverTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(revolverTxt);
+revolverTxt.y = 130;
+// Upgrade UI
+var upgradeTxt = new Text2('Upgrades: 0/3', {
+ size: 60,
+ fill: 0xFFD700
+});
+upgradeTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(upgradeTxt);
+upgradeTxt.y = 200;
+// Difficulty
+var wave = 1;
+var spawnTimer = 0;
+var spawnInterval = 90; // frames
+var enemySpeed = 2;
+// Dragging
+var dragNode = null;
+// Helper: distance
+function dist(ax, ay, bx, by) {
+ var dx = ax - bx;
+ var dy = ay - by;
+ return Math.sqrt(dx * dx + dy * dy);
+}
+// Helper: clamp
+function clamp(val, min, max) {
+ return Math.max(min, Math.min(max, val));
+}
+// Helper: get direction vector
+function getDir(ax, ay, bx, by) {
+ var dx = bx - ax;
+ var dy = by - ay;
+ var len = Math.sqrt(dx * dx + dy * dy);
+ if (len === 0) return {
+ x: 0,
+ y: 0
+ };
+ return {
+ x: dx / len,
+ y: dy / len
+ };
+}
+// Helper: spawn enemy at random edge
+function spawnEnemy() {
+ var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
+ var ex, ey;
+ if (edge === 0) {
+ // top
+ ex = Math.random() * (GAME_W - 200) + 100;
+ ey = -80;
+ } else if (edge === 1) {
+ // right
+ ex = GAME_W + 80;
+ ey = Math.random() * (GAME_H - 200) + 100;
+ } else if (edge === 2) {
+ // bottom
+ ex = Math.random() * (GAME_W - 200) + 100;
+ ey = GAME_H + 80;
+ } else {
+ // left
+ ex = -80;
+ ey = Math.random() * (GAME_H - 200) + 100;
+ }
+ var enemy = new Enemy();
+ enemy.x = ex;
+ enemy.y = ey;
+ var dir = getDir(ex, ey, cowboy.x, cowboy.y);
+ enemy.dirX = dir.x;
+ enemy.dirY = dir.y;
+ enemy.speed = enemySpeed + Math.random() * 0.5 + (wave - 1) * 0.2;
+ enemy.hp = 1 + Math.floor(wave / 5);
+ enemies.push(enemy);
+ game.addChild(enemy);
+}
+// Helper: spawn upgrade at (x, y)
+function spawnUpgrade(x, y) {
+ var upg = new UpgradeDrop();
+ upg.x = x;
+ upg.y = y;
+ upgrades.push(upg);
+ game.addChild(upg);
+}
+// Handle movement (dragging cowboy)
+function handleMove(x, y, obj) {
+ if (dragNode) {
+ // Clamp to game area, avoid top left 100x100
+ dragNode.x = clamp(x, 120, GAME_W - 120);
+ dragNode.y = clamp(y, 120, GAME_H - 120);
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // Only allow drag if touch is on cowboy
+ var dx = x - cowboy.x;
+ var dy = y - cowboy.y;
+ if (dx * dx + dy * dy < 80 * 80) {
+ dragNode = cowboy;
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Handle tap/attack (whip or revolver)
+game.tap = function (x, y, obj) {
+ // Not used, as LK does not have tap event
+};
+// Touch: whip (short range, no cooldown)
+game.down2 = function (x, y, obj) {
+ // Not used, as LK does not have down2 event
+};
+// Touch: fire revolver (if ready)
+game.doubletap = function (x, y, obj) {
+ // Not used, as LK does not have doubletap event
+};
+// Whip attack: on quick tap (simulate with up event if not dragging)
+game.up = function (x, y, obj) {
+ if (!dragNode) {
+ // Whip attack in direction of tap
+ if (cowboy.whipCooldown <= 0) {
+ var dir = getDir(cowboy.x, cowboy.y, x, y);
+ var whip = new WhipAttack();
+ whip.x = cowboy.x + dir.x * 60;
+ whip.y = cowboy.y + dir.y * 60;
+ whip.dirX = dir.x;
+ whip.dirY = dir.y;
+ whip.rotation = Math.atan2(dir.y, dir.x);
+ whipAttacks.push(whip);
+ game.addChild(whip);
+ cowboy.whipCooldown = 20; // 1/3 second
+ // Animate whip
+ tween(whip, {
+ alpha: 0
+ }, {
+ duration: 200,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ whip.alpha = 1;
+ }
+ });
+ }
+ }
+ dragNode = null;
+};
+// Fire revolver: on long press (simulate with two-finger tap or hold, but here use a button)
+var fireBtn = new Text2('REVOLVER', {
+ size: 80,
+ fill: "#fff"
+});
+fireBtn.anchor.set(0.5, 0.5);
+LK.gui.bottom.addChild(fireBtn);
+fireBtn.y = -120;
+fireBtn.x = 0;
+fireBtn.interactive = true;
+fireBtn.down = function (x, y, obj) {
+ if (cowboy.pumpUnlocked) {
+ // Fire pump-action (spread shot)
+ if (cowboy.pumpCooldown <= 0) {
+ for (var i = -1; i <= 1; i++) {
+ var dir = getDir(cowboy.x, cowboy.y, cowboy.x + Math.cos(game.lastAimAngle + i * 0.18) * 100, cowboy.y + Math.sin(game.lastAimAngle + i * 0.18) * 100);
+ var bullet = new PumpBullet();
+ bullet.x = cowboy.x + dir.x * 70;
+ bullet.y = cowboy.y + dir.y * 70;
+ bullet.dirX = dir.x;
+ bullet.dirY = dir.y;
+ bullet.rotation = Math.atan2(dir.y, dir.x);
+ bullets.push(bullet);
+ game.addChild(bullet);
+ }
+ cowboy.pumpCooldown = 90; // 1.5s
+ }
+ } else {
+ // Fire revolver
+ if (cowboy.revolverCooldown <= 0) {
+ // Aim at last direction of movement or default right
+ var angle = game.lastAimAngle || 0;
+ var dir = {
+ x: Math.cos(angle),
+ y: Math.sin(angle)
+ };
+ var bullet = new RevolverBullet();
+ bullet.x = cowboy.x + dir.x * 70;
+ bullet.y = cowboy.y + dir.y * 70;
+ bullet.dirX = dir.x;
+ bullet.dirY = dir.y;
+ bullet.rotation = Math.atan2(dir.y, dir.x);
+ bullets.push(bullet);
+ game.addChild(bullet);
+ cowboy.revolverCooldown = cowboy.revolverCooldownTime;
+ }
+ }
+};
+// Track last aim direction (for revolver)
+game.lastAimAngle = 0;
+game.move = function (x, y, obj) {
+ if (dragNode) {
+ dragNode.x = clamp(x, 120, GAME_W - 120);
+ dragNode.y = clamp(y, 120, GAME_H - 120);
+ }
+ // Update aim angle
+ var dx = x - cowboy.x;
+ var dy = y - cowboy.y;
+ if (dx * dx + dy * dy > 10 * 10) {
+ game.lastAimAngle = Math.atan2(dy, dx);
+ }
+};
+// Main update loop
+game.update = function () {
+ // Cooldowns
+ if (cowboy.whipCooldown > 0) cowboy.whipCooldown--;
+ if (cowboy.revolverCooldown > 0) cowboy.revolverCooldown--;
+ if (cowboy.pumpCooldown > 0) cowboy.pumpCooldown--;
+ // Update UI
+ scoreTxt.setText(score);
+ if (cowboy.pumpUnlocked) {
+ revolverTxt.setText('Pump-Action: ' + (cowboy.pumpCooldown > 0 ? (cowboy.pumpCooldown / 60).toFixed(1) + 's' : 'Ready'));
+ } else {
+ revolverTxt.setText('Revolver: ' + (cowboy.revolverCooldown > 0 ? (cowboy.revolverCooldown / 60).toFixed(1) + 's' : 'Ready'));
+ }
+ upgradeTxt.setText('Upgrades: ' + cowboy.upgrades + '/3');
+ // Spawn enemies
+ spawnTimer--;
+ if (spawnTimer <= 0) {
+ spawnEnemy();
+ spawnTimer = Math.max(30, spawnInterval - wave * 2);
+ }
+ // Increase difficulty
+ if (LK.ticks % 600 === 0) {
+ // every 10s
+ wave++;
+ enemySpeed += 0.2;
+ }
+ // Update enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var e = enemies[i];
+ e.update();
+ // Re-aim at player
+ var dir = getDir(e.x, e.y, cowboy.x, cowboy.y);
+ e.dirX = dir.x;
+ e.dirY = dir.y;
+ // Out of bounds
+ if (e.x < -200 || e.x > GAME_W + 200 || e.y < -200 || e.y > GAME_H + 200) {
+ e.destroy();
+ enemies.splice(i, 1);
+ continue;
+ }
+ // Collide with player
+ if (dist(e.x, e.y, cowboy.x, cowboy.y) < e.radius + cowboy.radius - 10) {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Update bullets
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ var b = bullets[i];
+ b.update();
+ // Out of bounds
+ if (b.x < -100 || b.x > GAME_W + 100 || b.y < -100 || b.y > GAME_H + 100) {
+ b.destroy();
+ bullets.splice(i, 1);
+ continue;
+ }
+ // Hit enemy
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var e = enemies[j];
+ if (dist(b.x, b.y, e.x, e.y) < b.radius + e.radius) {
+ e.hp--;
+ if (e.hp <= 0) {
+ // Drop upgrade with 1/5 chance
+ if (Math.random() < 0.2) {
+ spawnUpgrade(e.x, e.y);
+ }
+ e.destroy();
+ enemies.splice(j, 1);
+ score++;
+ }
+ b.destroy();
+ bullets.splice(i, 1);
+ break;
+ }
+ }
+ }
+ // Update whip attacks
+ for (var i = whipAttacks.length - 1; i >= 0; i--) {
+ var w = whipAttacks[i];
+ w.update();
+ // Hit enemy
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var e = enemies[j];
+ if (dist(w.x + w.dirX * 40, w.y + w.dirY * 40, e.x, e.y) < w.radius + e.radius) {
+ e.hp--;
+ if (e.hp <= 0) {
+ if (Math.random() < 0.2) {
+ spawnUpgrade(e.x, e.y);
+ }
+ e.destroy();
+ enemies.splice(j, 1);
+ score++;
+ }
+ }
+ }
+ // Lifetime
+ if (w.lifetime <= 0) {
+ w.destroy();
+ whipAttacks.splice(i, 1);
+ }
+ }
+ // Update upgrades
+ for (var i = upgrades.length - 1; i >= 0; i--) {
+ var u = upgrades[i];
+ // Move toward player if close
+ if (dist(u.x, u.y, cowboy.x, cowboy.y) < 300) {
+ var dir = getDir(u.x, u.y, cowboy.x, cowboy.y);
+ u.x += dir.x * 8;
+ u.y += dir.y * 8;
+ }
+ // Collect
+ if (dist(u.x, u.y, cowboy.x, cowboy.y) < u.radius + cowboy.radius) {
+ cowboy.upgrades++;
+ if (cowboy.upgrades === 1) {
+ cowboy.revolverCooldownTime = Math.max(90, cowboy.revolverCooldownTime - 60); // 2s
+ } else if (cowboy.upgrades === 2) {
+ cowboy.revolverCooldownTime = Math.max(60, cowboy.revolverCooldownTime - 60); // 1s
+ } else if (cowboy.upgrades >= 3) {
+ cowboy.pumpUnlocked = true;
+ }
+ u.destroy();
+ upgrades.splice(i, 1);
+ }
+ }
+ // Win condition: survive 5 minutes or reach 100 score
+ if (score >= 100 || LK.ticks > 60 * 60 * 5) {
+ LK.showYouWin();
+ return;
+ }
+};
\ No newline at end of file
There is a + on the gun. In-Game asset. 2d. High contrast. No shadows
Zombie. In-Game asset. 2d. High contrast. No shadows
revovler. In-Game asset. 2d. High contrast. No shadows
Pump bullet. In-Game asset. 2d. High contrast. No shadows
Cowboy. In-Game asset. 2d. High contrast. No shadows
whip. In-Game asset. 2d. High contrast. No shadows
center circle. In-Game asset. 2d. High contrast. No shadows