Zombie Error
https://dl.dropboxusercontent.com/u/141246873/ZombieError/index.html
Note: It might take a few seconds to load due to the image file.
The webpage consists of the below html, css and javascript as well as an image file zombie.png (graphics by Clint Bellanger licensed CC-BY 3.0).
Tested in google chrome v36, but I expect it will work in most browsers.
Update:
26th Jul: Now removes zombies once they walk off the screen
28th Jul: You can now click on the zombies to blast them off the website
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Zombie Error</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<script src="zombie.js"></script>
</head>
<body style="margin: 0px;">
<div style="position: relative;">
<div style="margin: 0 auto; width:100%; height:100%;">
<iframe src="https://godaddy.com/" style="width: 100%; height: 100%; margin: 0; border-width: 0px;"></iframe>
</div>
</div>
</body>
</html>
CSS:
body {
font-family: 'Segoe UI', sans-serif;
}
span {
font-style: italic;
}
.zombie{
width: 78px;
height: 78px;
background-image: url('https://dl.dropboxusercontent.com/u/141246873/ZombieError/zombie.png');
background-position: left;
background-position-x: 0px;
background-position-y: 0px;
position: absolute;
left: 10px;
top: 10px;
}
body{
overflow: hidden;
}
Javascript:
var directionWest = 0;
var directionNorth = 6;
var directionEast = 4;
var directionSouth = 2;
var stateWalking = 0;
var stateDying = 1;
var stateDead = 2;
var animWalk = {
speed: 0.15,
numFrames: 8,
frames: [4, 5, 6, 7, 8, 9, 10, 11]
}
var animDying = {
speed: 0.10,
numFrames: 8,
frames: [28, 29, 30, 31, 32, 33, 34, 35]
}
var spriteWidth = 128;
var spriteHeight = 128;
var spriteOffsetX = 25;
var spriteOffsetY = 25;
var spritesheetWidth = 4608;
function Zombie(_id, _x, _y, _direction) {
this.direction = _direction
this.id = _id;
this.pos = { x: _x, y: _y }
this.anim = animWalk;
this.animFrame = 0;
this.animDelta = 0;
this.speed = 30;
this.state = stateWalking;
this.corpseDelta = 0;
return this;
}
Zombie.prototype.Update = function (delta) {
if (this.state == stateDead)
return;
//update the animation frame
this.animDelta += delta;
if (this.animDelta >= this.anim.speed) {
this.animDelta -= this.anim.speed;
this.animFrame++;
if (this.animFrame >= this.anim.numFrames)
this.animFrame = 0;
}
//background-position-x
var div = document.getElementById(this.id);
div.style.backgroundPositionX = ((spritesheetWidth - (spriteWidth * this.anim.frames[this.animFrame])) - spriteOffsetX) + "px";
div.style.backgroundPositionY = ((spriteHeight * this.direction) - spriteOffsetY) + "px";
if (this.state == stateWalking) {
//update position
if (this.direction == directionEast)
this.pos.x += (this.speed * delta);
if (this.direction == directionWest)
this.pos.x -= (this.speed * delta);
if (this.direction == directionNorth)
this.pos.y -= (this.speed * delta);
if (this.direction == directionSouth)
this.pos.y += (this.speed * delta);
div.style.left = Math.floor(this.pos.x) + "px";
div.style.top = Math.floor(this.pos.y) + "px";
}
else if (this.state == stateDying && this.animFrame == (this.anim.numFrames - 1)) {
this.state = stateDead;
}
}
var zombies = []
var nextZombieID = 0;
function GetZombie(zombieID)
{
return zombies.filter(function (z) { return z.id == zombieID })[0];
}
function ZombieClick(div)
{
var zombie = GetZombie(div.srcElement.id);
if (zombie.state == stateWalking) {
zombie.state = stateDying;
zombie.animFrame = 0;
zombie.animDelta = 0;
zombie.anim = animDying;
}
}
function NewZombie()
{
var x = 0;
var y = 0;
var direction = 0;
var rand = Math.random();
if (rand < 0.25)
{
//spawn from left of screen
x = spriteWidth * -1;
y = (Math.random() * screen.height) - spriteHeight;
direction = directionEast;
}
else if (rand < 0.5) {
//spawn from right of screen
x = screen.width;
y = (Math.random() * screen.height) - spriteHeight;
direction = directionWest;
}
else if (rand < 0.75) {
//spawn from top of screen
x = (Math.random() * screen.width) - spriteWidth;
y = spriteWidth * -1;
direction = directionSouth;
}
else {
//spawn from bottom
x = (Math.random() * screen.width) - spriteWidth;
y = screen.height;
direction = directionNorth;
}
//generate an id
var id = nextZombieID;
nextZombieID++;
//create a div
var div = document.createElement("div");
div.id = id;
div.classList.add("zombie");
div.onclick = ZombieClick;
document.body.appendChild(div);
//create a zombie
zombies.push(new Zombie(id, x, y, direction));
}
var spawnRate = 1;
var spawnDelta = 0;
function spawnZombies(delta)
{
spawnDelta += delta;
if (spawnDelta >= spawnRate) {
spawnDelta -= spawnRate;
NewZombie();
}
}
var corpseDuration = 3;
function cleanupZombies(delta)
{
for (var i = zombies.length - 1; i >= 0 ; i--) {
//if the zombie has walked off the screen, remove them
if (zombies[i].pos.x < (spriteWidth * -2)
|| zombies[i].pos.x > screen.width + spriteWidth
|| zombies[i].pos.y < (spriteHeight * -2)
|| zombies[i].pos.y > screen.height + spriteHeight)
{
var element = document.getElementById(zombies[i].id);
element.parentNode.removeChild(element);
zombies.splice(i, 1);
}
}
for (var i = zombies.length - 1; i >= 0 ; i--) {
//if the zombie has died, remove their corpse after some time
if (zombies[i].state == stateDead) {
zombies[i].corpseDelta += delta;
if (zombies[i].corpseDelta > corpseDuration) {
var element = document.getElementById(zombies[i].id);
element.parentNode.removeChild(element);
zombies.splice(i, 1);
}
}
}
}
var started = false;
var main = function () {
var now = Date.now();
var delta = now - then;
if (started) {
cleanupZombies(delta / 1000);
spawnZombies(delta / 1000);
for (var i in zombies)
zombies[i].Update(delta / 1000);
}
then = now;
setTimeout(main, 30);
};
var then = Date.now();
setTimeout(main, 30);
setTimeout(function () {
alert("Error 8102: Unexpected zombie attack. Please stand by...");
started = true;
}, 2000)
I think this could have some interesting results, even though it's a very broad challenge. – nderscore – 2014-07-24T20:31:40.550
I do not see what is unclear at the moment, I voted for reopening. It is of course a broad challenge as @nderscore mentioned, all in all a rather creative task than a programming challenge and I think that this has to have its place here too. – flawr – 2014-07-24T20:49:37.707
2it seems to me challenges like this are the exact reason the admins were so hesitant to allow [tag:popularity-contest] on the site.. no real objective way to identify a "correct answer" – ardnew – 2014-07-24T23:05:11.530
@ardnew thats why its a [tag:popularity-contest], there is no right or wrong. the one with the most votes wins. – Teun Pronk – 2014-07-25T07:14:03.543
1@TeunPronk No - A popularity-contest is a competition where the correct answer with the highest vote tally (upvotes minus downvotes) wins, usually the most creative answer. Each [tag:popularity-contest] must give precise requirements such that we can judge if an answer is correct. – Howard – 2014-07-25T08:28:06.137
@Howard okay, fair enough.. my bad. On the other hand, he did give requirements even if there aren't a lot but they are there. – Teun Pronk – 2014-07-25T08:33:09.933
Wouldn't it be more fun to see who could actually crash the browser fastest with the smallest amount of code ? – adeneo – 2014-07-26T22:28:02.323