/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ArmedScientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('scientist', {
anchorX: 0.5,
anchorY: 0.5
});
scientistGraphics.tint = 0xFF0000; // Red tint to distinguish armed scientists
self.speed = 2.5;
self.health = 7;
self.points = 4;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
// Mark as exploding to prevent multiple explosions
if (self.exploding) return true;
self.exploding = true;
// Check for ALL scientists to kill BEFORE starting animation
for (var i = scientists.length - 1; i >= 0; i--) {
var otherScientist = scientists[i];
if (otherScientist !== self && !otherScientist.exploding) {
// Kill ALL scientists on screen regardless of distance
if (otherScientist.constructor === Scientist || otherScientist.constructor === FastScientist || otherScientist.constructor === SteelBallScientist) {
LK.setScore(LK.getScore() + otherScientist.points);
updateScore();
spawnLoot(otherScientist.x, otherScientist.y);
scientistResidues++;
updateResidue();
// Track normal scientist deaths
if (otherScientist.constructor === Scientist) {
normalScientistDeaths++;
} else if (otherScientist.constructor === FastScientist) {
fastScientistDeaths++;
}
otherScientist.destroy();
scientists.splice(i, 1);
LK.getSound('hit').play();
}
}
}
// Check if dog is in explosion range
var dogDx = dog.x - self.x;
var dogDy = dog.y - self.y;
var dogDistance = Math.sqrt(dogDx * dogDx + dogDy * dogDy);
if (dogDistance <= explosionRange) {
// Reduce score by 20 points for being caught in explosion
LK.setScore(Math.max(0, LK.getScore() - 20));
updateScore();
// Kill the dog when caught in explosion
dog.health = 0;
LK.showGameOver();
}
// Give 50 score for detonating armed scientist
LK.setScore(LK.getScore() + 50);
updateScore();
// Create explosion animation
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return true;
}
return false;
};
return self;
});
var Chest = Container.expand(function () {
var self = Container.call(this);
var chestGraphics = self.attachAsset('chest', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'chest';
self.value = 20;
self.update = function () {
self.rotation += 0.03;
};
return self;
});
var DirectionalButton = Container.expand(function (direction) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('dirButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = direction;
self.alpha = 0.7;
// Create arrow text based on direction
var arrowText = new Text2('', {
size: 90,
fill: 0xFFFFFF
});
arrowText.anchor.set(0.5, 0.5);
switch (direction) {
case 'up':
arrowText.setText('↑');
break;
case 'down':
arrowText.setText('↓');
break;
case 'left':
arrowText.setText('←');
break;
case 'right':
arrowText.setText('→');
break;
}
self.addChild(arrowText);
self.down = function (x, y, obj) {
currentShootDirection = self.direction;
self.alpha = 1.0;
// Reset other buttons
for (var i = 0; i < dirButtons.length; i++) {
if (dirButtons[i] !== self) {
dirButtons[i].alpha = 0.7;
}
}
// Fire bullet immediately when button is pressed
dog.shoot();
};
return self;
});
var Dog = Container.expand(function () {
var self = Container.call(this);
var dogGraphics = self.attachAsset('dog', {
anchorX: 0.5,
anchorY: 0.5
});
// Add gun icon
var gunIcon = self.attachAsset('dogBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: 60,
y: 0
});
gunIcon.tint = 0x888888; // Gray tint for gun icon
self.health = 3;
self.maxHealth = 3;
self.shootCooldown = 0;
self.shootRate = 20;
self.speed = 5;
self.powerUpActive = false;
self.powerUpEndTime = 0;
self.weaponType = 'knife';
self.weaponLevel = 1;
self.gold = 0;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
if (self.powerUpActive && LK.now > self.powerUpEndTime) {
self.powerUpActive = false;
self.speed = 5;
self.shootRate = 20;
}
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
var bullet = new DogBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.weaponType = self.weaponType;
bullet.weaponLevel = self.weaponLevel;
// Set direction based on current shoot direction
switch (currentShootDirection) {
case 'up':
bullet.dirX = 0;
bullet.dirY = -1;
bullet.y -= 60;
break;
case 'down':
bullet.dirX = 0;
bullet.dirY = 1;
bullet.y += 60;
break;
case 'left':
bullet.dirX = -1;
bullet.dirY = 0;
bullet.x -= 60;
break;
case 'right':
bullet.dirX = 1;
bullet.dirY = 0;
bullet.x += 60;
break;
}
bullets.push(bullet);
game.addChild(bullet);
self.shootCooldown = self.shootRate;
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
self.health--;
LK.effects.flashObject(self, 0xFF0000, 500);
if (self.health <= 0) {
LK.showGameOver();
}
};
self.activatePowerUp = function () {
self.powerUpActive = true;
self.powerUpEndTime = LK.now + 5000;
self.speed = 8;
self.shootRate = 11;
};
self.upgradeWeapon = function () {
if (self.weaponLevel < 3) {
self.weaponLevel++;
if (self.weaponLevel === 2 && (scientistResidues >= 1000 || LK.getScore() >= 2000)) {
self.weaponType = 'laser';
self.shootRate = 13;
} else if (self.weaponLevel === 3) {
self.shootRate = 7;
}
}
};
return self;
});
var DogBullet = Container.expand(function () {
var self = Container.call(this);
self.speed = 8;
self.damage = 1;
self.dirX = 0;
self.dirY = -1;
self.weaponType = 'knife';
self.weaponLevel = 1;
var bulletGraphics;
self.update = function () {
// Update graphics based on weapon type if not set
if (!bulletGraphics) {
if (self.weaponType === 'laser') {
bulletGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 2;
} else {
bulletGraphics = self.attachAsset('knife', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Set rotation based on direction
if (self.dirX === 1) bulletGraphics.rotation = Math.PI / 2;else if (self.dirX === -1) bulletGraphics.rotation = -Math.PI / 2;else if (self.dirY === 1) bulletGraphics.rotation = Math.PI;
}
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
var FastScientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('fastScientist', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 7.0;
self.health = 10;
self.points = 5;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var Gold = Container.expand(function () {
var self = Container.call(this);
var goldGraphics = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'gold';
self.value = 10;
self.update = function () {
self.rotation += 0.06;
};
return self;
});
var Metal = Container.expand(function () {
var self = Container.call(this);
var metalGraphics = self.attachAsset('metal', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'metal';
self.value = 5;
self.update = function () {
self.rotation += 0.05;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'speed';
self.duration = 5000;
self.update = function () {
self.rotation += 0.1;
};
return self;
});
var Scientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('scientist', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 5;
self.points = 3;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var SteelBall = Container.expand(function () {
var self = Container.call(this);
var steelBallGraphics = self.attachAsset('dogBullet', {
anchorX: 0.5,
anchorY: 0.5
});
steelBallGraphics.tint = 0x808080; // Gray color for steel
self.speed = 4;
self.damage = 1;
self.dirX = 0;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
var SteelBallScientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('scientist', {
anchorX: 0.5,
anchorY: 0.5
});
scientistGraphics.tint = 0x4169E1; // Blue tint to distinguish steel ball scientists
self.speed = 2.5;
self.health = 8; // 8 hits with knife, 5 with laser (damage 2)
self.points = 6;
self.targetX = 0;
self.targetY = 0;
self.shootCooldown = 0;
self.shootRate = 60; // Shoot every 60 frames (1 second)
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Shooting logic
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
// Shoot at dog
var steelBall = new SteelBall();
steelBall.x = self.x;
steelBall.y = self.y;
// Calculate direction to dog
var shootDistance = Math.sqrt(dx * dx + dy * dy);
if (shootDistance > 0) {
steelBall.dirX = dx / shootDistance;
steelBall.dirY = dy / shootDistance;
}
steelBalls.push(steelBall);
game.addChild(steelBall);
self.shootCooldown = self.shootRate;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var Technology = Container.expand(function () {
var self = Container.call(this);
var technologyGraphics = self.attachAsset('technology', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'technology';
self.value = 50;
self.update = function () {
self.rotation += 0.08;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var dog = new Dog();
var bullets = [];
var scientists = [];
var powerUps = [];
var metals = [];
var chests = [];
var technologies = [];
var golds = [];
var dirButtons = [];
var steelBalls = [];
var currentShootDirection = 'up';
var spawnTimer = 0;
var waveTimer = 0;
var difficultyLevel = 1;
var lastSpawnRate = 120;
var scientistResidues = 0;
var scientistCount = 0;
var normalScientistHits = 0;
var fastScientistHits = 0;
var fastScientistSpawned = 0;
var normalScientistDeaths = 0;
var fastScientistDeaths = 0;
var explosionRange = 200; // Range for armed scientist explosions
// Add laboratory background
var labBackground = LK.getAsset('labBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(labBackground);
dog.x = 1024;
dog.y = 2200;
game.addChild(dog);
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var goldTxt = new Text2('Gold: 0', {
size: 60,
fill: 0xFFD700
});
goldTxt.anchor.set(0, 0);
goldTxt.x = 150;
goldTxt.y = 120;
LK.gui.topLeft.addChild(goldTxt);
var weaponTxt = new Text2('Weapon: Knife Lv.1', {
size: 50,
fill: 0xFFFFFF
});
weaponTxt.anchor.set(0, 0);
weaponTxt.x = 150;
weaponTxt.y = 190;
LK.gui.topLeft.addChild(weaponTxt);
var residueTxt = new Text2('Residues: 0/1000 (Laser: 1000 residues or 2000 score)', {
size: 45,
fill: 0x00FF00
});
residueTxt.anchor.set(0, 0);
residueTxt.x = 150;
residueTxt.y = 250;
LK.gui.topLeft.addChild(residueTxt);
// Create directional buttons in main game area with proper spacing
var upBtn = new DirectionalButton('up');
upBtn.x = 300;
upBtn.y = 2350;
game.addChild(upBtn);
dirButtons.push(upBtn);
var downBtn = new DirectionalButton('down');
downBtn.x = 300;
downBtn.y = 2650;
game.addChild(downBtn);
dirButtons.push(downBtn);
var leftBtn = new DirectionalButton('left');
leftBtn.x = 150;
leftBtn.y = 2500;
game.addChild(leftBtn);
dirButtons.push(leftBtn);
var rightBtn = new DirectionalButton('right');
rightBtn.x = 450;
rightBtn.y = 2500;
game.addChild(rightBtn);
dirButtons.push(rightBtn);
// Set initial button state
upBtn.alpha = 1.0;
var dragNode = null;
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
function updateGold() {
goldTxt.setText('Gold: ' + dog.gold);
}
function updateWeapon() {
var weaponName = dog.weaponType === 'knife' ? 'Knife' : 'Laser';
weaponTxt.setText('Weapon: ' + weaponName + ' Lv.' + dog.weaponLevel);
}
function updateResidue() {
// Give 20 score for each scientist residue collected
LK.setScore(LK.getScore() + 20);
updateScore();
var laserUnlocked = scientistResidues >= 1000 || LK.getScore() >= 2000;
if (laserUnlocked) {
residueTxt.setText('Residues: ' + scientistResidues + '/1000 (LASER UNLOCKED!)');
} else {
residueTxt.setText('Residues: ' + scientistResidues + '/1000 (Laser: 1000 residues or 2000 score)');
}
}
function spawnScientist() {
var scientist;
scientistCount++;
if (fastScientistDeaths >= 6 && fastScientistDeaths % 6 === 0) {
scientist = new ArmedScientist();
fastScientistDeaths++; // Increment to avoid spawning multiple in a row
} else if (scientistCount % 10 === 0) {
scientist = new FastScientist();
fastScientistSpawned++;
// Spawn SteelBallScientist after every 5 fast scientists
if (fastScientistSpawned % 5 === 0) {
scientist = new SteelBallScientist();
}
} else {
scientist = new Scientist();
}
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
scientist.x = Math.random() * 2048;
scientist.y = -40;
break;
case 1:
// Right
scientist.x = 2088;
scientist.y = Math.random() * 2732;
break;
case 2:
// Bottom
scientist.x = Math.random() * 2048;
scientist.y = 2772;
break;
case 3:
// Left
scientist.x = -40;
scientist.y = Math.random() * 2732;
break;
}
scientist.targetX = dog.x;
scientist.targetY = dog.y;
scientists.push(scientist);
game.addChild(scientist);
}
function spawnPowerUp() {
if (Math.random() < 0.02 && powerUps.length < 2) {
var powerUp = new PowerUp();
powerUp.x = Math.random() * 1800 + 124;
powerUp.y = Math.random() * 2400 + 166;
powerUps.push(powerUp);
game.addChild(powerUp);
}
}
function spawnLoot(x, y) {
var lootChance = Math.random();
var loot;
if (lootChance < 0.5) {
// 50% chance for metal
loot = new Metal();
metals.push(loot);
} else if (lootChance < 0.8) {
// 30% chance for chest
loot = new Chest();
chests.push(loot);
} else {
// 20% chance for technology
loot = new Technology();
technologies.push(loot);
}
loot.x = x;
loot.y = y;
game.addChild(loot);
}
function spawnGoldFromChest(x, y) {
// Spawn 2-3 gold pieces from chest
var goldCount = Math.floor(Math.random() * 2) + 2;
for (var i = 0; i < goldCount; i++) {
var gold = new Gold();
gold.x = x + (Math.random() - 0.5) * 60;
gold.y = y + (Math.random() - 0.5) * 60;
golds.push(gold);
game.addChild(gold);
}
}
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(60, Math.min(1988, x));
dragNode.y = Math.max(60, Math.min(2672, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = dog;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
spawnTimer++;
waveTimer++;
if (waveTimer % 1800 === 0) {
difficultyLevel++;
lastSpawnRate = Math.max(30, lastSpawnRate - 10);
}
if (spawnTimer >= lastSpawnRate) {
spawnScientist();
spawnTimer = 0;
}
spawnPowerUp();
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.y < -50 || bullet.y > 2782 || bullet.x < -50 || bullet.x > 2098) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
for (var j = scientists.length - 1; j >= 0; j--) {
var scientist = scientists[j];
if (bullet.intersects(scientist)) {
if (scientist.takeDamage(bullet.damage)) {
LK.setScore(LK.getScore() + scientist.points);
updateScore();
spawnLoot(scientist.x, scientist.y);
scientistResidues++;
updateResidue();
// Track normal scientist deaths
if (scientist.constructor === Scientist) {
normalScientistDeaths++;
} else if (scientist.constructor === FastScientist) {
fastScientistDeaths++;
}
scientist.destroy();
scientists.splice(j, 1);
LK.getSound('hit').play();
}
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
}
for (var k = scientists.length - 1; k >= 0; k--) {
var scientist = scientists[k];
if (!scientist) continue; // Skip if scientist is undefined
scientist.targetX = dog.x;
scientist.targetY = dog.y;
if (scientist.intersects(dog)) {
// Deduct half the score that the enemy would give when killed
var scoreDeduction = Math.floor(scientist.points / 2);
LK.setScore(Math.max(0, LK.getScore() - scoreDeduction));
updateScore();
// Check if it's an armed scientist (red) - trigger explosion
if (scientist.constructor === ArmedScientist) {
scientist.takeDamage(999); // Force explosion by dealing massive damage
scientists.splice(k, 1);
continue;
}
// Track hits by scientist type
if (scientist.constructor === FastScientist) {
fastScientistHits++;
} else if (scientist.constructor === Scientist) {
normalScientistHits++;
}
// Check death conditions
if (normalScientistHits >= 5 || fastScientistHits >= 3) {
LK.showGameOver();
}
scientist.destroy();
scientists.splice(k, 1);
continue;
}
var distanceToEdge = Math.min(scientist.x, 2048 - scientist.x, scientist.y, 2732 - scientist.y);
if (distanceToEdge < -100) {
scientist.destroy();
scientists.splice(k, 1);
}
}
for (var l = powerUps.length - 1; l >= 0; l--) {
var powerUp = powerUps[l];
if (powerUp.intersects(dog)) {
LK.setScore(LK.getScore() + 2);
updateScore();
dog.activatePowerUp();
LK.getSound('powerup').play();
powerUp.destroy();
powerUps.splice(l, 1);
}
}
// Check metal collection
for (var m = metals.length - 1; m >= 0; m--) {
var metal = metals[m];
if (metal.intersects(dog)) {
LK.setScore(LK.getScore() + metal.value);
updateScore();
metal.destroy();
metals.splice(m, 1);
}
}
// Check chest collection
for (var c = chests.length - 1; c >= 0; c--) {
var chest = chests[c];
if (chest.intersects(dog)) {
LK.setScore(LK.getScore() + chest.value);
updateScore();
// Spawn gold from chest
spawnGoldFromChest(chest.x, chest.y);
// Random chance for weapon upgrade
if (Math.random() < 0.3) {
dog.upgradeWeapon();
updateWeapon();
}
chest.destroy();
chests.splice(c, 1);
}
}
// Check technology collection
for (var t = technologies.length - 1; t >= 0; t--) {
var technology = technologies[t];
if (technology.intersects(dog)) {
LK.setScore(LK.getScore() + technology.value);
updateScore();
technology.destroy();
technologies.splice(t, 1);
}
}
// Check gold collection
for (var g = golds.length - 1; g >= 0; g--) {
var gold = golds[g];
if (gold.intersects(dog)) {
dog.gold += gold.value;
updateGold();
gold.destroy();
golds.splice(g, 1);
}
}
// Check steel ball collisions with dog
for (var s = steelBalls.length - 1; s >= 0; s--) {
var steelBall = steelBalls[s];
if (steelBall.y < -50 || steelBall.y > 2782 || steelBall.x < -50 || steelBall.x > 2098) {
steelBall.destroy();
steelBalls.splice(s, 1);
continue;
}
if (steelBall.intersects(dog)) {
dog.takeDamage();
steelBall.destroy();
steelBalls.splice(s, 1);
}
}
if (LK.ticks % 10 === 0 && dog.powerUpActive) {
dog.shoot();
}
};
LK.playMusic('bgmusic'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ArmedScientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('scientist', {
anchorX: 0.5,
anchorY: 0.5
});
scientistGraphics.tint = 0xFF0000; // Red tint to distinguish armed scientists
self.speed = 2.5;
self.health = 7;
self.points = 4;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
// Mark as exploding to prevent multiple explosions
if (self.exploding) return true;
self.exploding = true;
// Check for ALL scientists to kill BEFORE starting animation
for (var i = scientists.length - 1; i >= 0; i--) {
var otherScientist = scientists[i];
if (otherScientist !== self && !otherScientist.exploding) {
// Kill ALL scientists on screen regardless of distance
if (otherScientist.constructor === Scientist || otherScientist.constructor === FastScientist || otherScientist.constructor === SteelBallScientist) {
LK.setScore(LK.getScore() + otherScientist.points);
updateScore();
spawnLoot(otherScientist.x, otherScientist.y);
scientistResidues++;
updateResidue();
// Track normal scientist deaths
if (otherScientist.constructor === Scientist) {
normalScientistDeaths++;
} else if (otherScientist.constructor === FastScientist) {
fastScientistDeaths++;
}
otherScientist.destroy();
scientists.splice(i, 1);
LK.getSound('hit').play();
}
}
}
// Check if dog is in explosion range
var dogDx = dog.x - self.x;
var dogDy = dog.y - self.y;
var dogDistance = Math.sqrt(dogDx * dogDx + dogDy * dogDy);
if (dogDistance <= explosionRange) {
// Reduce score by 20 points for being caught in explosion
LK.setScore(Math.max(0, LK.getScore() - 20));
updateScore();
// Kill the dog when caught in explosion
dog.health = 0;
LK.showGameOver();
}
// Give 50 score for detonating armed scientist
LK.setScore(LK.getScore() + 50);
updateScore();
// Create explosion animation
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return true;
}
return false;
};
return self;
});
var Chest = Container.expand(function () {
var self = Container.call(this);
var chestGraphics = self.attachAsset('chest', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'chest';
self.value = 20;
self.update = function () {
self.rotation += 0.03;
};
return self;
});
var DirectionalButton = Container.expand(function (direction) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('dirButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = direction;
self.alpha = 0.7;
// Create arrow text based on direction
var arrowText = new Text2('', {
size: 90,
fill: 0xFFFFFF
});
arrowText.anchor.set(0.5, 0.5);
switch (direction) {
case 'up':
arrowText.setText('↑');
break;
case 'down':
arrowText.setText('↓');
break;
case 'left':
arrowText.setText('←');
break;
case 'right':
arrowText.setText('→');
break;
}
self.addChild(arrowText);
self.down = function (x, y, obj) {
currentShootDirection = self.direction;
self.alpha = 1.0;
// Reset other buttons
for (var i = 0; i < dirButtons.length; i++) {
if (dirButtons[i] !== self) {
dirButtons[i].alpha = 0.7;
}
}
// Fire bullet immediately when button is pressed
dog.shoot();
};
return self;
});
var Dog = Container.expand(function () {
var self = Container.call(this);
var dogGraphics = self.attachAsset('dog', {
anchorX: 0.5,
anchorY: 0.5
});
// Add gun icon
var gunIcon = self.attachAsset('dogBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: 60,
y: 0
});
gunIcon.tint = 0x888888; // Gray tint for gun icon
self.health = 3;
self.maxHealth = 3;
self.shootCooldown = 0;
self.shootRate = 20;
self.speed = 5;
self.powerUpActive = false;
self.powerUpEndTime = 0;
self.weaponType = 'knife';
self.weaponLevel = 1;
self.gold = 0;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
if (self.powerUpActive && LK.now > self.powerUpEndTime) {
self.powerUpActive = false;
self.speed = 5;
self.shootRate = 20;
}
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
var bullet = new DogBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.weaponType = self.weaponType;
bullet.weaponLevel = self.weaponLevel;
// Set direction based on current shoot direction
switch (currentShootDirection) {
case 'up':
bullet.dirX = 0;
bullet.dirY = -1;
bullet.y -= 60;
break;
case 'down':
bullet.dirX = 0;
bullet.dirY = 1;
bullet.y += 60;
break;
case 'left':
bullet.dirX = -1;
bullet.dirY = 0;
bullet.x -= 60;
break;
case 'right':
bullet.dirX = 1;
bullet.dirY = 0;
bullet.x += 60;
break;
}
bullets.push(bullet);
game.addChild(bullet);
self.shootCooldown = self.shootRate;
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
self.health--;
LK.effects.flashObject(self, 0xFF0000, 500);
if (self.health <= 0) {
LK.showGameOver();
}
};
self.activatePowerUp = function () {
self.powerUpActive = true;
self.powerUpEndTime = LK.now + 5000;
self.speed = 8;
self.shootRate = 11;
};
self.upgradeWeapon = function () {
if (self.weaponLevel < 3) {
self.weaponLevel++;
if (self.weaponLevel === 2 && (scientistResidues >= 1000 || LK.getScore() >= 2000)) {
self.weaponType = 'laser';
self.shootRate = 13;
} else if (self.weaponLevel === 3) {
self.shootRate = 7;
}
}
};
return self;
});
var DogBullet = Container.expand(function () {
var self = Container.call(this);
self.speed = 8;
self.damage = 1;
self.dirX = 0;
self.dirY = -1;
self.weaponType = 'knife';
self.weaponLevel = 1;
var bulletGraphics;
self.update = function () {
// Update graphics based on weapon type if not set
if (!bulletGraphics) {
if (self.weaponType === 'laser') {
bulletGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 2;
} else {
bulletGraphics = self.attachAsset('knife', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Set rotation based on direction
if (self.dirX === 1) bulletGraphics.rotation = Math.PI / 2;else if (self.dirX === -1) bulletGraphics.rotation = -Math.PI / 2;else if (self.dirY === 1) bulletGraphics.rotation = Math.PI;
}
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
var FastScientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('fastScientist', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 7.0;
self.health = 10;
self.points = 5;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var Gold = Container.expand(function () {
var self = Container.call(this);
var goldGraphics = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'gold';
self.value = 10;
self.update = function () {
self.rotation += 0.06;
};
return self;
});
var Metal = Container.expand(function () {
var self = Container.call(this);
var metalGraphics = self.attachAsset('metal', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'metal';
self.value = 5;
self.update = function () {
self.rotation += 0.05;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'speed';
self.duration = 5000;
self.update = function () {
self.rotation += 0.1;
};
return self;
});
var Scientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('scientist', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 5;
self.points = 3;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var SteelBall = Container.expand(function () {
var self = Container.call(this);
var steelBallGraphics = self.attachAsset('dogBullet', {
anchorX: 0.5,
anchorY: 0.5
});
steelBallGraphics.tint = 0x808080; // Gray color for steel
self.speed = 4;
self.damage = 1;
self.dirX = 0;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
var SteelBallScientist = Container.expand(function () {
var self = Container.call(this);
var scientistGraphics = self.attachAsset('scientist', {
anchorX: 0.5,
anchorY: 0.5
});
scientistGraphics.tint = 0x4169E1; // Blue tint to distinguish steel ball scientists
self.speed = 2.5;
self.health = 8; // 8 hits with knife, 5 with laser (damage 2)
self.points = 6;
self.targetX = 0;
self.targetY = 0;
self.shootCooldown = 0;
self.shootRate = 60; // Shoot every 60 frames (1 second)
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Shooting logic
if (self.shootCooldown > 0) {
self.shootCooldown--;
} else {
// Shoot at dog
var steelBall = new SteelBall();
steelBall.x = self.x;
steelBall.y = self.y;
// Calculate direction to dog
var shootDistance = Math.sqrt(dx * dx + dy * dy);
if (shootDistance > 0) {
steelBall.dirX = dx / shootDistance;
steelBall.dirY = dy / shootDistance;
}
steelBalls.push(steelBall);
game.addChild(steelBall);
self.shootCooldown = self.shootRate;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var Technology = Container.expand(function () {
var self = Container.call(this);
var technologyGraphics = self.attachAsset('technology', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'technology';
self.value = 50;
self.update = function () {
self.rotation += 0.08;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var dog = new Dog();
var bullets = [];
var scientists = [];
var powerUps = [];
var metals = [];
var chests = [];
var technologies = [];
var golds = [];
var dirButtons = [];
var steelBalls = [];
var currentShootDirection = 'up';
var spawnTimer = 0;
var waveTimer = 0;
var difficultyLevel = 1;
var lastSpawnRate = 120;
var scientistResidues = 0;
var scientistCount = 0;
var normalScientistHits = 0;
var fastScientistHits = 0;
var fastScientistSpawned = 0;
var normalScientistDeaths = 0;
var fastScientistDeaths = 0;
var explosionRange = 200; // Range for armed scientist explosions
// Add laboratory background
var labBackground = LK.getAsset('labBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(labBackground);
dog.x = 1024;
dog.y = 2200;
game.addChild(dog);
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var goldTxt = new Text2('Gold: 0', {
size: 60,
fill: 0xFFD700
});
goldTxt.anchor.set(0, 0);
goldTxt.x = 150;
goldTxt.y = 120;
LK.gui.topLeft.addChild(goldTxt);
var weaponTxt = new Text2('Weapon: Knife Lv.1', {
size: 50,
fill: 0xFFFFFF
});
weaponTxt.anchor.set(0, 0);
weaponTxt.x = 150;
weaponTxt.y = 190;
LK.gui.topLeft.addChild(weaponTxt);
var residueTxt = new Text2('Residues: 0/1000 (Laser: 1000 residues or 2000 score)', {
size: 45,
fill: 0x00FF00
});
residueTxt.anchor.set(0, 0);
residueTxt.x = 150;
residueTxt.y = 250;
LK.gui.topLeft.addChild(residueTxt);
// Create directional buttons in main game area with proper spacing
var upBtn = new DirectionalButton('up');
upBtn.x = 300;
upBtn.y = 2350;
game.addChild(upBtn);
dirButtons.push(upBtn);
var downBtn = new DirectionalButton('down');
downBtn.x = 300;
downBtn.y = 2650;
game.addChild(downBtn);
dirButtons.push(downBtn);
var leftBtn = new DirectionalButton('left');
leftBtn.x = 150;
leftBtn.y = 2500;
game.addChild(leftBtn);
dirButtons.push(leftBtn);
var rightBtn = new DirectionalButton('right');
rightBtn.x = 450;
rightBtn.y = 2500;
game.addChild(rightBtn);
dirButtons.push(rightBtn);
// Set initial button state
upBtn.alpha = 1.0;
var dragNode = null;
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
function updateGold() {
goldTxt.setText('Gold: ' + dog.gold);
}
function updateWeapon() {
var weaponName = dog.weaponType === 'knife' ? 'Knife' : 'Laser';
weaponTxt.setText('Weapon: ' + weaponName + ' Lv.' + dog.weaponLevel);
}
function updateResidue() {
// Give 20 score for each scientist residue collected
LK.setScore(LK.getScore() + 20);
updateScore();
var laserUnlocked = scientistResidues >= 1000 || LK.getScore() >= 2000;
if (laserUnlocked) {
residueTxt.setText('Residues: ' + scientistResidues + '/1000 (LASER UNLOCKED!)');
} else {
residueTxt.setText('Residues: ' + scientistResidues + '/1000 (Laser: 1000 residues or 2000 score)');
}
}
function spawnScientist() {
var scientist;
scientistCount++;
if (fastScientistDeaths >= 6 && fastScientistDeaths % 6 === 0) {
scientist = new ArmedScientist();
fastScientistDeaths++; // Increment to avoid spawning multiple in a row
} else if (scientistCount % 10 === 0) {
scientist = new FastScientist();
fastScientistSpawned++;
// Spawn SteelBallScientist after every 5 fast scientists
if (fastScientistSpawned % 5 === 0) {
scientist = new SteelBallScientist();
}
} else {
scientist = new Scientist();
}
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
scientist.x = Math.random() * 2048;
scientist.y = -40;
break;
case 1:
// Right
scientist.x = 2088;
scientist.y = Math.random() * 2732;
break;
case 2:
// Bottom
scientist.x = Math.random() * 2048;
scientist.y = 2772;
break;
case 3:
// Left
scientist.x = -40;
scientist.y = Math.random() * 2732;
break;
}
scientist.targetX = dog.x;
scientist.targetY = dog.y;
scientists.push(scientist);
game.addChild(scientist);
}
function spawnPowerUp() {
if (Math.random() < 0.02 && powerUps.length < 2) {
var powerUp = new PowerUp();
powerUp.x = Math.random() * 1800 + 124;
powerUp.y = Math.random() * 2400 + 166;
powerUps.push(powerUp);
game.addChild(powerUp);
}
}
function spawnLoot(x, y) {
var lootChance = Math.random();
var loot;
if (lootChance < 0.5) {
// 50% chance for metal
loot = new Metal();
metals.push(loot);
} else if (lootChance < 0.8) {
// 30% chance for chest
loot = new Chest();
chests.push(loot);
} else {
// 20% chance for technology
loot = new Technology();
technologies.push(loot);
}
loot.x = x;
loot.y = y;
game.addChild(loot);
}
function spawnGoldFromChest(x, y) {
// Spawn 2-3 gold pieces from chest
var goldCount = Math.floor(Math.random() * 2) + 2;
for (var i = 0; i < goldCount; i++) {
var gold = new Gold();
gold.x = x + (Math.random() - 0.5) * 60;
gold.y = y + (Math.random() - 0.5) * 60;
golds.push(gold);
game.addChild(gold);
}
}
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(60, Math.min(1988, x));
dragNode.y = Math.max(60, Math.min(2672, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = dog;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
spawnTimer++;
waveTimer++;
if (waveTimer % 1800 === 0) {
difficultyLevel++;
lastSpawnRate = Math.max(30, lastSpawnRate - 10);
}
if (spawnTimer >= lastSpawnRate) {
spawnScientist();
spawnTimer = 0;
}
spawnPowerUp();
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.y < -50 || bullet.y > 2782 || bullet.x < -50 || bullet.x > 2098) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
for (var j = scientists.length - 1; j >= 0; j--) {
var scientist = scientists[j];
if (bullet.intersects(scientist)) {
if (scientist.takeDamage(bullet.damage)) {
LK.setScore(LK.getScore() + scientist.points);
updateScore();
spawnLoot(scientist.x, scientist.y);
scientistResidues++;
updateResidue();
// Track normal scientist deaths
if (scientist.constructor === Scientist) {
normalScientistDeaths++;
} else if (scientist.constructor === FastScientist) {
fastScientistDeaths++;
}
scientist.destroy();
scientists.splice(j, 1);
LK.getSound('hit').play();
}
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
}
for (var k = scientists.length - 1; k >= 0; k--) {
var scientist = scientists[k];
if (!scientist) continue; // Skip if scientist is undefined
scientist.targetX = dog.x;
scientist.targetY = dog.y;
if (scientist.intersects(dog)) {
// Deduct half the score that the enemy would give when killed
var scoreDeduction = Math.floor(scientist.points / 2);
LK.setScore(Math.max(0, LK.getScore() - scoreDeduction));
updateScore();
// Check if it's an armed scientist (red) - trigger explosion
if (scientist.constructor === ArmedScientist) {
scientist.takeDamage(999); // Force explosion by dealing massive damage
scientists.splice(k, 1);
continue;
}
// Track hits by scientist type
if (scientist.constructor === FastScientist) {
fastScientistHits++;
} else if (scientist.constructor === Scientist) {
normalScientistHits++;
}
// Check death conditions
if (normalScientistHits >= 5 || fastScientistHits >= 3) {
LK.showGameOver();
}
scientist.destroy();
scientists.splice(k, 1);
continue;
}
var distanceToEdge = Math.min(scientist.x, 2048 - scientist.x, scientist.y, 2732 - scientist.y);
if (distanceToEdge < -100) {
scientist.destroy();
scientists.splice(k, 1);
}
}
for (var l = powerUps.length - 1; l >= 0; l--) {
var powerUp = powerUps[l];
if (powerUp.intersects(dog)) {
LK.setScore(LK.getScore() + 2);
updateScore();
dog.activatePowerUp();
LK.getSound('powerup').play();
powerUp.destroy();
powerUps.splice(l, 1);
}
}
// Check metal collection
for (var m = metals.length - 1; m >= 0; m--) {
var metal = metals[m];
if (metal.intersects(dog)) {
LK.setScore(LK.getScore() + metal.value);
updateScore();
metal.destroy();
metals.splice(m, 1);
}
}
// Check chest collection
for (var c = chests.length - 1; c >= 0; c--) {
var chest = chests[c];
if (chest.intersects(dog)) {
LK.setScore(LK.getScore() + chest.value);
updateScore();
// Spawn gold from chest
spawnGoldFromChest(chest.x, chest.y);
// Random chance for weapon upgrade
if (Math.random() < 0.3) {
dog.upgradeWeapon();
updateWeapon();
}
chest.destroy();
chests.splice(c, 1);
}
}
// Check technology collection
for (var t = technologies.length - 1; t >= 0; t--) {
var technology = technologies[t];
if (technology.intersects(dog)) {
LK.setScore(LK.getScore() + technology.value);
updateScore();
technology.destroy();
technologies.splice(t, 1);
}
}
// Check gold collection
for (var g = golds.length - 1; g >= 0; g--) {
var gold = golds[g];
if (gold.intersects(dog)) {
dog.gold += gold.value;
updateGold();
gold.destroy();
golds.splice(g, 1);
}
}
// Check steel ball collisions with dog
for (var s = steelBalls.length - 1; s >= 0; s--) {
var steelBall = steelBalls[s];
if (steelBall.y < -50 || steelBall.y > 2782 || steelBall.x < -50 || steelBall.x > 2098) {
steelBall.destroy();
steelBalls.splice(s, 1);
continue;
}
if (steelBall.intersects(dog)) {
dog.takeDamage();
steelBall.destroy();
steelBalls.splice(s, 1);
}
}
if (LK.ticks % 10 === 0 && dog.powerUpActive) {
dog.shoot();
}
};
LK.playMusic('bgmusic');
Cabeza de perro labrador. In-Game asset. 2d. High contrast. No shadows
Láser azul. In-Game asset. 2d. High contrast. No shadows
Perrobala. In-Game asset. 2d. High contrast. No shadows
Huella de perro. In-Game asset. 2d. High contrast. No shadows
Vista desde arriba de un laboratorio. In-Game asset. 2d. High contrast. No shadows