分享一个js小游戏--贪吃蛇

上周看到一个大腿用20行代码写了贪吃蛇游戏,觉得好屌,分享一下他的代码。
原文地址戳这👉: 原文链接
废话不多说,看代码

游戏场景设计

<!doctype html>  
<html>  
<body>  
    <canvas id="can" width="400" height="400" style="background: Black"></canvas>  
    <script>  
        var sn = [ 42, 41 ], dz = 43, fx = 1, n, ctx = document.getElementById("can").getContext("2d");  
        function draw(t, c) {  
            ctx.fillStyle = c;  
            ctx.fillRect(t % 20 * 20 + 1, ~~(t / 20) * 20 + 1, 18, 18);  
        }  
        document.onkeydown = function(e) {  
            fx = sn[1] - sn[0] == (n = [ -1, -20, 1, 20 ][(e || event).keyCode - 37] ) ? fx : n  
        };  
        !function() {  
            sn.unshift(n = sn[0] + fx);  
            if (sn.indexOf(n, 1) > 0 || n<0||n>399 || fx == 1 && n % 20 == 0 || fx == -1 && n % 20 == 19)  
                return alert("GAME OVER");  
            draw(n, "Lime");  
            if (n == dz) {  
                while (sn.indexOf(dz = ~~(Math.random() * 400)) >= 0);  
                draw(dz, "Yellow");  
            } else  {
                draw(sn.pop(), "Black");  
            }
            setTimeout(arguments.callee, 1000);  
        }();  
    </script>  
</body>  
</html> 

一眼是不是没杂看明白,没关系,用浏览器打开,先玩一把,是不是感觉挺溜的。

游戏场景.png

下面一段一段来看看代码都干哈的。
首先是生成一个400x400的画布:图1

画布.png
<canvas id="can" width="400" height="400" style="background: Black"></canvas>

这是整个游戏场景,蛇体,蛇移动和食物都在这里。设计单位小块尺寸20x20,这样整个画布一共就有20X20=400个正方小块,如图2

400格.png

只需加入这段js

<script>
        var ctx = document.getElementById("can").getContext("2d");  
        function draw(t, c) {  
            ctx.fillStyle = c;  
            ctx.fillRect(t % 20 * 20 + 1, ~~(t / 20) * 20 + 1, 18, 18);  
        } 
        !function(){
            for (var i = 0; i < 400; i++) {
                draw(i, 'lime')
            } 
        }();
 </script>

首先声明canvas的上下文,然后声明绘制单元格函数,fillstyle是颜色属性,fillRect绘制一个矩形,四个参数,分别是:1.离原点的x方向距离;2.离原点的y方向的距离;3.长;4.宽。
长和宽只有18,不是20,是为了单元格之间流出1个长度的空隙,400个小块从左到右,从上到下依次对应0-399。
这里的函数draw是整个游戏绘制蛇体,食物的基础函数。执行一次绘制一个小方块,敲黑板了,功能设计关键的地方之一:

  • 用一个数组表示蛇体,数组的一项代表蛇体的一块,通过draw绘制;
  • 蛇体移动,通过数组头部增加一项,尾部去除一项实现;
  • 蛇吃到食物,蛇体长度增加一块,通过数组增加一项实现;

从新来看下代码

<script>  
        var sn = [ 42, 41 ],  ctx = document.getElementById("can").getContext("2d");  
        function draw(t, c) {  
            ctx.fillStyle = c;  
            ctx.fillRect(t % 20 * 20 + 1, ~~(t / 20) * 20 + 1, 18, 18);  
        }  
         ...
        !function() {  
            sn.unshift(n = sn[0] + fx);  
           ...
            draw(n, "Lime");  
            if (n == dz) {  
               ...
            } else  {
                draw(sn.pop(), "Black");  
            }
            setTimeout(arguments.callee, 1000);  
        }();  
 </script> 

每秒钟往数组头部添加一项,尾部去除一项(吃到食物时除外)
往数组头部里添加的一项是sn[0] + fx,这个fx就是蛇体不同移动方向的标识。

蛇体移动控制

前面说过画布的400个小块分别对应0-399,那蛇体向右移动一步就是+1,向左就是-1,向上就是-20,向下就是+20。
fx的控制绑定在键盘事件,左上右下方向键的keyCode分别为[37,38,39,40],结合这两点就可以理解这段代码了

document.onkeydown = function(e) {  
    fx = sn[1] - sn[0] == (n = [ -1, -20, 1, 20 ][(e || event).keyCode - 37] ) ? fx : n  
 };

蛇吃食物控制

sn.unshift(n = sn[0] + fx);
if (n == dz) {  
    while (sn.indexOf(dz = ~~(Math.random() * 400)) >= 0);  
    draw(dz, "Yellow");  
}

游戏开始时,n = 42 + 1,dz = 43。
此时执行上面的代码,while里的表达式是生成一个0-400的随机数,且不在蛇体数组内,即在蛇体外随机位置生成一个食物块。

游戏结束条件

游戏结束条件有两个:
1.蛇头碰到蛇体;
2.蛇头碰到四壁;
满足一个即可。
sn.indexOf(n, 1) > 0 || n<0||n>399 || fx == 1 && n % 20 == 0 || fx == -1 && n % 20 == 19

总结

一开始看完,真觉得原文作者程序设计的很好,分享出来给更多的人学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,501评论 25 707
  • 53.计算字符 在字符串中获取字符值的数量, 可以使用字符串字符属性中的计数属性: let unusualMena...
    无沣阅读 1,068评论 0 4
  • 最近发生的事,有的时候甚至挡住了我内心所有的光。冒出来的想法让自己都吓了一跳。那时觉得要坚守人生的底线,有的时候真...
    夜缨阅读 317评论 0 1
  • 2、入职培训 我叫秦式微,今年22岁,最近正在找工作。前几日刚刚通过了肯德基的面试,又经历了三天做牛做马的日子,终...
    赵羞涩阅读 1,299评论 0 0
  • CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,AFNetW...
    _浅墨_阅读 11,228评论 6 20