原文地址:http://alokmenghrajani.github.com/tron/,这里只是中文解读:)
1、完整代码
<body id=b οnkeyup=e=event οnlοad=
z=c.getContext('2d');
z.fillRect(s=0,0,n=150,x=11325);
setInterval("
0<x%n
&x<n*n
&(z[x+=[1,-n,-1,n][e.which&3]]^=1)
?z.clearRect(x%n,x/n,1,1,s++)
:b.innerHTML='game⬜over:'+s
",9)
><canvas id=c>
上面的代码是经过格式化的,只是为了方便解读,无法运行。在最下面有原始格式的代码,在支持HTML5的浏览器中运行就可以观察效果了。看起来像是一个简化版的贪吃蛇。
2、简化body的id
为body的id属性赋值,这样就可以利用b.innerHTML代替document.body.innerHTML,另外双引号也是被省略掉的,因为浏览器会自动补全的。
3、键盘事件
用onkeyup代替onkeydown,省略2个字符,并把默认参数event赋给变量e,这样在后面的代码中就可以使用这个全局变量e了。
4、代码初始化
onload中的代码其实应该放在<script>中的,但是一切都是为了节省代码量:)
5、设备关联文
把设备关联文赋给变量z,并在后面的代码以方括号的形式访问z中的属性
6、背景绘制
游戏的背景色是默认的黑色,前景色是白色,在绘制的时候,顺便初始化了三个变量的值n、x、s。虽然这里绘制的矩形是150×11325,但实际的场景看起来只是150×150,这和Canvas的默认高度可能。n用来计算场景的大小,x用来设置当前位置。
7、主循环
通过函数setInterval,每隔9毫秒执行一次引号中的代码。
8、判定当前位置的有效性
在第六条中我们已经说明,x代表当前位置,当前位置必须大于零,并且要小于横向的最大长度150(由变量n表示),并且,x的最大长度必须小于矩形的最大值n*n。
9、利用键盘事件更新当前位置
操作的时候我们需要利用四个按键i、j、k、l,它们所对应的ascii都会和数字3进行与操作,其结果范围会是0-3,0-3恰好就是数组[1, -n, -1, n]的下标索引范围。这样一来,x的值就会从当前位置往上下左右四个方向移动,也就是说[1, -n, -1, n]对应【右、上、左、下】。
10、碰撞检测
表达式z[x...]^=1,其中“x...”的结果就是当前位置,参考第九条说明。第一次访问z[x...]时,其中的值总是undefined。当我们用z[x...]与1进行“亦或”操作时,如果z[x...]曾经被赋过初始值(1),再次访问后,计算结果就为0(碰撞),如果是首次访问,结果为1(未碰撞)。(Newbility啊~~~)
11、绘制轨迹
未碰撞时,我们需要画出经过的估计,利用当前位置x就可以计算出水平和垂直坐标,然后清除一个像素点(白)。最后的变量s是用来计算分值的。
12、Game Over
碰撞时,显示分值。显示“game over”的时候,需要注意中间的空格,由于代码处于属性中,并且没有引号限定,所以不可以使用空格,Unicode是OK的(空格=>U+00A0=>⬜)。为了方便,下面的代码把"game over"改成"game_over"。
13、HTML5的Canvas
定义我们的场景元素,canvas。
最终可运行的代码:
<body id=b οnkeyup=e=event οnlοad=z=c.getContext('2d');z.fillRect(s=0,0,n=150,x=11325);setInterval("0<x%n&x<n*n&(z[x+=[1,-n,-1,n][e.which&3]]^=1)?z.clearRect(x%n,x/n,1,1,s++):b.innerHTML='game_over:'+s",9)><canvas id=c>