User prompt
reduce player bullet damage by 25%
User prompt
set a maximum fire rate for the hero weapon to 333ms
User prompt
increase zombie speed by 50%
User prompt
add code that stops zombies intersecting
User prompt
stop zombies damaging or killing each other
User prompt
double player bullet damage
User prompt
add more zombies
User prompt
have more zombies on screen
User prompt
the player moves instantaneously, this is a bug
User prompt
keep the player movement as it is, but the player character can shoot while moving
User prompt
double player bullet damage
User prompt
the player can shoot while moving
User prompt
Triple the speed of the bullets
User prompt
only fire a new player bullet when the previous bullet is offscreen or has hit an enemy
User prompt
Fix Bug: 'TypeError: undefined is not an object (evaluating 'self.bullets.length')' in this line: 'if (self.shootDelay <= 0 && self.targetX === self.x && self.targetY === self.y && self.bullets.length === 0) {' Line Number: 87
User prompt
Fix Bug: 'ReferenceError: Can't find variable: bullets' in this line: 'if (self.shootDelay <= 0 && self.targetX === self.x && self.targetY === self.y && bullets.length === 0) {' Line Number: 87
User prompt
there is only one player bullet on screen at any one time
Remix started
Copy Merging Zombie Defense
var Puff = Container.expand(function () {
var self = Container.call(this);
var puffGraphics = self.createAsset('puff', 'Puff effect', .5, .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.createAsset('clickTarget', 'Click Target', 0.5, 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.createAsset('healthBarBackground', 'Health Bar Background', .5, 1);
var foreground = self.createAsset('healthBarForeground', 'Health Bar Foreground', .5, 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.createAsset('heroShadow', 'Hero Shadow', .5, .5);
heroShadow.alpha = 0.3;
heroShadow.zIndex = -1;
self.addChild(heroShadow);
var heroGraphics = self.createAsset('hero', 'Hero character', .4, .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.createAsset('zombie', 'Zombie character', .5, .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.createAsset('bullet', 'Bullet Graphics', .5, .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;
};
});
var Game = Container.expand(function () {
var self = Container.call(this);
var background = self.createAsset('background', 'Game Background', .5, .5);
background.x = 2048 / 2 - 80;
background.y = 2732 / 2;
background.alpha = .4;
var hero, zombies = [], bullets = [], effects = [];
var scoreTxt, timer, score = 0;
hero = self.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() && self.clickTarget) {
self.clickTarget.setVisible(false);
}
if (hero.shootDelay <= 0) {
var newBullet = hero.shoot(zombies);
if (newBullet) {
bullets.push(newBullet);
self.addChildAt(newBullet, self.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++;
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);
self.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();
}
});
stage.on('down', function (obj) {
var pos = obj.event.getLocalPosition(self);
hero.targetX = pos.x;
hero.targetY = pos.y;
if (!self.clickTarget) {
self.clickTarget = self.addChildAt(new ClickTarget(), self.getChildIndex(background) + 1);
}
self.clickTarget.x = pos.x;
self.clickTarget.y = pos.y;
self.clickTarget.setVisible(true);
});
var spawnInterval = 2100;
timer = LK.setInterval(function () {
var zombie = new Zombie(hero);
zombie.spawn();
zombies.push(zombie);
self.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.