<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="icon" src="/images/favicon.gif" />
<title>star thing</title>
<style type="text/css">
* { padding: 0; margin: 0; border: 0; font-size: 8pt; font-weight: normal; }
html, body {
height: 100%;
width: 100%;
background: #000;
color: #fff;
font-family: sans-serif;
}
html { display: table; }
body { display: table-cell; vertical-align: middle; text-align: center; }
a { color: #88f; }
</style>
</head>
<body>
<canvas height="600px" width="800px">Y U no canvas?</canvas>
<script type="text/javascript">
/* let's build a canvas rendering environment comparable to oldschool vga hardware */
/* handily, we also get triple buffering out of this setup, for free. */
var ele = document.getElementsByTagName("canvas")[0];
var scr = ele.getContext("2d");
scr.ratio = ele.width / ele.height;
/* turn off smooth resizing of huge pixels. we want all the pixelly goodness. */
/* having to do this is silly. browser vendors, stop this shit. */
if (scr.imageSmoothingEnabled) scr.imageSmoothingEnabled = false;
else if (scr.webkitImageSmoothingEnabled) scr.webkitImageSmoothingEnabled = false;
else if (scr.mozImageSmoothingEnabled) scr.mozImageSmoothingEnabled = false;
else if (scr.msImageSmoothingEnabled) scr.msImageSmoothingEnabled = false;
else if (scr.oImageSmoothingEnabled) scr.oImageSmoothingEnabled = false;
var rsz = document.createElement("canvas");
rsz.height = (""+document.location.href).match(/[?&](lines|height)=([^&]*)/) ? RegExp.lastParen : 200;
rsz.width = (""+document.location.href).match(/[?&]columns=([^&]*)/) ? RegExp.lastParen : 4 * rsz.height / 3;
var ctx = rsz.getContext("2d");
var img = ctx.createImageData(rsz.width, rsz.height);
/* now, let's build some simple graphics functions */
img.ratio = img.width / img.height;
img.astigmatism = scr.ratio / img.ratio;
img.a = 255; /* alpha */
img.inBounds = function inBounds () {
return (
this.x >= 0 && this.x < this.width &&
this.y >= 0 && this.y < this.height
);
}
img.setIndex = function setIndex () {
if (!this.inBounds()) return false;
this.i = 4 * (this.width * this.y + this.x);
return this;
}
img.putpxRaw = function putpxRaw () {
var b = this.i;
this.data[b++] = this.r & 255;
this.data[b++] = this.g & 255;
this.data[b++] = this.b & 255;
this.data[b] = this.a & 255;
return this;
}
img.putpx = function putpx () {
if (!this.setIndex()) return false;
return this.putpxRaw();
}
img.getpxRaw = function getpxRaw () {
var b = this.i;
this.r = this.data[b++];
this.g = this.data[b++];
this.b = this.data[b];
/* skip alpha */
return this;
}
img.getpx = function getpx () {
if (!this.setIndex()) return false;
return this.getpxRaw();
}
/* behold, stars */
var stars = [];
stars.length = (""+document.location.href).match(/[?&]stars=([^&]*)/) ? RegExp.lastParen : 512;
for (var i = 0; i < stars.length; i++)
do stars[i] = {
x: Math.floor(Math.random() * img.width * 2),
y: Math.floor(Math.random() * img.height * 2),
z: Math.floor(Math.random() * 256)
};
while (stars[i].x == img.width && stars[i].y == img.height);
/* let's add some new stuff to the boring old starfield */
/* thanks, GPU acceleration! */
var tux = document.createElement("img");
tux.angle = 0;
tux.v = { x: 1, y: 1 };
tux.spin = Math.floor(Math.random() * 2) * 2 - 1;
tux.save = function () {
ctx.translate(tux.p.x, tux.p.y);
ctx.rotate(this.angle / 18);
ctx.translate(-tux.width / 2, -tux.height * 2 / 3);
}
tux.restore = function () {
ctx.translate(tux.width / 2, tux.height * 2 / 3);
ctx.rotate(-this.angle / 18);
ctx.translate(-tux.p.x, -tux.p.y);
}
tux.clear = function () {
tux.save();
ctx.fillStyle = "rgb(0, 0, 0)";
ctx.fillRect(0, 0, tux.width, tux.height);
scr.drawImage(rsz, 0, 0, ele.width, ele.height);
tux.restore();
}
tux.draw = function () {
tux.angle += tux.spin;
tux.save();
ctx.drawImage(tux, 0, 0, tux.width, tux.height);
tux.restore();
}
tux.move = function () {
tux.p.x += tux.v.x;
tux.p.y += tux.v.y;
/* this part could stand some meditation */
if (tux.p.x < tux.height * 2 / 3) {
tux.v.x = 1;
tux.spin = tux.v.y;
} else if (tux.p.y < tux.height * 2 / 3) {
tux.v.y = 1;
tux.spin = -tux.v.x;
} else if (tux.p.x >= (img.width - tux.height * 2 / 3)) {
tux.v.x = -1;
tux.spin = -tux.v.y;
} else if (tux.p.y >= (img.height - tux.height * 2 / 3)) {
tux.v.y = -1;
tux.spin = tux.v.x;
}
}
/* render loop! go! */
var animate = { angle: 0 };
animate.doframe = function () {
/* avoid killing browsers that actually do threads properly */
if (this.busy++) { return --this.busy; }
/* make room for tux */
tux.clear();
/* draw starfield */
ctx.putImageData(img, 0, 0);
/* draw tux */
tux.move();
tux.draw();
/* blit to screen */
scr.drawImage(rsz, 0, 0, ele.width, ele.height);
/* draw stars to buffer for next frame */
for (var i = 0; i < stars.length; i++) {
img.r = img.g = img.b = 0;
img.x = Math.floor(((stars[i].x - img.width) << 7) / stars[i].z + img.width / 2);
img.y = Math.floor(((stars[i].y - img.height) << 7) / stars[i].z + img.height / 2);
if (img.setIndex()) img.putpxRaw();
if (0 < (stars[i].z -= 1)) {
img.x = Math.floor(((stars[i].x - img.width) << 7) / stars[i].z + img.width / 2);
img.y = Math.floor(((stars[i].y - img.height) << 7) / stars[i].z + img.height / 2);
}
if (img.setIndex()) {
var c = 256 - stars[i].z;
if (img.getpxRaw().g < c) {
img.r = img.g = img.b = Math.floor((Math.random() * 32 + c) * 256 / (256 + 32));
img.putpxRaw();
}
} else do stars[i] = {
x: Math.floor(Math.random() * img.width * 2),
y: Math.floor(Math.random() * img.height * 2),
z: 255
}; while (stars[i].x == img.width && stars[i].y == img.height);
}
/* clear semaphore */
this.busy--;
}
/* load the gun */
tux.onload = function () {
/* resize tux for the sake of fitting on the screen */
this.height = this.height * rsz.height / 600;
this.width = this.width * rsz.height / 600;
/* set his initial position */
this.p = {
x: Math.floor(Math.random() * (img.width - this.width)) + this.width / 2,
y: Math.floor(Math.random() * (img.height - this.height)) + this.height / 2
};
/* kick off the animation */
animate.doframe();
setInterval(animate.doframe.bind(animate), 1000/30);
};
/* pull the trigger */
tux.src = "/images/tux-beer.gif";
</script>
</body>
</html>