Skip to content

Instantly share code, notes, and snippets.

@iznax
Created March 7, 2012 06:54
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iznax/1991541 to your computer and use it in GitHub Desktop.
Save iznax/1991541 to your computer and use it in GitHub Desktop.
Mini Frogger

Mini Frogger

This is a miniature version of the classic Frogger arcade game. It is written in the smallest amount of JavaScript that I could squeeze it. The core logic of the game is a single function that fits in less than 140 characters.

Play Game

Display

#OO##OO##OO#   O Lilly pad
~~==~~~~==~~   ~ Water
~~~~====~~~~   = Log
::::::::::::   : Grass
............   . Road
..##...##...   # Truck
.....@......   @ Frog  You
::::::::::::   : Sidewalk

Controls

Left  Arrow = Move left
Right Arrow = Move right
Up    Arrow = Move up
Down  Arrow = Move down

The Update Function

The update function is the core logic of the game. It processes all game data for the next display frame. This is the function that I am trying to minimize. I realize it's cheating a bit to ignore the size of the outer script, but it's the benchmark I have chosen since the display mechanism is arbitrary and less important, for my purposes.

Compact Version ( 123 characters )

The update function can be stripped of white-space and formatted to in less than 140 characters of text which is small enough for tweeting etc.

Information

See my other games:

Mini Tetris

Mini Invaders

var Update=function(g,i)
{
// For each line in the game board.
for (i=H; --i;)
// If time cycle is 1/4 or line is below middle sidewalk.
if (!(t%4) | i>5)
//{
// Read the current bits for log/car traffic
g=r[i],
// Shift (odd) rows left with wrap-around
// Shift (even) rows right with wrap-around
r[i] = i&1?(g&1)<<V|g>>1:g>>V&1|g<<1;
//}
// If player has not reach (0,1,2,3) end of death animation advance timer.
// otherwise reset the player to the bottom middle of the screen.
p<3?t++:(p=0,x=M,y=B);
// Advance the player animation if already dead or newly hit by traffic.
p+=p?1:r[y]>>x&1;
}
function(g,i){for(i=H;--i;)if(!(t%4)|i>5)g=r[i],r[i]=i&1?(g&1)<<V|g>>1:g>>V&1|g<<1;p<3?t++:(p=0,x=M,y=B);p+=p?1:r[y]>>x&1}
The "WTH" Public License
Copyright (C) 2012 Paul Isaac
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.
#. You can do whatever-the-heck you like with this code.
{
"name": "MiniFrogger",
"description": "Mini version of Frogger game in less than 140 bytes",
"keywords": [
"game",
"javascript",
"frogger",
"arcade"
]
}
<html>
<style>body{ font-family: monospace; font-size: 20px}</style>
<div id="out"></div>
</html>
<script>
var W=16,R=W-1,M=W/2;
var H=12,B=H-1;
var V=18; // View size bits to wrap-around?
var Z = 0x6666; // Top line pattern
var x=M,y=B; // Player position x,y
var p=0; // Player animation
var t=0; // Time counter
// Water logs and car traffic
var r=[0,0x0e38f,0x38f3c,0x383e0,0x39e3c,0,85,1048,31+(63<<9),85<<8,2048|9,0];
function Input(k)
{
// Ignore key if player is dead.
k *= !p;
// Move left/right?
x -= k==37 & x>0;
x += k==39 & x<R;
// Move up/down?
y -= k==38 & ((y==1&Z>>x) | y>1);
y += k==40 & y<B;
// Check if you hop into danger?
p+=r[y]>>x&!p;
}
var Update=function(g,i)
{
for (i=H; --i;)
if (!(t%4) | i>5)
//{
g=r[i],
r[i] = i&1?(g&1)<<V|g>>1:g>>V&1|g<<1;
//}
p<3?t++:(p=0,x=M,y=B);
p+=p?1:r[y]>>x&1;
}
function Draw()
{
var view = "";
for (var j=0; j<H; j++)
{
for (var i=0; i<W; i++)
view += "#O~=:.#@X%%"[i==x&j==y?p+7:
y?j?2+(j<5?!(r[j]&1<<i):2+!!r[j]+(j>5?(r[j]&1<<i)>0:0)):Z>>i&1:1];
view += "<br>";
}
document.getElementById('out').innerHTML = view;
}
// IE requires implicit 'event' parameter?
document.onkeydown = function()
{
Input(event.keyCode);
Draw();
}
function Main()
{
Update(0,0);
Draw();
setTimeout(Main, 300);
}
Main();
</script>
@aemkei
Copy link

aemkei commented Mar 7, 2012

Awesome! I love the concept of JS games that fit into a tweet!

@aemkei
Copy link

aemkei commented Mar 7, 2012

Btw: to make it a valid entry for http://140byt.es you should avoid leaking to the global scope, (such as H, t, V, ...).
But impressive anyway!

Update: This should fix the global scope:

function(g,i,H,t,i,g,V,p,x,M,B,y,r){for(i=H;--i;)if(!(t%4)|i>5)g=r[i],r[i]=i&1?(g&1)<<V|g>>1:g>>V&1|g<<1;p<3?t++:(p=0,x=M,y=B);p+=p?1:r[y]>>x&1}

It's 144 bytes so how do we get rid of 4 chars here?

Update 2: Hmm, when passing the vars as arguments, we have no chance to override them outside.

@iznax
Copy link
Author

iznax commented Mar 7, 2012

You passed g,i, twice in your revision which is 4-chars, but would have to add a large statement to return the changes to p,x,y,r.

@iznax
Copy link
Author

iznax commented Mar 7, 2012

I had to adopt some alternate rules to make an "interactive" script that doesn't spend 30% of the budget on passing constants & state in/out of the function. The rules also don't allow my onkeydown() and draw() functions to exist... so I'm just trying to make some compromises that don't increase the overall size of the script, just to reduce the size of a single function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment