/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigCactus = Container.expand(function () {
var self = Container.call(this);
var cactusGraphics = self.attachAsset('kaktus2', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 2;
self.direction = {
x: 0,
y: 0
};
self.lastIntersectingSheriff = false;
self.update = function () {
// Recalculate direction to always track sheriff's current position
var dx = sheriff.x - self.x;
var dy = sheriff.y - self.y;
var distance = calculateDistance(self.x, self.y, sheriff.x, sheriff.y);
if (distance > 0) {
self.direction.x = dx / distance;
self.direction.y = dy / distance;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Check collision with sheriff
var currentIntersecting = self.intersects(sheriff);
if (!self.lastIntersectingSheriff && currentIntersecting) {
sheriff.takeDamage(2); // Deal 2 damage
self.destroy();
var index = bigCacti.indexOf(self);
if (index > -1) {
bigCacti.splice(index, 1);
}
}
self.lastIntersectingSheriff = currentIntersecting;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
self.destroy();
var index = bigCacti.indexOf(self);
if (index > -1) {
bigCacti.splice(index, 1);
}
// Add gold
LK.setScore(LK.getScore() + 20);
scoreText.setText('Gold: ' + LK.getScore());
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.direction = {
x: 0,
y: 0
};
self.lastY = 0;
self.lastX = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Cactus = Container.expand(function () {
var self = Container.call(this);
var cactusGraphics = self.attachAsset('cactus', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = {
x: 0,
y: 0
};
self.lastIntersectingSheriff = false;
self.update = function () {
// Recalculate direction to always track sheriff's current position
var dx = sheriff.x - self.x;
var dy = sheriff.y - self.y;
var distance = calculateDistance(self.x, self.y, sheriff.x, sheriff.y);
if (distance > 0) {
self.direction.x = dx / distance;
self.direction.y = dy / distance;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Check collision with sheriff
var currentIntersecting = self.intersects(sheriff);
if (!self.lastIntersectingSheriff && currentIntersecting) {
sheriff.takeDamage();
self.destroy();
var index = cacti.indexOf(self);
if (index > -1) {
cacti.splice(index, 1);
}
}
self.lastIntersectingSheriff = currentIntersecting;
};
return self;
});
var GoldenStar = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('goldenStar', {
anchorX: 0.5,
anchorY: 0.5
});
self.lastIntersectingSheriff = false;
self.update = function () {
// Rotate the star
starGraphics.rotation += 0.1;
// Check collision with sheriff
var currentIntersecting = self.intersects(sheriff);
if (!self.lastIntersectingSheriff && currentIntersecting) {
sheriff.activateInvincibility();
self.destroy();
var index = goldenStars.indexOf(self);
if (index > -1) {
goldenStars.splice(index, 1);
}
}
self.lastIntersectingSheriff = currentIntersecting;
};
return self;
});
var Sheriff = Container.expand(function () {
var self = Container.call(this);
var sheriffGraphics = self.attachAsset('sheriff', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.invincible = false;
self.invincibilityEndTime = 0;
self.rapidFire = false;
self.rapidFireEndTime = 0;
self.update = function () {
// Check if invincibility expired
if (self.invincible && LK.ticks > self.invincibilityEndTime) {
self.invincible = false;
sheriffGraphics.tint = 0xFFFFFF; // Reset tint
}
// Check if rapid fire expired
if (self.rapidFire && LK.ticks > self.rapidFireEndTime) {
self.rapidFire = false;
}
// Flash effect when invincible
if (self.invincible) {
var flashValue = Math.sin(LK.ticks * 0.3) > 0 ? 0xFFD700 : 0xFFFFFF;
sheriffGraphics.tint = flashValue;
}
};
self.takeDamage = function (damage) {
if (!self.invincible) {
damage = damage || 1; // Default to 1 damage if not specified
self.health -= damage;
LK.getSound('hit').play();
// Flash red briefly
sheriffGraphics.tint = 0xFF0000;
LK.setTimeout(function () {
if (!self.invincible) {
sheriffGraphics.tint = 0xFFFFFF;
}
}, 200);
if (self.health <= 0) {
LK.showGameOver();
}
}
};
self.activateInvincibility = function () {
self.invincible = true;
self.invincibilityEndTime = LK.ticks + 600; // 10 seconds at 60fps
LK.getSound('powerup').play();
};
self.activateRapidFire = function () {
self.rapidFire = true;
self.rapidFireEndTime = LK.ticks + 600; // 10 seconds at 60fps
LK.getSound('powerup').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xDEB887
});
/****
* Game Code
****/
var sheriff = game.addChild(new Sheriff());
sheriff.x = 1024;
sheriff.y = 1366;
var cacti = [];
var bullets = [];
var goldenStars = [];
var bigCacti = [];
var waveNumber = 1;
var cactusSpawnRate = 120; // frames between spawns
var cactusSpeed = 2;
var dragNode = null;
var lastShootTime = 0;
var shootInterval = 60; // 60 frames = 1 second at 60fps
// UI Elements
var healthText = new Text2('Health: 10', {
size: 60,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.y = 80; // Move health text down to make room for upgrade button
LK.gui.topRight.addChild(healthText);
// Upgrade button and counter
var upgradeButton = new Container();
var buttonBg = upgradeButton.attachAsset('button', {
width: 150,
height: 60,
color: 0x0000FF,
shape: 'box',
anchorX: 1,
anchorY: 0
});
LK.gui.topRight.addChild(upgradeButton);
var upgradeCounter = new Text2('0', {
size: 50,
fill: 0x0000FF
});
upgradeCounter.anchor.set(1, 0);
upgradeCounter.x = -160; // Position to the left of the button
LK.gui.topRight.addChild(upgradeCounter);
var upgradeLevel = 0;
var upgradeCost = 10;
var scoreText = new Text2('Gold: 0', {
size: 60,
fill: 0xFFD700
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var invincibilityText = new Text2('', {
size: 50,
fill: 0xFFD700
});
invincibilityText.anchor.set(0.5, 0);
invincibilityText.y = 80;
LK.gui.top.addChild(invincibilityText);
var rapidFireText = new Text2('', {
size: 50,
fill: 0xFF8C00
});
rapidFireText.anchor.set(0.5, 0);
rapidFireText.y = 140;
LK.gui.top.addChild(rapidFireText);
var waveText = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 120; // Offset to avoid menu icon
function spawnCactus() {
var cactus = new Cactus();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
cactus.x = Math.random() * 2048;
cactus.y = -30;
break;
case 1:
// Right
cactus.x = 2078;
cactus.y = Math.random() * 2732;
break;
case 2:
// Bottom
cactus.x = Math.random() * 2048;
cactus.y = 2762;
break;
case 3:
// Left
cactus.x = -30;
cactus.y = Math.random() * 2732;
break;
}
var direction = calculateDirection(cactus.x, cactus.y, sheriff.x, sheriff.y);
cactus.direction.x = direction.x;
cactus.direction.y = direction.y;
cactus.speed = cactusSpeed;
cacti.push(cactus);
game.addChild(cactus);
}
function spawnBigCactus() {
var bigCactus = new BigCactus();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
bigCactus.x = Math.random() * 2048;
bigCactus.y = -30;
break;
case 1:
// Right
bigCactus.x = 2078;
bigCactus.y = Math.random() * 2732;
break;
case 2:
// Bottom
bigCactus.x = Math.random() * 2048;
bigCactus.y = 2762;
break;
case 3:
// Left
bigCactus.x = -30;
bigCactus.y = Math.random() * 2732;
break;
}
var direction = calculateDirection(bigCactus.x, bigCactus.y, sheriff.x, sheriff.y);
bigCactus.direction.x = direction.x;
bigCactus.direction.y = direction.y;
bigCactus.speed = cactusSpeed;
bigCacti.push(bigCactus);
game.addChild(bigCactus);
}
function spawnGoldenStar() {
var star = new GoldenStar();
star.x = Math.random() * 1800 + 124; // Keep away from edges
star.y = Math.random() * 2400 + 166;
goldenStars.push(star);
game.addChild(star);
}
function calculateDistance(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
function calculateDirection(fromX, fromY, toX, toY) {
var dx = toX - fromX;
var dy = toY - fromY;
var distance = calculateDistance(fromX, fromY, toX, toY);
return {
x: distance > 0 ? dx / distance : 0,
y: distance > 0 ? dy / distance : 0
};
}
function shootBullet(targetX, targetY) {
var bullet = new Bullet();
bullet.x = sheriff.x;
bullet.y = sheriff.y;
// Find the nearest cactus (including big cacti)
var nearestCactus = null;
var nearestDistance = Infinity;
for (var i = 0; i < cacti.length; i++) {
var cactus = cacti[i];
var distance = calculateDistance(sheriff.x, sheriff.y, cactus.x, cactus.y);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestCactus = cactus;
}
}
// Also check big cacti
for (var i = 0; i < bigCacti.length; i++) {
var bigCactus = bigCacti[i];
var distance = calculateDistance(sheriff.x, sheriff.y, bigCactus.x, bigCactus.y);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestCactus = bigCactus;
}
}
// If there's a nearest cactus, aim at it, otherwise use touch direction
var direction;
if (nearestCactus) {
direction = calculateDirection(sheriff.x, sheriff.y, nearestCactus.x, nearestCactus.y);
} else {
direction = calculateDirection(sheriff.x, sheriff.y, targetX, targetY);
}
bullet.direction.x = direction.x;
bullet.direction.y = direction.y;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
// Upgrade button click handler
upgradeButton.down = function (x, y, obj) {
if (LK.getScore() >= upgradeCost) {
// Deduct gold
LK.setScore(LK.getScore() - upgradeCost);
scoreText.setText('Gold: ' + LK.getScore());
// Increase shooting speed by reducing interval by 10 frames (10/60 = ~167ms)
shootInterval = Math.max(10, shootInterval - 10); // Minimum 10 frames between shots
// Increment upgrade level and counter
upgradeLevel++;
upgradeCounter.setText(upgradeLevel.toString());
// Increase cost for next upgrade
upgradeCost += 10;
}
};
game.down = function (x, y, obj) {
dragNode = sheriff;
sheriff.x = x;
sheriff.y = y;
};
game.move = function (x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
// Automatic shooting - rapid fire shoots every 30 frames (0.5 seconds), normal shoots every 60 frames (1 second)
var currentShootInterval = sheriff.rapidFire ? 30 : shootInterval;
if (LK.ticks - lastShootTime >= currentShootInterval) {
shootBullet(sheriff.x, sheriff.y);
lastShootTime = LK.ticks;
}
// Spawn cacti - spawn multiple based on wave number
if (LK.ticks % cactusSpawnRate === 0) {
var cactusesToSpawn = Math.min(waveNumber, 5); // Cap at 5 cacti per spawn
for (var c = 0; c < cactusesToSpawn; c++) {
spawnCactus();
}
}
// Spawn big cacti starting from wave 3 - spawn multiple based on wave number
if (waveNumber >= 3 && LK.ticks % (cactusSpawnRate * 3) === 0) {
var bigCactiToSpawn = Math.min(waveNumber - 2, 3); // Start from wave 3, cap at 3 big cacti per spawn
for (var bc = 0; bc < bigCactiToSpawn; bc++) {
spawnBigCactus();
}
}
// Spawn golden stars (5% chance every 3 seconds)
if (LK.ticks % 180 === 0 && Math.random() < 0.05) {
spawnGoldenStar();
}
// Update wave progression
var newWave = Math.floor(LK.ticks / 1800) + 1; // New wave every 30 seconds
if (newWave > waveNumber) {
waveNumber = newWave;
cactusSpawnRate = Math.max(30, cactusSpawnRate - 10); // Increase spawn rate
cactusSpeed = Math.min(5, cactusSpeed + 0.3); // Increase speed
waveText.setText('Wave: ' + waveNumber);
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check bullet-cactus collisions
for (var j = cacti.length - 1; j >= 0; j--) {
var cactus = cacti[j];
if (bullet.intersects(cactus)) {
// Destroy cactus and bullet
cactus.destroy();
cacti.splice(j, 1);
bullet.destroy();
bullets.splice(i, 1);
// Add gold
LK.setScore(LK.getScore() + 10);
scoreText.setText('Gold: ' + LK.getScore());
break;
}
}
// Check bullet-big cactus collisions
for (var j = bigCacti.length - 1; j >= 0; j--) {
var bigCactus = bigCacti[j];
if (bullet.intersects(bigCactus)) {
// Damage big cactus and destroy bullet
bigCactus.takeDamage();
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
}
// Remove bullets that go off screen
for (var k = bullets.length - 1; k >= 0; k--) {
var bullet = bullets[k];
if (bullet.x < -100 || bullet.x > 2148 || bullet.y < -100 || bullet.y > 2832) {
bullet.destroy();
bullets.splice(k, 1);
}
}
// Remove cacti that go too far off screen
for (var k = cacti.length - 1; k >= 0; k--) {
var cactus = cacti[k];
if (cactus.x < -100 || cactus.x > 2148 || cactus.y < -100 || cactus.y > 2832) {
cactus.destroy();
cacti.splice(k, 1);
}
}
// Remove big cacti that go too far off screen
for (var k = bigCacti.length - 1; k >= 0; k--) {
var bigCactus = bigCacti[k];
if (bigCactus.x < -100 || bigCactus.x > 2148 || bigCactus.y < -100 || bigCactus.y > 2832) {
bigCactus.destroy();
bigCacti.splice(k, 1);
}
}
// Update UI
healthText.setText('Health: ' + sheriff.health);
// Update invincibility timer display
if (sheriff.invincible) {
var timeLeft = Math.ceil((sheriff.invincibilityEndTime - LK.ticks) / 60);
invincibilityText.setText('Invincible: ' + timeLeft + 's');
} else {
invincibilityText.setText('');
}
// Update rapid fire timer display
if (sheriff.rapidFire) {
var timeLeft = Math.ceil((sheriff.rapidFireEndTime - LK.ticks) / 60);
rapidFireText.setText('Rapid Fire: ' + timeLeft + 's');
} else {
rapidFireText.setText('');
}
};
// Goal already implemented: BigCactus.takeDamage() method already awards 20 gold when kaktus2 is destroyed /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigCactus = Container.expand(function () {
var self = Container.call(this);
var cactusGraphics = self.attachAsset('kaktus2', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 2;
self.direction = {
x: 0,
y: 0
};
self.lastIntersectingSheriff = false;
self.update = function () {
// Recalculate direction to always track sheriff's current position
var dx = sheriff.x - self.x;
var dy = sheriff.y - self.y;
var distance = calculateDistance(self.x, self.y, sheriff.x, sheriff.y);
if (distance > 0) {
self.direction.x = dx / distance;
self.direction.y = dy / distance;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Check collision with sheriff
var currentIntersecting = self.intersects(sheriff);
if (!self.lastIntersectingSheriff && currentIntersecting) {
sheriff.takeDamage(2); // Deal 2 damage
self.destroy();
var index = bigCacti.indexOf(self);
if (index > -1) {
bigCacti.splice(index, 1);
}
}
self.lastIntersectingSheriff = currentIntersecting;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
self.destroy();
var index = bigCacti.indexOf(self);
if (index > -1) {
bigCacti.splice(index, 1);
}
// Add gold
LK.setScore(LK.getScore() + 20);
scoreText.setText('Gold: ' + LK.getScore());
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.direction = {
x: 0,
y: 0
};
self.lastY = 0;
self.lastX = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Cactus = Container.expand(function () {
var self = Container.call(this);
var cactusGraphics = self.attachAsset('cactus', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = {
x: 0,
y: 0
};
self.lastIntersectingSheriff = false;
self.update = function () {
// Recalculate direction to always track sheriff's current position
var dx = sheriff.x - self.x;
var dy = sheriff.y - self.y;
var distance = calculateDistance(self.x, self.y, sheriff.x, sheriff.y);
if (distance > 0) {
self.direction.x = dx / distance;
self.direction.y = dy / distance;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Check collision with sheriff
var currentIntersecting = self.intersects(sheriff);
if (!self.lastIntersectingSheriff && currentIntersecting) {
sheriff.takeDamage();
self.destroy();
var index = cacti.indexOf(self);
if (index > -1) {
cacti.splice(index, 1);
}
}
self.lastIntersectingSheriff = currentIntersecting;
};
return self;
});
var GoldenStar = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('goldenStar', {
anchorX: 0.5,
anchorY: 0.5
});
self.lastIntersectingSheriff = false;
self.update = function () {
// Rotate the star
starGraphics.rotation += 0.1;
// Check collision with sheriff
var currentIntersecting = self.intersects(sheriff);
if (!self.lastIntersectingSheriff && currentIntersecting) {
sheriff.activateInvincibility();
self.destroy();
var index = goldenStars.indexOf(self);
if (index > -1) {
goldenStars.splice(index, 1);
}
}
self.lastIntersectingSheriff = currentIntersecting;
};
return self;
});
var Sheriff = Container.expand(function () {
var self = Container.call(this);
var sheriffGraphics = self.attachAsset('sheriff', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.invincible = false;
self.invincibilityEndTime = 0;
self.rapidFire = false;
self.rapidFireEndTime = 0;
self.update = function () {
// Check if invincibility expired
if (self.invincible && LK.ticks > self.invincibilityEndTime) {
self.invincible = false;
sheriffGraphics.tint = 0xFFFFFF; // Reset tint
}
// Check if rapid fire expired
if (self.rapidFire && LK.ticks > self.rapidFireEndTime) {
self.rapidFire = false;
}
// Flash effect when invincible
if (self.invincible) {
var flashValue = Math.sin(LK.ticks * 0.3) > 0 ? 0xFFD700 : 0xFFFFFF;
sheriffGraphics.tint = flashValue;
}
};
self.takeDamage = function (damage) {
if (!self.invincible) {
damage = damage || 1; // Default to 1 damage if not specified
self.health -= damage;
LK.getSound('hit').play();
// Flash red briefly
sheriffGraphics.tint = 0xFF0000;
LK.setTimeout(function () {
if (!self.invincible) {
sheriffGraphics.tint = 0xFFFFFF;
}
}, 200);
if (self.health <= 0) {
LK.showGameOver();
}
}
};
self.activateInvincibility = function () {
self.invincible = true;
self.invincibilityEndTime = LK.ticks + 600; // 10 seconds at 60fps
LK.getSound('powerup').play();
};
self.activateRapidFire = function () {
self.rapidFire = true;
self.rapidFireEndTime = LK.ticks + 600; // 10 seconds at 60fps
LK.getSound('powerup').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xDEB887
});
/****
* Game Code
****/
var sheriff = game.addChild(new Sheriff());
sheriff.x = 1024;
sheriff.y = 1366;
var cacti = [];
var bullets = [];
var goldenStars = [];
var bigCacti = [];
var waveNumber = 1;
var cactusSpawnRate = 120; // frames between spawns
var cactusSpeed = 2;
var dragNode = null;
var lastShootTime = 0;
var shootInterval = 60; // 60 frames = 1 second at 60fps
// UI Elements
var healthText = new Text2('Health: 10', {
size: 60,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.y = 80; // Move health text down to make room for upgrade button
LK.gui.topRight.addChild(healthText);
// Upgrade button and counter
var upgradeButton = new Container();
var buttonBg = upgradeButton.attachAsset('button', {
width: 150,
height: 60,
color: 0x0000FF,
shape: 'box',
anchorX: 1,
anchorY: 0
});
LK.gui.topRight.addChild(upgradeButton);
var upgradeCounter = new Text2('0', {
size: 50,
fill: 0x0000FF
});
upgradeCounter.anchor.set(1, 0);
upgradeCounter.x = -160; // Position to the left of the button
LK.gui.topRight.addChild(upgradeCounter);
var upgradeLevel = 0;
var upgradeCost = 10;
var scoreText = new Text2('Gold: 0', {
size: 60,
fill: 0xFFD700
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var invincibilityText = new Text2('', {
size: 50,
fill: 0xFFD700
});
invincibilityText.anchor.set(0.5, 0);
invincibilityText.y = 80;
LK.gui.top.addChild(invincibilityText);
var rapidFireText = new Text2('', {
size: 50,
fill: 0xFF8C00
});
rapidFireText.anchor.set(0.5, 0);
rapidFireText.y = 140;
LK.gui.top.addChild(rapidFireText);
var waveText = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 120; // Offset to avoid menu icon
function spawnCactus() {
var cactus = new Cactus();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
cactus.x = Math.random() * 2048;
cactus.y = -30;
break;
case 1:
// Right
cactus.x = 2078;
cactus.y = Math.random() * 2732;
break;
case 2:
// Bottom
cactus.x = Math.random() * 2048;
cactus.y = 2762;
break;
case 3:
// Left
cactus.x = -30;
cactus.y = Math.random() * 2732;
break;
}
var direction = calculateDirection(cactus.x, cactus.y, sheriff.x, sheriff.y);
cactus.direction.x = direction.x;
cactus.direction.y = direction.y;
cactus.speed = cactusSpeed;
cacti.push(cactus);
game.addChild(cactus);
}
function spawnBigCactus() {
var bigCactus = new BigCactus();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
bigCactus.x = Math.random() * 2048;
bigCactus.y = -30;
break;
case 1:
// Right
bigCactus.x = 2078;
bigCactus.y = Math.random() * 2732;
break;
case 2:
// Bottom
bigCactus.x = Math.random() * 2048;
bigCactus.y = 2762;
break;
case 3:
// Left
bigCactus.x = -30;
bigCactus.y = Math.random() * 2732;
break;
}
var direction = calculateDirection(bigCactus.x, bigCactus.y, sheriff.x, sheriff.y);
bigCactus.direction.x = direction.x;
bigCactus.direction.y = direction.y;
bigCactus.speed = cactusSpeed;
bigCacti.push(bigCactus);
game.addChild(bigCactus);
}
function spawnGoldenStar() {
var star = new GoldenStar();
star.x = Math.random() * 1800 + 124; // Keep away from edges
star.y = Math.random() * 2400 + 166;
goldenStars.push(star);
game.addChild(star);
}
function calculateDistance(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
function calculateDirection(fromX, fromY, toX, toY) {
var dx = toX - fromX;
var dy = toY - fromY;
var distance = calculateDistance(fromX, fromY, toX, toY);
return {
x: distance > 0 ? dx / distance : 0,
y: distance > 0 ? dy / distance : 0
};
}
function shootBullet(targetX, targetY) {
var bullet = new Bullet();
bullet.x = sheriff.x;
bullet.y = sheriff.y;
// Find the nearest cactus (including big cacti)
var nearestCactus = null;
var nearestDistance = Infinity;
for (var i = 0; i < cacti.length; i++) {
var cactus = cacti[i];
var distance = calculateDistance(sheriff.x, sheriff.y, cactus.x, cactus.y);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestCactus = cactus;
}
}
// Also check big cacti
for (var i = 0; i < bigCacti.length; i++) {
var bigCactus = bigCacti[i];
var distance = calculateDistance(sheriff.x, sheriff.y, bigCactus.x, bigCactus.y);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestCactus = bigCactus;
}
}
// If there's a nearest cactus, aim at it, otherwise use touch direction
var direction;
if (nearestCactus) {
direction = calculateDirection(sheriff.x, sheriff.y, nearestCactus.x, nearestCactus.y);
} else {
direction = calculateDirection(sheriff.x, sheriff.y, targetX, targetY);
}
bullet.direction.x = direction.x;
bullet.direction.y = direction.y;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
// Upgrade button click handler
upgradeButton.down = function (x, y, obj) {
if (LK.getScore() >= upgradeCost) {
// Deduct gold
LK.setScore(LK.getScore() - upgradeCost);
scoreText.setText('Gold: ' + LK.getScore());
// Increase shooting speed by reducing interval by 10 frames (10/60 = ~167ms)
shootInterval = Math.max(10, shootInterval - 10); // Minimum 10 frames between shots
// Increment upgrade level and counter
upgradeLevel++;
upgradeCounter.setText(upgradeLevel.toString());
// Increase cost for next upgrade
upgradeCost += 10;
}
};
game.down = function (x, y, obj) {
dragNode = sheriff;
sheriff.x = x;
sheriff.y = y;
};
game.move = function (x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
// Automatic shooting - rapid fire shoots every 30 frames (0.5 seconds), normal shoots every 60 frames (1 second)
var currentShootInterval = sheriff.rapidFire ? 30 : shootInterval;
if (LK.ticks - lastShootTime >= currentShootInterval) {
shootBullet(sheriff.x, sheriff.y);
lastShootTime = LK.ticks;
}
// Spawn cacti - spawn multiple based on wave number
if (LK.ticks % cactusSpawnRate === 0) {
var cactusesToSpawn = Math.min(waveNumber, 5); // Cap at 5 cacti per spawn
for (var c = 0; c < cactusesToSpawn; c++) {
spawnCactus();
}
}
// Spawn big cacti starting from wave 3 - spawn multiple based on wave number
if (waveNumber >= 3 && LK.ticks % (cactusSpawnRate * 3) === 0) {
var bigCactiToSpawn = Math.min(waveNumber - 2, 3); // Start from wave 3, cap at 3 big cacti per spawn
for (var bc = 0; bc < bigCactiToSpawn; bc++) {
spawnBigCactus();
}
}
// Spawn golden stars (5% chance every 3 seconds)
if (LK.ticks % 180 === 0 && Math.random() < 0.05) {
spawnGoldenStar();
}
// Update wave progression
var newWave = Math.floor(LK.ticks / 1800) + 1; // New wave every 30 seconds
if (newWave > waveNumber) {
waveNumber = newWave;
cactusSpawnRate = Math.max(30, cactusSpawnRate - 10); // Increase spawn rate
cactusSpeed = Math.min(5, cactusSpeed + 0.3); // Increase speed
waveText.setText('Wave: ' + waveNumber);
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check bullet-cactus collisions
for (var j = cacti.length - 1; j >= 0; j--) {
var cactus = cacti[j];
if (bullet.intersects(cactus)) {
// Destroy cactus and bullet
cactus.destroy();
cacti.splice(j, 1);
bullet.destroy();
bullets.splice(i, 1);
// Add gold
LK.setScore(LK.getScore() + 10);
scoreText.setText('Gold: ' + LK.getScore());
break;
}
}
// Check bullet-big cactus collisions
for (var j = bigCacti.length - 1; j >= 0; j--) {
var bigCactus = bigCacti[j];
if (bullet.intersects(bigCactus)) {
// Damage big cactus and destroy bullet
bigCactus.takeDamage();
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
}
// Remove bullets that go off screen
for (var k = bullets.length - 1; k >= 0; k--) {
var bullet = bullets[k];
if (bullet.x < -100 || bullet.x > 2148 || bullet.y < -100 || bullet.y > 2832) {
bullet.destroy();
bullets.splice(k, 1);
}
}
// Remove cacti that go too far off screen
for (var k = cacti.length - 1; k >= 0; k--) {
var cactus = cacti[k];
if (cactus.x < -100 || cactus.x > 2148 || cactus.y < -100 || cactus.y > 2832) {
cactus.destroy();
cacti.splice(k, 1);
}
}
// Remove big cacti that go too far off screen
for (var k = bigCacti.length - 1; k >= 0; k--) {
var bigCactus = bigCacti[k];
if (bigCactus.x < -100 || bigCactus.x > 2148 || bigCactus.y < -100 || bigCactus.y > 2832) {
bigCactus.destroy();
bigCacti.splice(k, 1);
}
}
// Update UI
healthText.setText('Health: ' + sheriff.health);
// Update invincibility timer display
if (sheriff.invincible) {
var timeLeft = Math.ceil((sheriff.invincibilityEndTime - LK.ticks) / 60);
invincibilityText.setText('Invincible: ' + timeLeft + 's');
} else {
invincibilityText.setText('');
}
// Update rapid fire timer display
if (sheriff.rapidFire) {
var timeLeft = Math.ceil((sheriff.rapidFireEndTime - LK.ticks) / 60);
rapidFireText.setText('Rapid Fire: ' + timeLeft + 's');
} else {
rapidFireText.setText('');
}
};
// Goal already implemented: BigCactus.takeDamage() method already awards 20 gold when kaktus2 is destroyed
göğsünde bir şerif yıldızı olan silahlı bir stickman. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
kafalarında kaktüs çiçeği olan 2 kaktüs . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
üçlarında topçuk olan gökkuşağı bir yıldız. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
altın renginde mermi. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
büyük bir kaktüs. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
üzerinde SPEED UP yazan bir buton. In-Game asset. 2d. High contrast. No shadows