Skip to content

Instantly share code, notes, and snippets.

@aemkei
Forked from maettig/LICENSE.txt
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aemkei/cbb8434989d2e18aa1c2 to your computer and use it in GitHub Desktop.
Save aemkei/cbb8434989d2e18aa1c2 to your computer and use it in GitHub Desktop.

An oldskool remake of the classic arcade game Pac-Man almost completely made with 140 bytes snippets. Collect all points in all six levels to win the game. Avoid the ghosts. Click here to play the game.

My getFirstElement is based on @jed's cssSelect. Everything else is created from scratch. Tested with Opera, Firefox and Internet Explorer 8.

Optional graphics are supported and can be downloaded here.

function(l, k) //level object, keyCode
{
l[l.x] = 0; //remove player from level
l.p += l[ //increase points
l.x += //walk
l.d = //calculate walking direction
k - 37 >> 2 || //if no cursor key was pressed or
l[l.x + ( //check new position
k = k % 2 //calculate new walking direction
? k - 38 //-1 is left, +1 is right
: (k - 39) * l.w //-width is up, +width is down
)] & 4 //if it's not possible to use new direction
? l[l.x + l.d //then check old direction
] & 4 //if it's a wall
? 0 //stop
: l.d //else use old direction
: k //else use new direction
] == 2; //if walking into some gold
l.e |= l[l.x] & 8;
l[l.x] = 1 //place player in level
}
function(l,k){l[l.x]=0;l.p+=l[l.x+=l.d=k-37>>2||l[l.x+(k=k%2?k-38:(k-39)*l.w)]&4?l[l.x+l.d]&4?0:l.d:k]==2;l.e|=l[l.x]&8;l[l.x]=1}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Thiemo Mättig <http://maettig.com/>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "pacMan",
"description": "Pac-Man made with 140 bytes snippets.",
"keywords": [
"game",
"pacman"
]
}
<!DOCTYPE html>
<title>Pac-Man in 140byt.es by @maettig</title>
<pre>LOADING...</pre>
<h2></h2>
<span id="points">0</span> POINTS
<style type="text/css">
* { color: #FFF; font-family: Consolas, monospace; text-shadow: 0 0 .2em #FFF; }
body { background: #000; margin: 4em; }
h2 { font-size: 3em; margin: .2em 0; }
img { border: 0; font-size: 32px; height: 32px; padding: 1px; vertical-align: top; width: 32px; }
pre { font-size: 58px; line-height: 32px; margin: 0; }
#points { font-size: 2em; line-height: 2em; }
.air { color: #222; text-shadow: 0 0 .2em #222; }
.player { color: #FD0; text-shadow: 0 0 .2em #FD0; }
.wall { color: #30F; text-shadow: 0 0 .2em #30F; }
.ghost { color: #A0F; text-shadow: 0 0 .2em #A0F; }
</style>
<script type="text/javascript">
// 138 bytes
var getFirstElement = function(a)
{
a = /([#.]?)(.*)/.exec(a || '*');
a = document['getElement' + (a[1] > '-' ? 'sByClassName' : a[1] ? 'ById' : 'sByTagName')](a[2]);
return a[0] || a
}
// 69 bytes
var getOuterHTML = function(a)
{
return a.outerHTML || XMLSerializer().serializeToString(a)
}
// 126 bytes
var parseLevel = function(l, w)
{
l = l.join ? l[0].length > 1 //if it's an array of strings per row
? l.join('\n') : l.join('') : l; //then join rows else join characters
w = l.indexOf('\n') + 1; //calculate row length
// It would be possible to calculate player position with `l.indexOf(1)` but that's 7 bytes longer.
// It would be possible to count gold with `l.split(2).length - 1` but that's 11 bytes longer.
l = l.split(''); //convert to character array
l.w = w; //store width
l.c = l.d = l.p = 0; //initialize gold count, player walking direction, points
return l
}
// 110 bytes
var initLevel = function(l)
{
for (var i = g = []; i < l.length; )
{
l[i] & 8 && //if found a ghost then
g.push({ //append to the array of ghosts
x: i, //ghost position
d: 0 //ghost walking direction (0 = north)
});
if (l[i] & 1) l.x = i; //store player position
l.c += l[i++] == 2 //count gold
}
return g
}
// 136 bytes
var loadSprites = function(t, f) //theme, filename with $1 placeholder
{
for (var i in t)
with (new Image()) //new is required in IE
{
alt = i;
onload = function()
{
t[this.alt] = getOuterHTML(this)
}
src = t[i].replace(/.*"(.*)".*/, f)
}
}
// 88 bytes
var renderLevel = function(l, t) //level object, optional theme object
{
for (var c, h = '', x = 0; x < l.length; x++)
h += t && t[c = l[x] & 8 || l[x]] //ghosts can sit on gold, render the ghost only
? t[c] : c; //use theme or original character (e.g. the newline)
return h
}
// 129 bytes
var updatePlayer = function(l, k)
{
l[l.x] = 0;
l.p += l[l.x += l.d = k - 37 >> 2 || l[l.x + (k = k % 2 ? k - 38 : (k - 39) * l.w)] & 4 ? l[l.x + l.d] & 4 ? 0 : l.d : k] == 2;
l.e |= l[l.x] & 8;
l[l.x] = 1
}
// 134 bytes
var updateGhosts = function(a, l, g, d)
{
for (g in a)
l[a[g].x] &= 7; //remove all ghosts first
for (g in a)
{
g = a[g];
d = g.d % 4;
d = d % 2 ? d - 2 : (d - 1) * l.w; //calculate walking direction
l[g.x + d] & 4 //if walking into a wall
? g.d++ //rotate ghost by 90 degree
: l.e |= 1 & l[ //else check if hitting the player
g.x += d]; //and walk
l[g.x] |= 8 //place ghost
}
}
var levels = [parseLevel([
'44444444444', //no ghosts
'42222222224',
'42444242424',
'42412242424',
'42444242424',
'42222242224',
'44444444444']),
parseLevel([
'4444444444444', //1 ghost
'4222224222224',
'4244424244424',
'4242228222424',
'4242424442424',
'4242421242424',
'4242444242424',
'4242222222424',
'4244424244424',
'4222224222224',
'4444444444444']),
parseLevel([
'444444444444444', //2 ghosts
'424222222222224',
'424244444242444',
'422222222222224',
'424244444242424',
'424242212242424',
'424242444442424',
'422222222222224',
'444242444442424',
'482222222222484',
'444444444444444']),
parseLevel([
'4444444444444444444', //classic with 2 ghosts
'4222242228222422224',
'4244242444442424424',
'4242222222222222424',
'4242442440442442424',
'4222222408042222224',
'4242442444442442424',
'4242222221222222424',
'4244242444442424424',
'4222242222222422224',
'4444444444444444444']),
parseLevel([
'444444444444444', //3 ghosts
'422222282222224',
'424444424444424',
'424222424822424',
'424242424242424',
'422242212242224',
'424242424242424',
'424228424222424',
'424444424444424',
'422222222222224',
'444444444444444']),
parseLevel([
'4444444444444444444', //5 ghosts
'4222222248222222224',
'4244444242444442444',
'4242222282222222224',
'4242444442444442424',
'4242422242482222424',
'4242424242424244424',
'4222222222222228224',
'4244424242424242424',
'4242222842422242424',
'4242444442444442424',
'4222222222222222424',
'4442444442424444424',
'4222222122422222224',
'4444444444444444444'])];
var theme = {
0: '<span class="air">\u2219</span>', //doesn't need to be checked
1: '<span class="player">\u263B</span>', //can be checked with &1
2: '<span class="gold">\u2219</span>', //can be checked with &2
4: '<span class="wall">\u25A1</span>', //can be checked with &4
8: '<span class="ghost">\u00A4</span>', //can be checked with &8 or >7
'\n': '<br>' //required for IE
}
loadSprites(theme, 'sprite-$1.gif'); //load optional GIF files from the same directory
document.onkeydown = function(e)
{
level.keyCode = (e || window.event).keyCode
}
var ghosts, level, number = 0;
window.setInterval(function()
{
if (!level && levels[number])
ghosts = initLevel(level = levels[number++]);
if (level.p >= level.c)
{
if (level.p < level.c-- + 4) //wait a few moments before loading next level
return;
level = 0 //unload current level when won
}
if (!level || level.e) //stop updating when lost or won
return;
updatePlayer(level, level.keyCode || 0);
updateGhosts(ghosts, level);
getFirstElement('PRE').innerHTML = renderLevel(level, theme);
getFirstElement('#points').innerHTML = level.p;
getFirstElement('H2').innerHTML = level.e ? 'GAME OVER!' : level.p < level.c ? '' : 'YOU WIN!'
}, 250);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment