/****
* Classes
****/
var Puff = Container.expand(function () {
var self = Container.call(this);
var puffGraphics = self.attachAsset('puff', {
anchorX: 0.5,
anchorY: 0.5
});
self.tick = function () {
self.scale.x += 0.05;
self.scale.y += 0.05;
self.alpha -= 0.05;
if (self.alpha <= 0) {
self.destroy();
}
};
});
var ClickTarget = Container.expand(function () {
var self = Container.call(this);
var targetGraphics = self.attachAsset('clickTarget', {
anchorX: 0.5,
anchorY: 0.5
});
targetGraphics.alpha = 0.4;
self.x = 0;
self.y = 0;
self.setVisible = function (isVisible) {
self.visible = isVisible;
};
});
var HealthBar = Container.expand(function (maxHealth, currentHealth) {
var self = Container.call(this);
self.maxHealth = maxHealth;
self.currentHealth = currentHealth;
var background = self.attachAsset('healthBarBackground', {
anchorX: 0.5,
anchorY: 1
});
var foreground = self.attachAsset('healthBarForeground', {
anchorX: 0.5,
anchorY: 1
});
foreground.y -= 5;
self.updateHealth = function (newHealth) {
self.currentHealth = newHealth;
var healthRatio = self.currentHealth / self.maxHealth;
foreground.scale.x = healthRatio;
};
});
var Hero = Container.expand(function () {
var self = Container.call(this);
self.findNearestZombie = function (zombies) {
var nearestZombie = null;
var nearestDistance = Infinity;
for (var i = 0; i < zombies.length; i++) {
var dx = zombies[i].x - self.x;
var dy = zombies[i].y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestZombie = zombies[i];
nearestDistance = distance;
}
}
return nearestZombie;
};
self.targetX = 2048 / 2;
self.targetY = 2732 / 2;
var heroShadow = self.attachAsset('heroShadow', {
anchorX: 0.5,
anchorY: 0.5
});
heroShadow.alpha = 0.3;
heroShadow.zIndex = -1;
self.addChild(heroShadow);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.4,
anchorY: 0.3
});
self.addChild(heroGraphics);
var initialHeroRotation = -0.0872665 - 35 * (Math.PI / 180);
heroGraphics.rotation = initialHeroRotation;
self.healthBar = self.addChild(new HealthBar(100, 100));
self.healthBar.y = -125;
self.move = function () {
if (self.targetX !== undefined && self.targetY !== undefined) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var speed = 5;
self.x += dx / distance * speed;
self.y += dy / distance * speed;
var angle = Math.atan2(dy, dx);
heroGraphics.rotation = angle + initialHeroRotation;
return false;
} else {
self.x = self.targetX;
self.y = self.targetY;
return true;
}
} else {
return true;
}
};
self.shootDelay = 0;
self.shoot = function (zombies) {
if (self.shootDelay <= 0 && self.targetX === self.x && self.targetY === self.y) {
var nearestZombie = self.findNearestZombie(zombies);
if (nearestZombie) {
var dx = nearestZombie.x - self.x;
var dy = nearestZombie.y - self.y;
var direction = Math.atan2(dy, dx);
var bullet = new Bullet(self, direction);
self.shootDelay = 15;
heroGraphics.rotation = direction + initialHeroRotation;
return bullet;
}
}
self.shootDelay--;
return null;
};
});
var Zombie = Container.expand(function (hero) {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.rotation = -Math.PI / 2;
self.target = hero;
self.healthBar = self.addChild(new HealthBar(100, 100));
self.healthBar.y = -125;
self.spawn = function () {
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
self.x = Math.random() * 2048;
self.y = -50;
break;
case 1:
self.x = 2048 + 50;
self.y = Math.random() * 2732;
break;
case 2:
self.x = Math.random() * 2048;
self.y = 2732 + 50;
break;
case 3:
self.x = -50;
self.y = Math.random() * 2732;
break;
}
};
self.move = function (zombies) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var speed = 2;
self.x += dx / distance * speed;
self.y += dy / distance * speed;
var angle = Math.atan2(dy, dx);
zombieGraphics.rotation = angle - Math.PI / 2;
}
for (var i = 0; i < zombies.length; i++) {
if (zombies[i] !== self) {
var dx2 = zombies[i].x - self.x;
var dy2 = zombies[i].y - self.y;
var distance2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
if (distance2 < 1000) {
self.x += dx2 / distance2 * 1;
self.y += dy2 / distance2 * 1;
}
}
}
};
self.removed = false;
self.merge = function (otherZombie) {
if (otherZombie.removed) {
return false;
}
var newMaxHealth = self.healthBar.maxHealth + otherZombie.healthBar.maxHealth;
self.x = (self.x + otherZombie.x) / 2;
self.y = (self.y + otherZombie.y) / 2;
self.healthBar.maxHealth = newMaxHealth * 0.8;
self.healthBar.updateHealth((self.healthBar.currentHealth + otherZombie.healthBar.currentHealth) * 0.8);
self.scale.x = (self.scale.x + otherZombie.scale.x) / 2 * 1.2;
self.scale.y = (self.scale.y + otherZombie.scale.y) / 2 * 1.2;
otherZombie.removed = true;
return true;
};
self.hit = function () {
var newHealth = self.healthBar.currentHealth - 10;
self.healthBar.updateHealth(newHealth);
if (newHealth <= 0) {
return true;
}
};
});
var Bullet = Container.expand(function (shooter, direction) {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.x = shooter.x - Math.cos(direction - .5) * 55;
self.y = shooter.y - Math.sin(direction - .5) * 55;
self.direction = direction;
self.hit = false;
self.move = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
bulletGraphics.rotation = self.direction + Math.PI / 2;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var background = game.attachAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2 - 80;
background.y = 2732 / 2;
background.alpha = .4;
var hero,
zombies = [],
bullets = [],
effects = [];
var scoreTxt,
timer,
score = 0;
hero = game.addChild(new Hero());
hero.x = 2048 / 2;
hero.y = 2732 / 2;
scoreTxt = new Text2('0', {
size: 120,
fill: "#ffffff",
font: 'Impact',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreTxt.anchor.set(.5, 0);
LK.gui.topCenter.addChild(scoreTxt);
LK.on('tick', function () {
if (hero.move() && game.clickTarget) {
game.clickTarget.setVisible(false);
}
if (hero.shootDelay <= 0) {
var newBullet = hero.shoot(zombies);
if (newBullet) {
bullets.push(newBullet);
game.addChildAt(newBullet, game.getChildIndex(hero));
}
}
hero.shootDelay--;
for (var i = 0; i < zombies.length; i++) {
zombies[i].move(zombies);
}
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].move();
if (bullets[i].x < 0 || bullets[i].x > 2048 || bullets[i].y < 0 || bullets[i].y > 2732) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
for (var i = zombies.length - 1; i >= 0; i--) {
for (var j = bullets.length - 1; j >= 0; j--) {
if (bullets[j].intersects(zombies[i]) && !bullets[j].hit) {
bullets[j].hit = true;
if (zombies[i].hit()) {
zombies[i].destroy();
zombies.splice(i, 1);
score++;
LK.setScore(score);
scoreTxt.setText(score);
}
bullets[j].destroy();
bullets.splice(j, 1);
}
}
for (var k = 0; k < zombies.length; k++) {
if (zombies[i] !== zombies[k] && zombies[i] && zombies[k] && zombies[i].intersects(zombies[k])) {
if (zombies[i].merge(zombies[k])) {
var puff = new Puff();
puff.x = zombies[i].x;
puff.y = zombies[i].y;
effects.push(puff);
game.addChild(puff);
zombies[k].destroy();
zombies.splice(k, 1);
}
}
}
}
for (var i = 0; i < zombies.length; i++) {
if (hero.intersects(zombies[i])) {
hero.healthBar.updateHealth(hero.healthBar.currentHealth - 0.5);
}
}
for (var i = effects.length - 1; i >= 0; i--) {
effects[i].tick();
if (effects[i].alpha <= 0) {
effects.splice(i, 1);
}
}
if (isGameOver()) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
});
game.on('down', function (obj) {
var pos = obj.event.getLocalPosition(game);
hero.targetX = pos.x;
hero.targetY = pos.y;
if (!game.clickTarget) {
game.clickTarget = game.addChildAt(new ClickTarget(), game.getChildIndex(background) + 1);
}
game.clickTarget.x = pos.x;
game.clickTarget.y = pos.y;
game.clickTarget.setVisible(true);
});
var spawnInterval = 2100;
timer = LK.setInterval(function () {
var zombie = new Zombie(hero);
zombie.spawn();
zombies.push(zombie);
game.addChild(zombie);
spawnInterval = Math.max(500, spawnInterval - 10);
LK.clearInterval(timer);
timer = LK.setInterval(arguments.callee, spawnInterval);
}, spawnInterval);
function isGameOver() {
return hero.healthBar.currentHealth <= 0;
}
Soldier with gun seen from above. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
empty abandoned city street background seen from the top. Zoomed in. Top down. Street only
Zombie seen from above. Arms in front of it Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Fired Bullet tip, no case, grayscale Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Simple circular click target, showing where the hero needs to walk to. Grayscale. No shadows Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cloud puff explosion, grayscale, seen from topdown. Circular. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.