Threes!1k
JS1k entry
by evan
HTML
<canvas id="c"></canvas>
<script>
var a = document.getElementsByTagName('canvas')[0];
var b = document.body;
var d = function(e){ return function(){ e.parentNode.removeChild(e); }; }(a);
// unprefix some popular vendor prefixed things (but stick to their original name)
var AudioContext =
window.AudioContext ||
window.webkitAudioContext;
var requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(f){ setTimeout(f, 1000/30); };
// stretch canvas to screen size (once, wont onresize!)
a.style.width = (a.width = innerWidth) + 'px';
a.style.height = (a.height = innerHeight) + 'px';
var c = a.getContext('2d');
</script>
CSS
html, body { margin: 0; padding: 0; border: 0; }
#c { display: block; } /* kill scrollbars from hell */
JavaScript
// Styles to be set once
b.bgColor="#eee";
c.font='17pt cursive';
c.textAlign="center";
// Some variables I'll want to use later.
E='';
// canvas drawing methods
S='fillStyle';
c.T=c.fillText;
L=function (v,x,y) {
// Set the fill color for rectangle using the current value
// 0,1,2 are listed, otherwise it falls through to W which is white
c[S]=[X,Z,Y][v] || W;
c.fillRect(x,y,40,45);
};
// Colors I use a few times.
V='#000'; // Black
W='#FFF'; // White
X='#DDD'; // Dark gray
Y='#F68'; // Pink
Z='#7CF'; // Blue
M=Math;
R=M.random;
// Highest starts out at 3
H = 3;
// Pick an upcoming (next) tile
U = G();
// get a tile value of less than or equal to the highest.
// We also use this a lot for drawing random numbers.
// A value for the first argument triggers alternate behavior.
function G(a) {
// Draw a number up to 3.
g = ~~(R()*3)+1;
// If the number is 3, and the highest number is lower than 3,
// flip a (weighted) coin to decide whether we should double the value.
// This gives us increasingly slim opportunities to spawn high value tiles.
// I haven't spent a TON of time balance-testing this. Seems fairly OK.
while (g > 2 && g < H && R() < .4) {
g*=2;
}
return a ? g-2 : g;
}
// rotate the field t through 4 rotations and squish on the r'th rotation (1,2,3,4)
// returns how many squishes it did OR how many were possible
// r: which rotation to squish on, or undefined to run a test on all directions
// Also draws the field- probably wastes CPU, but saves several bytes for another loop
function O(r) {
// reset the flag that tracks whether we performed any squishes
// To save bytes we're not going to return s at the end, just access it globally
p=s=0;
// rotate through 4 sides
for (k=1; k<5; k++) {
// Do the squish calculations before the r'th rotation-
// or always if we're not saving squishes
if (k==r || !r) {
...