User prompt
Also make a very rare t-rex for 200 money
User prompt
Wherever I click on the screen, the gun will hit there.
Code edit (1 edits merged)
Please save this source code
User prompt
Forest Hunter Tycoon
Initial prompt
We are hunters and we hunt animals in the forest with guns and then we hunt and sell them and buy guns with the money we get from selling them. lion 50 money zebra 30 money bird 10 money Spider 2 money
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Animal base class var Animal = Container.expand(function () { var self = Container.call(this); self.type = 'animal'; self.value = 0; self.speed = 0; self.caught = false; self.init = function (animalType) { self.animalType = animalType; var assetId; if (animalType === 'trex') { assetId = 'trex'; self.value = 146; self.speed = 2.2 + Math.random() * 0.8; } else if (animalType === 'lion') { assetId = 'lion'; self.value = 55; self.speed = 3.2 + Math.random() * 1.2; } else if (animalType === 'zebra') { assetId = 'zebra'; self.value = 35; self.speed = 3.8 + Math.random() * 1.5; } else if (animalType === 'bird') { assetId = 'bird'; self.value = 15; self.speed = 5.5 + Math.random() * 2.5; } else if (animalType === 'spider') { assetId = 'spider'; self.value = 10; self.speed = 2.2 + Math.random() * 1.2; } else if (animalType === 'stork') { assetId = 'bird'; self.value = 100; self.speed = 4.5 + Math.random() * 1.5; // Tint the stork to make it visually distinct // (LK.getAsset does not support dynamic tint, so we use the same asset for now) } else if (animalType === 'unicorn') { assetId = 'unicorn'; self.value = 126; self.speed = 3.5 + Math.random() * 1.2; } self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.direction = Math.random() < 0.5 ? 1 : -1; if (animalType === 'lion') { // Let lions roam farther away from the player (avoid center) // Top or bottom 1/3 of the screen if (Math.random() < 0.5) { self.y = 500 + Math.random() * 400; // Top band } else { self.y = 1900 + Math.random() * 300; // Bottom band } } else { self.y = 500 + Math.random() * 1700; } if (self.direction === 1) { self.x = -self.asset.width / 2; } else { self.x = 2048 + self.asset.width / 2; self.asset.scaleX = -1; } }; self.update = function () { if (self.caught) return; self.x += self.speed * self.direction; // Remove if off screen if (self.direction === 1 && self.x > 2048 + self.asset.width / 2 || self.direction === -1 && self.x < -self.asset.width / 2) { self.destroy(); var idx = animals.indexOf(self); if (idx !== -1) animals.splice(idx, 1); } }; self.getSellValue = function () { return self.value; }; return self; }); // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.range = 0; self.gunType = 'basic'; self.init = function (gunType) { self.gunType = gunType; var assetId; if (gunType === 'basic') { assetId = 'bullet_basic'; self.speed = 28; self.range = 1200; } else if (gunType === 'rapid') { assetId = 'bullet_rapid'; self.speed = 36; self.range = 900; } else if (gunType === 'sniper') { assetId = 'bullet_sniper'; self.speed = 44; self.range = 1800; } else if (gunType === 'blaster') { assetId = 'bullet_sniper'; self.speed = 60; self.range = 2200; } self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.distance = 0; }; self.update = function () { if (typeof self.dirX === "number" && typeof self.dirY === "number") { self.x += self.speed * self.dirX; self.y += self.speed * self.dirY; self.distance += self.speed; } else { self.x += self.speed; self.distance += self.speed; } if (self.distance > self.range || self.x < -100 || self.x > 2200 || self.y < -100 || self.y > 2832) { self.destroy(); var idx = bullets.indexOf(self); if (idx !== -1) bullets.splice(idx, 1); } }; return self; }); // Gun class var Gun = Container.expand(function () { var self = Container.call(this); self.gunType = 'basic'; self.reloadTime = 0; self.lastShotTick = 0; self.init = function (gunType) { self.gunType = gunType; var assetId; if (gunType === 'basic') { assetId = 'gun_basic'; self.reloadTime = 30; } else if (gunType === 'rapid') { assetId = 'gun_rapid'; self.reloadTime = 12; } else if (gunType === 'sniper') { assetId = 'gun_sniper'; self.reloadTime = 60; } else if (gunType === 'blaster') { assetId = 'gun_sniper'; self.reloadTime = 18; } self.asset = self.attachAsset(assetId, { anchorX: 0.1, anchorY: 0.5 }); }; self.canShoot = function () { return LK.ticks - self.lastShotTick >= self.reloadTime; }; self.shoot = function () { self.lastShotTick = LK.ticks; }; return self; }); // Turret class var Turret = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('turret', { anchorX: 0.5, anchorY: 0.5 }); self.fireCooldown = 0; self.update = function () { // Find nearest animal within 700px var closest = null; var minDist = 99999; for (var i = 0; i < animals.length; i++) { var a = animals[i]; if (a.caught) continue; var dx = a.x - self.x; var dy = a.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 700 && dist < minDist) { minDist = dist; closest = a; } } // Fire at nearest animal every 18 ticks (~3.3 shots/sec) if (closest && self.fireCooldown <= 0) { var bullet = new Bullet(); bullet.init('rapid'); bullet.x = self.x + self.asset.width * 0.5; bullet.y = self.y; var dx = closest.x - bullet.x; var dy = closest.y - bullet.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist === 0) dist = 1; bullet.dirX = dx / dist; bullet.dirY = dy / dist; bullet.rotation = Math.atan2(dy, dx); game.addChild(bullet); bullets.push(bullet); LK.getSound('shoot').play(); self.fireCooldown = 18; } if (self.fireCooldown > 0) self.fireCooldown--; }; return self; }); /**** * Initialize Game ****/ // Helper: spawn animal var game = new LK.Game({ backgroundColor: 0x2e5d2c }); /**** * Game Code ****/ // Turret asset // Music // Sounds // Bullets // Guns // Animals // Game state variables var animals = []; var bullets = []; var caughtAnimals = []; var money = 0; var killCount = 0; // Track total kills var gunLevel = 0; // 0: basic, 1: rapid, 2: sniper, 3: blaster var gunTypes = ['basic', 'rapid', 'sniper', 'blaster']; var gunPrices = [0, 350, 600, 1500]; var gunNames = ['Basic Gun', 'Rapid Gun', 'Sniper Gun', 'Blaster']; var gun; var animalsSpedUp = false; // Track if animals have been sped up // Tree spawn timer variables var treeSpawnTimer = 0; var treeSpawnInterval = 300; // 5 seconds at 60 FPS // UI var moneyTxt = new Text2('$0', { size: 90, fill: 0xFFF700 }); moneyTxt.anchor.set(0.5, 0); LK.gui.top.addChild(moneyTxt); var caughtTxt = new Text2('Bag: 0', { size: 70, fill: 0xFFFFFF }); caughtTxt.anchor.set(0.5, 0); LK.gui.top.addChild(caughtTxt); caughtTxt.y = 110; var killTxt = new Text2('Kills: 0', { size: 70, fill: 0xFF4444 }); killTxt.anchor.set(0, 1); // anchor bottom left LK.gui.bottomLeft.addChild(killTxt); killTxt.x = 0; killTxt.y = 0; var gunTxt = new Text2('Gun: Basic', { size: 60, fill: 0xFFFFFF }); gunTxt.anchor.set(0.5, 0); LK.gui.top.addChild(gunTxt); gunTxt.y = 200; var sellBtn = new Text2('Sell', { size: 70, fill: 0xFF8800 }); sellBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(sellBtn); sellBtn.y = -200; var upgradeBtn = new Text2('Upgrade', { size: 70, fill: 0x00FF00 }); upgradeBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(upgradeBtn); upgradeBtn.y = -120; // --- Buy Turret Button --- var buyTurretBtn = new Text2('Buy Turret ($1500)', { size: 70, fill: 0x00BFFF }); buyTurretBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(buyTurretBtn); buyTurretBtn.y = -40; // Track if player owns a turret var hasTurret = false; var playerTurret = null; // Gun gun = new Gun(); gun.init(gunTypes[gunLevel]); game.addChild(gun); gun.x = 2048 / 2; gun.y = 2732 / 2; // Friend button removed // Track if skin is bought var skinBought = false; // Turret spawn timer variables var turretSpawnInterval = 660; // 11 seconds at 60 FPS var turretSpawnTicks = 0; var turrets = []; var turretStayDuration = 300; // 5 seconds at 60 FPS function spawnTurret() { var turret = new Turret(); // Place turrets in a circle around the gun, up to 6 turrets var turretCount = turrets.length; var angle = turretCount % 6 * (Math.PI * 2 / 6); var radius = 500; turret.x = gun.x + Math.cos(angle) * radius; turret.y = gun.y + Math.sin(angle) * radius; game.addChild(turret); // Add a timer property to track how long the turret has been alive turret.ticksAlive = 0; turrets.push(turret); // Reset turret spawn timer turretSpawnTicks = 0; } // Helper: spawn animal function spawnAnimal() { // Very rarely, spawn a unicorn if (Math.random() < 0.0015) { var unicorn = new Animal(); unicorn.init('unicorn'); game.addChild(unicorn); animals.push(unicorn); return; } // Very rarely, spawn a stork if (Math.random() < 0.003) { var stork = new Animal(); stork.init('stork'); game.addChild(stork); animals.push(stork); return; } var r = Math.random(); var animalType; // After killCount >= 34, do not spawn spiders or birds if (killCount >= 34) { // Only spawn trex, lion, zebra, unicorn, stork if (r < 0.01) { animalType = 'trex'; } else if (r < 0.10) { animalType = 'lion'; } else if (r < 0.20) { animalType = 'zebra'; } else if (r < 0.21) { animalType = 'unicorn'; } else { animalType = 'stork'; } } else if (killCount >= 16) { if (r < 0.01) { animalType = 'trex'; } else if (r < 0.10) { animalType = 'lion'; } else if (r < 0.20) { animalType = 'zebra'; } else if (r < 0.35) { animalType = 'bird'; // birds increased } else { // spiders dominate animalType = 'spider'; } } else if (killCount >= 15) { if (r < 0.01) { animalType = 'trex'; } else if (r < 0.10) { animalType = 'lion'; } else if (r < 0.20) { animalType = 'zebra'; } else if (r < 0.23) { animalType = 'bird'; } else { // spiders dominate animalType = 'spider'; } } else if (killCount >= 11) { if (r < 0.01) { // more trex animalType = 'trex'; } else if (r < 0.18) { animalType = 'lion'; } else if (r < 0.38) { animalType = 'zebra'; } else if (r < 0.48) { animalType = 'bird'; } else { // even more spiders animalType = 'spider'; } } else if (killCount >= 5) { // More spiders when killCount >= 5 if (r < 0.005) { animalType = 'trex'; } else if (r < 0.13) { animalType = 'lion'; } else if (r < 0.33) { animalType = 'zebra'; } else if (r < 0.60) { animalType = 'bird'; } else { // more spiders animalType = 'spider'; } } else { if (r < 0.005) { animalType = 'trex'; } else if (r < 0.13) { animalType = 'lion'; } else if (r < 0.33) { animalType = 'zebra'; } else if (r < 0.70) { animalType = 'bird'; } else { animalType = 'spider'; } } var animal = new Animal(); animal.init(animalType); game.addChild(animal); animals.push(animal); } // Helper: update UI function updateUI() { moneyTxt.setText('$' + money); caughtTxt.setText('Bag: ' + caughtAnimals.length); killTxt.setText('Kills: ' + Math.floor(killCount)); gunTxt.setText('Gun: ' + gunNames[gunLevel]); if (gunLevel < 3) { upgradeBtn.setText('Upgrade ($' + gunPrices[gunLevel + 1] + ')'); upgradeBtn.alpha = money >= gunPrices[gunLevel + 1] ? 1 : 0.5; } else { upgradeBtn.setText('Maxed'); upgradeBtn.alpha = 0.5; } // Update Buy Turret button UI if (typeof buyTurretBtn !== "undefined") { if (hasTurret) { buyTurretBtn.setText('Turret Owned'); buyTurretBtn.alpha = 0.5; } else { buyTurretBtn.setText('Buy Turret ($1500)'); buyTurretBtn.alpha = money >= 1500 ? 1 : 0.5; } } // Friend button UI removed // Reset animalsSpedUp if game is reset (killCount is 0) if (killCount < 8) { game.animalsSpedUp = false; } // Reset animalsSuperSpedUp if game is reset (killCount is 0) if (killCount < 11) { game.animalsSuperSpedUp = false; } } // Helper: sell animals function sellAnimals() { if (caughtAnimals.length === 0) return; var total = 0; for (var i = 0; i < caughtAnimals.length; i++) { total += caughtAnimals[i].getSellValue(); } money += total; caughtAnimals = []; LK.getSound('sell').play(); updateUI(); } // Helper: upgrade gun function upgradeGun() { if (gunLevel >= 3) return; var price = gunPrices[gunLevel + 1]; if (money < price) return; money -= price; gunLevel++; gun.destroy(); gun = new Gun(); gun.init(gunTypes[gunLevel]); game.addChild(gun); gun.x = 2048 / 2; gun.y = 2732 / 2; // Hat logic removed (Friend button gone) LK.getSound('upgrade').play(); updateUI(); } // UI events upgradeBtn.down = function (x, y, obj) { upgradeGun(); }; sellBtn.down = function (x, y, obj) { LK.getSound('sell').play(); sellAnimals(); }; // Buy Turret button event buyTurretBtn.down = function (x, y, obj) { if (hasTurret) return; if (money < 1500) return; money -= 1500; hasTurret = true; // Spawn turret next to player (right side) playerTurret = new Turret(); playerTurret.x = gun.x + gun.asset.width * 1.2 + 80; playerTurret.y = gun.y; game.addChild(playerTurret); updateUI(); // Update button state buyTurretBtn.setText('Turret Owned'); buyTurretBtn.alpha = 0.5; }; // Touch to shoot game.down = function (x, y, obj) { // Don't shoot if touch is on GUI (bottom 300px) if (y > 2732 - 300) return; if (!gun.canShoot()) return; var bullet = new Bullet(); bullet.init(gunTypes[gunLevel]); bullet.x = gun.x + gun.asset.width * 0.9; bullet.y = gun.y; game.addChild(bullet); bullets.push(bullet); gun.shoot(); // Animate gun recoil tween(gun, { x: gun.x - 30 }, { duration: 60, easing: tween.cubicOut, onFinish: function onFinish() { tween(gun, { x: 300 }, { duration: 80, easing: tween.cubicIn }); } }); }; // Gun is fixed in the center; no dragging needed game.move = function (x, y, obj) { // No dragging logic }; // Shoot from the center gun position game.down = function (x, y, obj) { // Don't shoot if touch is on GUI (bottom 300px) if (y > 2732 - 300) return; if (!gun.canShoot()) return; if (gunTypes[gunLevel] === 'blaster') { // Fire 3 bullets in a spread var gunMuzzleX = gun.x + gun.asset.width * 0.9; var gunMuzzleY = gun.y; var dx = x - gunMuzzleX; var dy = y - gunMuzzleY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist === 0) dist = 1; var baseAngle = Math.atan2(dy, dx); var spread = Math.PI / 16; // ~11.25 degrees for (var i = -1; i <= 1; i++) { var bullet = new Bullet(); bullet.init('blaster'); bullet.x = gunMuzzleX; bullet.y = gunMuzzleY; var angle = baseAngle + i * spread; bullet.dirX = Math.cos(angle); bullet.dirY = Math.sin(angle); bullet.rotation = angle; game.addChild(bullet); bullets.push(bullet); } gun.shoot(); LK.getSound('shoot').play(); } else { var bullet = new Bullet(); bullet.init(gunTypes[gunLevel]); // Always shoot from the center gun position var gunMuzzleX = gun.x + gun.asset.width * 0.9; var gunMuzzleY = gun.y; bullet.x = gunMuzzleX; bullet.y = gunMuzzleY; var dx = x - gunMuzzleX; var dy = y - gunMuzzleY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist === 0) dist = 1; // prevent division by zero bullet.dirX = dx / dist; bullet.dirY = dy / dist; bullet.rotation = Math.atan2(dy, dx); game.addChild(bullet); bullets.push(bullet); gun.shoot(); LK.getSound('shoot').play(); } // Animate gun recoil tween(gun, { x: gun.x - 30 }, { duration: 60, easing: tween.cubicOut, onFinish: function onFinish() { tween(gun, { x: 2048 / 2 }, { duration: 80, easing: tween.cubicIn }); } }); }; game.up = function (x, y, obj) { // No dragging logic }; // Main update loop game.update = function () { // Spawn animals if (LK.ticks % 45 === 0 && animals.length < 7) { spawnAnimal(); } // Update animals for (var i = animals.length - 1; i >= 0; i--) { animals[i].update(); } // Update bullets for (var j = bullets.length - 1; j >= 0; j--) { bullets[j].update(); } // Bullet-animal collision for (var b = bullets.length - 1; b >= 0; b--) { var bullet = bullets[b]; for (var a = animals.length - 1; a >= 0; a--) { var animal = animals[a]; if (animal.caught) continue; if (bullet.intersects(animal)) { animal.caught = true; caughtAnimals.push(animal); // Increment killCount based on animal type: bird/spider = 0.5, zebra = 1, lion = 2, unicorn = 4, trex = 3.5, else 0.07 if (animal.animalType === 'bird' || animal.animalType === 'spider') { killCount += 0.5; } else if (animal.animalType === 'zebra') { killCount += 1; } else if (animal.animalType === 'lion') { killCount += 2; } else if (animal.animalType === 'unicorn') { killCount += 4; } else if (animal.animalType === 'trex') { killCount += 3.5; } else { killCount += 0.07; } // (tree spawn at killCount 4 removed) // Speed up all animals when kill counter passes 7 (only once, and make them very fast) if (!game.animalsSpedUp && killCount >= 7) { for (var ai = 0; ai < animals.length; ai++) { if (!animals[ai].caught) { animals[ai].speed *= 2.5; } } game.animalsSpedUp = true; } // Make all animals much faster and more difficult when killCount >= 11 (only once) if (!game.animalsSuperSpedUp && killCount >= 11) { for (var ai = 0; ai < animals.length; ai++) { if (!animals[ai].caught) { animals[ai].speed *= 1.5; } } game.animalsSuperSpedUp = true; } tween(animal, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { animal.destroy(); var idx = animals.indexOf(animal); if (idx !== -1) animals.splice(idx, 1); } }); bullet.destroy(); bullets.splice(b, 1); break; } } } // Turret spawn logic turretSpawnTicks++; if (turretSpawnTicks >= turretSpawnInterval) { if (Math.random() < 0.25) { spawnTurret(); } turretSpawnTicks = 0; } // Update turrets for (var i = turrets.length - 1; i >= 0; i--) { var turret = turrets[i]; if (typeof turret.update === "function") { turret.update(); } // Turret stay/leave logic if (typeof turret.ticksAlive === "number") { turret.ticksAlive++; if (turret.ticksAlive >= turretStayDuration) { // Remove turret from game and array turret.destroy(); turrets.splice(i, 1); } } } // Remove all spiders and birds from the game when killCount >= 34 (only once) if (!game.spidersAndBirdsGone && killCount >= 34) { for (var i = animals.length - 1; i >= 0; i--) { var a = animals[i]; if ((a.animalType === 'spider' || a.animalType === 'bird') && !a.caught) { a.destroy(); animals.splice(i, 1); } } game.spidersAndBirdsGone = true; } // (tree spawn logic after killCount >= 23 removed) updateUI(); }; // Play music LK.playMusic('forest_theme', { fade: { start: 0, end: 1, duration: 1200 } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Animal base class
var Animal = Container.expand(function () {
var self = Container.call(this);
self.type = 'animal';
self.value = 0;
self.speed = 0;
self.caught = false;
self.init = function (animalType) {
self.animalType = animalType;
var assetId;
if (animalType === 'trex') {
assetId = 'trex';
self.value = 146;
self.speed = 2.2 + Math.random() * 0.8;
} else if (animalType === 'lion') {
assetId = 'lion';
self.value = 55;
self.speed = 3.2 + Math.random() * 1.2;
} else if (animalType === 'zebra') {
assetId = 'zebra';
self.value = 35;
self.speed = 3.8 + Math.random() * 1.5;
} else if (animalType === 'bird') {
assetId = 'bird';
self.value = 15;
self.speed = 5.5 + Math.random() * 2.5;
} else if (animalType === 'spider') {
assetId = 'spider';
self.value = 10;
self.speed = 2.2 + Math.random() * 1.2;
} else if (animalType === 'stork') {
assetId = 'bird';
self.value = 100;
self.speed = 4.5 + Math.random() * 1.5;
// Tint the stork to make it visually distinct
// (LK.getAsset does not support dynamic tint, so we use the same asset for now)
} else if (animalType === 'unicorn') {
assetId = 'unicorn';
self.value = 126;
self.speed = 3.5 + Math.random() * 1.2;
}
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = Math.random() < 0.5 ? 1 : -1;
if (animalType === 'lion') {
// Let lions roam farther away from the player (avoid center)
// Top or bottom 1/3 of the screen
if (Math.random() < 0.5) {
self.y = 500 + Math.random() * 400; // Top band
} else {
self.y = 1900 + Math.random() * 300; // Bottom band
}
} else {
self.y = 500 + Math.random() * 1700;
}
if (self.direction === 1) {
self.x = -self.asset.width / 2;
} else {
self.x = 2048 + self.asset.width / 2;
self.asset.scaleX = -1;
}
};
self.update = function () {
if (self.caught) return;
self.x += self.speed * self.direction;
// Remove if off screen
if (self.direction === 1 && self.x > 2048 + self.asset.width / 2 || self.direction === -1 && self.x < -self.asset.width / 2) {
self.destroy();
var idx = animals.indexOf(self);
if (idx !== -1) animals.splice(idx, 1);
}
};
self.getSellValue = function () {
return self.value;
};
return self;
});
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.speed = 0;
self.range = 0;
self.gunType = 'basic';
self.init = function (gunType) {
self.gunType = gunType;
var assetId;
if (gunType === 'basic') {
assetId = 'bullet_basic';
self.speed = 28;
self.range = 1200;
} else if (gunType === 'rapid') {
assetId = 'bullet_rapid';
self.speed = 36;
self.range = 900;
} else if (gunType === 'sniper') {
assetId = 'bullet_sniper';
self.speed = 44;
self.range = 1800;
} else if (gunType === 'blaster') {
assetId = 'bullet_sniper';
self.speed = 60;
self.range = 2200;
}
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.distance = 0;
};
self.update = function () {
if (typeof self.dirX === "number" && typeof self.dirY === "number") {
self.x += self.speed * self.dirX;
self.y += self.speed * self.dirY;
self.distance += self.speed;
} else {
self.x += self.speed;
self.distance += self.speed;
}
if (self.distance > self.range || self.x < -100 || self.x > 2200 || self.y < -100 || self.y > 2832) {
self.destroy();
var idx = bullets.indexOf(self);
if (idx !== -1) bullets.splice(idx, 1);
}
};
return self;
});
// Gun class
var Gun = Container.expand(function () {
var self = Container.call(this);
self.gunType = 'basic';
self.reloadTime = 0;
self.lastShotTick = 0;
self.init = function (gunType) {
self.gunType = gunType;
var assetId;
if (gunType === 'basic') {
assetId = 'gun_basic';
self.reloadTime = 30;
} else if (gunType === 'rapid') {
assetId = 'gun_rapid';
self.reloadTime = 12;
} else if (gunType === 'sniper') {
assetId = 'gun_sniper';
self.reloadTime = 60;
} else if (gunType === 'blaster') {
assetId = 'gun_sniper';
self.reloadTime = 18;
}
self.asset = self.attachAsset(assetId, {
anchorX: 0.1,
anchorY: 0.5
});
};
self.canShoot = function () {
return LK.ticks - self.lastShotTick >= self.reloadTime;
};
self.shoot = function () {
self.lastShotTick = LK.ticks;
};
return self;
});
// Turret class
var Turret = Container.expand(function () {
var self = Container.call(this);
self.asset = self.attachAsset('turret', {
anchorX: 0.5,
anchorY: 0.5
});
self.fireCooldown = 0;
self.update = function () {
// Find nearest animal within 700px
var closest = null;
var minDist = 99999;
for (var i = 0; i < animals.length; i++) {
var a = animals[i];
if (a.caught) continue;
var dx = a.x - self.x;
var dy = a.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 700 && dist < minDist) {
minDist = dist;
closest = a;
}
}
// Fire at nearest animal every 18 ticks (~3.3 shots/sec)
if (closest && self.fireCooldown <= 0) {
var bullet = new Bullet();
bullet.init('rapid');
bullet.x = self.x + self.asset.width * 0.5;
bullet.y = self.y;
var dx = closest.x - bullet.x;
var dy = closest.y - bullet.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) dist = 1;
bullet.dirX = dx / dist;
bullet.dirY = dy / dist;
bullet.rotation = Math.atan2(dy, dx);
game.addChild(bullet);
bullets.push(bullet);
LK.getSound('shoot').play();
self.fireCooldown = 18;
}
if (self.fireCooldown > 0) self.fireCooldown--;
};
return self;
});
/****
* Initialize Game
****/
// Helper: spawn animal
var game = new LK.Game({
backgroundColor: 0x2e5d2c
});
/****
* Game Code
****/
// Turret asset
// Music
// Sounds
// Bullets
// Guns
// Animals
// Game state variables
var animals = [];
var bullets = [];
var caughtAnimals = [];
var money = 0;
var killCount = 0; // Track total kills
var gunLevel = 0; // 0: basic, 1: rapid, 2: sniper, 3: blaster
var gunTypes = ['basic', 'rapid', 'sniper', 'blaster'];
var gunPrices = [0, 350, 600, 1500];
var gunNames = ['Basic Gun', 'Rapid Gun', 'Sniper Gun', 'Blaster'];
var gun;
var animalsSpedUp = false; // Track if animals have been sped up
// Tree spawn timer variables
var treeSpawnTimer = 0;
var treeSpawnInterval = 300; // 5 seconds at 60 FPS
// UI
var moneyTxt = new Text2('$0', {
size: 90,
fill: 0xFFF700
});
moneyTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(moneyTxt);
var caughtTxt = new Text2('Bag: 0', {
size: 70,
fill: 0xFFFFFF
});
caughtTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(caughtTxt);
caughtTxt.y = 110;
var killTxt = new Text2('Kills: 0', {
size: 70,
fill: 0xFF4444
});
killTxt.anchor.set(0, 1); // anchor bottom left
LK.gui.bottomLeft.addChild(killTxt);
killTxt.x = 0;
killTxt.y = 0;
var gunTxt = new Text2('Gun: Basic', {
size: 60,
fill: 0xFFFFFF
});
gunTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(gunTxt);
gunTxt.y = 200;
var sellBtn = new Text2('Sell', {
size: 70,
fill: 0xFF8800
});
sellBtn.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(sellBtn);
sellBtn.y = -200;
var upgradeBtn = new Text2('Upgrade', {
size: 70,
fill: 0x00FF00
});
upgradeBtn.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(upgradeBtn);
upgradeBtn.y = -120;
// --- Buy Turret Button ---
var buyTurretBtn = new Text2('Buy Turret ($1500)', {
size: 70,
fill: 0x00BFFF
});
buyTurretBtn.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(buyTurretBtn);
buyTurretBtn.y = -40;
// Track if player owns a turret
var hasTurret = false;
var playerTurret = null;
// Gun
gun = new Gun();
gun.init(gunTypes[gunLevel]);
game.addChild(gun);
gun.x = 2048 / 2;
gun.y = 2732 / 2;
// Friend button removed
// Track if skin is bought
var skinBought = false;
// Turret spawn timer variables
var turretSpawnInterval = 660; // 11 seconds at 60 FPS
var turretSpawnTicks = 0;
var turrets = [];
var turretStayDuration = 300; // 5 seconds at 60 FPS
function spawnTurret() {
var turret = new Turret();
// Place turrets in a circle around the gun, up to 6 turrets
var turretCount = turrets.length;
var angle = turretCount % 6 * (Math.PI * 2 / 6);
var radius = 500;
turret.x = gun.x + Math.cos(angle) * radius;
turret.y = gun.y + Math.sin(angle) * radius;
game.addChild(turret);
// Add a timer property to track how long the turret has been alive
turret.ticksAlive = 0;
turrets.push(turret);
// Reset turret spawn timer
turretSpawnTicks = 0;
}
// Helper: spawn animal
function spawnAnimal() {
// Very rarely, spawn a unicorn
if (Math.random() < 0.0015) {
var unicorn = new Animal();
unicorn.init('unicorn');
game.addChild(unicorn);
animals.push(unicorn);
return;
}
// Very rarely, spawn a stork
if (Math.random() < 0.003) {
var stork = new Animal();
stork.init('stork');
game.addChild(stork);
animals.push(stork);
return;
}
var r = Math.random();
var animalType;
// After killCount >= 34, do not spawn spiders or birds
if (killCount >= 34) {
// Only spawn trex, lion, zebra, unicorn, stork
if (r < 0.01) {
animalType = 'trex';
} else if (r < 0.10) {
animalType = 'lion';
} else if (r < 0.20) {
animalType = 'zebra';
} else if (r < 0.21) {
animalType = 'unicorn';
} else {
animalType = 'stork';
}
} else if (killCount >= 16) {
if (r < 0.01) {
animalType = 'trex';
} else if (r < 0.10) {
animalType = 'lion';
} else if (r < 0.20) {
animalType = 'zebra';
} else if (r < 0.35) {
animalType = 'bird'; // birds increased
} else {
// spiders dominate
animalType = 'spider';
}
} else if (killCount >= 15) {
if (r < 0.01) {
animalType = 'trex';
} else if (r < 0.10) {
animalType = 'lion';
} else if (r < 0.20) {
animalType = 'zebra';
} else if (r < 0.23) {
animalType = 'bird';
} else {
// spiders dominate
animalType = 'spider';
}
} else if (killCount >= 11) {
if (r < 0.01) {
// more trex
animalType = 'trex';
} else if (r < 0.18) {
animalType = 'lion';
} else if (r < 0.38) {
animalType = 'zebra';
} else if (r < 0.48) {
animalType = 'bird';
} else {
// even more spiders
animalType = 'spider';
}
} else if (killCount >= 5) {
// More spiders when killCount >= 5
if (r < 0.005) {
animalType = 'trex';
} else if (r < 0.13) {
animalType = 'lion';
} else if (r < 0.33) {
animalType = 'zebra';
} else if (r < 0.60) {
animalType = 'bird';
} else {
// more spiders
animalType = 'spider';
}
} else {
if (r < 0.005) {
animalType = 'trex';
} else if (r < 0.13) {
animalType = 'lion';
} else if (r < 0.33) {
animalType = 'zebra';
} else if (r < 0.70) {
animalType = 'bird';
} else {
animalType = 'spider';
}
}
var animal = new Animal();
animal.init(animalType);
game.addChild(animal);
animals.push(animal);
}
// Helper: update UI
function updateUI() {
moneyTxt.setText('$' + money);
caughtTxt.setText('Bag: ' + caughtAnimals.length);
killTxt.setText('Kills: ' + Math.floor(killCount));
gunTxt.setText('Gun: ' + gunNames[gunLevel]);
if (gunLevel < 3) {
upgradeBtn.setText('Upgrade ($' + gunPrices[gunLevel + 1] + ')');
upgradeBtn.alpha = money >= gunPrices[gunLevel + 1] ? 1 : 0.5;
} else {
upgradeBtn.setText('Maxed');
upgradeBtn.alpha = 0.5;
}
// Update Buy Turret button UI
if (typeof buyTurretBtn !== "undefined") {
if (hasTurret) {
buyTurretBtn.setText('Turret Owned');
buyTurretBtn.alpha = 0.5;
} else {
buyTurretBtn.setText('Buy Turret ($1500)');
buyTurretBtn.alpha = money >= 1500 ? 1 : 0.5;
}
}
// Friend button UI removed
// Reset animalsSpedUp if game is reset (killCount is 0)
if (killCount < 8) {
game.animalsSpedUp = false;
}
// Reset animalsSuperSpedUp if game is reset (killCount is 0)
if (killCount < 11) {
game.animalsSuperSpedUp = false;
}
}
// Helper: sell animals
function sellAnimals() {
if (caughtAnimals.length === 0) return;
var total = 0;
for (var i = 0; i < caughtAnimals.length; i++) {
total += caughtAnimals[i].getSellValue();
}
money += total;
caughtAnimals = [];
LK.getSound('sell').play();
updateUI();
}
// Helper: upgrade gun
function upgradeGun() {
if (gunLevel >= 3) return;
var price = gunPrices[gunLevel + 1];
if (money < price) return;
money -= price;
gunLevel++;
gun.destroy();
gun = new Gun();
gun.init(gunTypes[gunLevel]);
game.addChild(gun);
gun.x = 2048 / 2;
gun.y = 2732 / 2;
// Hat logic removed (Friend button gone)
LK.getSound('upgrade').play();
updateUI();
}
// UI events
upgradeBtn.down = function (x, y, obj) {
upgradeGun();
};
sellBtn.down = function (x, y, obj) {
LK.getSound('sell').play();
sellAnimals();
};
// Buy Turret button event
buyTurretBtn.down = function (x, y, obj) {
if (hasTurret) return;
if (money < 1500) return;
money -= 1500;
hasTurret = true;
// Spawn turret next to player (right side)
playerTurret = new Turret();
playerTurret.x = gun.x + gun.asset.width * 1.2 + 80;
playerTurret.y = gun.y;
game.addChild(playerTurret);
updateUI();
// Update button state
buyTurretBtn.setText('Turret Owned');
buyTurretBtn.alpha = 0.5;
};
// Touch to shoot
game.down = function (x, y, obj) {
// Don't shoot if touch is on GUI (bottom 300px)
if (y > 2732 - 300) return;
if (!gun.canShoot()) return;
var bullet = new Bullet();
bullet.init(gunTypes[gunLevel]);
bullet.x = gun.x + gun.asset.width * 0.9;
bullet.y = gun.y;
game.addChild(bullet);
bullets.push(bullet);
gun.shoot();
// Animate gun recoil
tween(gun, {
x: gun.x - 30
}, {
duration: 60,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(gun, {
x: 300
}, {
duration: 80,
easing: tween.cubicIn
});
}
});
};
// Gun is fixed in the center; no dragging needed
game.move = function (x, y, obj) {
// No dragging logic
};
// Shoot from the center gun position
game.down = function (x, y, obj) {
// Don't shoot if touch is on GUI (bottom 300px)
if (y > 2732 - 300) return;
if (!gun.canShoot()) return;
if (gunTypes[gunLevel] === 'blaster') {
// Fire 3 bullets in a spread
var gunMuzzleX = gun.x + gun.asset.width * 0.9;
var gunMuzzleY = gun.y;
var dx = x - gunMuzzleX;
var dy = y - gunMuzzleY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) dist = 1;
var baseAngle = Math.atan2(dy, dx);
var spread = Math.PI / 16; // ~11.25 degrees
for (var i = -1; i <= 1; i++) {
var bullet = new Bullet();
bullet.init('blaster');
bullet.x = gunMuzzleX;
bullet.y = gunMuzzleY;
var angle = baseAngle + i * spread;
bullet.dirX = Math.cos(angle);
bullet.dirY = Math.sin(angle);
bullet.rotation = angle;
game.addChild(bullet);
bullets.push(bullet);
}
gun.shoot();
LK.getSound('shoot').play();
} else {
var bullet = new Bullet();
bullet.init(gunTypes[gunLevel]);
// Always shoot from the center gun position
var gunMuzzleX = gun.x + gun.asset.width * 0.9;
var gunMuzzleY = gun.y;
bullet.x = gunMuzzleX;
bullet.y = gunMuzzleY;
var dx = x - gunMuzzleX;
var dy = y - gunMuzzleY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) dist = 1; // prevent division by zero
bullet.dirX = dx / dist;
bullet.dirY = dy / dist;
bullet.rotation = Math.atan2(dy, dx);
game.addChild(bullet);
bullets.push(bullet);
gun.shoot();
LK.getSound('shoot').play();
}
// Animate gun recoil
tween(gun, {
x: gun.x - 30
}, {
duration: 60,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(gun, {
x: 2048 / 2
}, {
duration: 80,
easing: tween.cubicIn
});
}
});
};
game.up = function (x, y, obj) {
// No dragging logic
};
// Main update loop
game.update = function () {
// Spawn animals
if (LK.ticks % 45 === 0 && animals.length < 7) {
spawnAnimal();
}
// Update animals
for (var i = animals.length - 1; i >= 0; i--) {
animals[i].update();
}
// Update bullets
for (var j = bullets.length - 1; j >= 0; j--) {
bullets[j].update();
}
// Bullet-animal collision
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
for (var a = animals.length - 1; a >= 0; a--) {
var animal = animals[a];
if (animal.caught) continue;
if (bullet.intersects(animal)) {
animal.caught = true;
caughtAnimals.push(animal);
// Increment killCount based on animal type: bird/spider = 0.5, zebra = 1, lion = 2, unicorn = 4, trex = 3.5, else 0.07
if (animal.animalType === 'bird' || animal.animalType === 'spider') {
killCount += 0.5;
} else if (animal.animalType === 'zebra') {
killCount += 1;
} else if (animal.animalType === 'lion') {
killCount += 2;
} else if (animal.animalType === 'unicorn') {
killCount += 4;
} else if (animal.animalType === 'trex') {
killCount += 3.5;
} else {
killCount += 0.07;
}
// (tree spawn at killCount 4 removed)
// Speed up all animals when kill counter passes 7 (only once, and make them very fast)
if (!game.animalsSpedUp && killCount >= 7) {
for (var ai = 0; ai < animals.length; ai++) {
if (!animals[ai].caught) {
animals[ai].speed *= 2.5;
}
}
game.animalsSpedUp = true;
}
// Make all animals much faster and more difficult when killCount >= 11 (only once)
if (!game.animalsSuperSpedUp && killCount >= 11) {
for (var ai = 0; ai < animals.length; ai++) {
if (!animals[ai].caught) {
animals[ai].speed *= 1.5;
}
}
game.animalsSuperSpedUp = true;
}
tween(animal, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
animal.destroy();
var idx = animals.indexOf(animal);
if (idx !== -1) animals.splice(idx, 1);
}
});
bullet.destroy();
bullets.splice(b, 1);
break;
}
}
}
// Turret spawn logic
turretSpawnTicks++;
if (turretSpawnTicks >= turretSpawnInterval) {
if (Math.random() < 0.25) {
spawnTurret();
}
turretSpawnTicks = 0;
}
// Update turrets
for (var i = turrets.length - 1; i >= 0; i--) {
var turret = turrets[i];
if (typeof turret.update === "function") {
turret.update();
}
// Turret stay/leave logic
if (typeof turret.ticksAlive === "number") {
turret.ticksAlive++;
if (turret.ticksAlive >= turretStayDuration) {
// Remove turret from game and array
turret.destroy();
turrets.splice(i, 1);
}
}
}
// Remove all spiders and birds from the game when killCount >= 34 (only once)
if (!game.spidersAndBirdsGone && killCount >= 34) {
for (var i = animals.length - 1; i >= 0; i--) {
var a = animals[i];
if ((a.animalType === 'spider' || a.animalType === 'bird') && !a.caught) {
a.destroy();
animals.splice(i, 1);
}
}
game.spidersAndBirdsGone = true;
}
// (tree spawn logic after killCount >= 23 removed)
updateUI();
};
// Play music
LK.playMusic('forest_theme', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
Spider pixel. In-Game asset. 2d. High contrast. No shadows
Lion pixel. In-Game asset. 2d. High contrast. No shadows
Zebra pixel. In-Game asset. 2d. High contrast. No shadows
Trex pixel. In-Game asset. 2d. High contrast. No shadows
Bird pixel. In-Game asset. 2d. High contrast. No shadows
person with glock18 in hand pixel. In-Game asset. 2d. High contrast. No shadows
man with sniper
Person with m4a1 in hand
Bullet pixel. In-Game asset. 2d. High contrast. No shadows
Turret pixel. In-Game asset. 2d. High contrast. No shadows
Unicorn pixel. In-Game asset. 2d. High contrast. No shadows
Tree pixel. In-Game asset. 2d. High contrast. No shadows
man with laser gun