首页 > 网站 > WEB开发 > 正文

JavaScript写一个小乌龟推箱子游戏

2024-04-27 14:07:45
字体:
来源:转载
供稿:网友

javaScript写一个小乌龟推箱子游戏

  推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频实例

  推箱子游戏的在线DEMO : 打开

  如下是效果图:

  这个拖箱子游戏做了移动端的适配, 我使用了zeptotouch模块, 通过手指滑动屏幕就可以控制乌龟走不同的方向;

  因为推箱子这个游戏比较简单, 直接用了过程式的方式写代码, 模块也就是两个ViewModel, 剩下就是用户的事件Controller, 用户每一次按下键盘的方向键都会改变数据模型的数据,然后重新生成游戏的静态html, 然后用innerHTML方式插入到界面, 自动生成DOM节点;

  游戏的关卡模型就是数据, 我把每一关的数据分为三块

  1.   地图数据,二维数组(地图数据包括板砖, 箱子要去的目标位置, 空白的位置)
  2.   箱子数据,一维数组(箱子的初始位置)
  3.   小乌龟的数据,json对象

  每一个关卡都有对应的游戏关卡数据, 模拟的数据如下:

            level: [                {                    //0是空的地图                    //1是板砖                    //3是目标点                    state:[                        [0,0,1,1,1,0,0,0,0],                        [0,1,1,3,3,1,0,0,0],                        [0,1,0,0,0,0,1,0,0],                        [0,1,0,0,0,0,1,0,0],                        [0,1,1,1,1,1,1,0,0]                    ],                    person: {x : 2, y : 2},                    box: [{x:3, y : 2},{x:4,y:2}]                },                //第二关                {                    //0是空的地图                    //1是板砖                    //3是目标点                    state:[                        [0,1,1,1,1,1,0,0],                        [0,1,0,0,1,1,1,0],                        [0,1,0,0,0,0,1,0],                        [1,1,1,0,1,0,1,1],                        [1,3,1,0,1,0,0,1],                        [1,3,0,0,0,1,0,1],                        [1,3,0,0,0,0,0,1],                        [1,1,1,1,1,1,1,1]                    ],                    person: {x : 2, y : 2},                    box: [{x:3, y : 2}, {x:2,y:5} ,{x:5, y:6}]                    /*                    box : [                        {x:3, y : 1},                        {x:4, y : 1},                        {x:4, y : 2},                        {x:5, y : 5}                    ]                    */                },                //第三关                {                    //0是空的地图                    //1是板砖                    //3是目标点                    state:[                        [0,0,0,1,1,1,1,1,1,0],                        [0,1,1,1,0,0,0,0,1,0],                        [1,1,3,0,0,1,1,0,1,1],                        [1,3,3,0,0,0,0,0,0,1],                        [1,3,3,0,0,0,0,0,1,1],                        [1,1,1,1,1,1,0,0,1,0],                        [0,0,0,0,0,1,1,1,1,0]                    ],                    person: {x : 8, y : 3},                    box: [{x:4, y : 2}, {x:3,y:3} ,{x:4, y:4},{x:5, y:3},{x:6, y:4}]                },                //第四关                {                    //0是空的地图                    //1是板砖                    //3是目标点                    state:[                        [0,1,1,1,1,1,1,1,0,0],                        [0,1,0,0,0,0,0,1,1,1],                        [1,1,0,1,1,1,0,0,0,1],                        [1,0,0,0,0,0,0,0,0,1],                        [1,0,3,3,1,0,0,0,1,1],                        [1,1,3,3,1,0,0,0,1,0],                        [0,1,1,1,1,1,1,1,1,0]                    ],                    person: {x : 2, y : 3},                    box: [{x:2, y : 2}, {x:4,y:3} ,{x:6, y:4},{x:7, y:3},{x:6, y:4}]                },                //第五关                {                    //0是空的地图                    //1是板砖                    //3是目标点                    state:[                        [0,0,1,1,1,1,0,0],                        [0,0,1,3,3,1,0,0],                        [0,1,1,0,3,1,1,0],                        [0,1,0,0,0,3,1,0],                        [1,1,0,0,0,0,1,1],                        [1,0,0,1,0,0,0,1],                        [1,0,0,0,0,0,0,1],                        [1,1,1,1,1,1,1,1]                    ],                    person: {x : 4, y : 6},                    box: [{x:4, y : 3}, {x:3,y:4} ,{x:4, y:5}, {x:5,y:5}]                    /*                     box : [                     {x:3, y : 1},                     {x:4, y : 1},                     {x:4, y : 2},                     {x:5, y : 5}                     ]                     */                },                    //第六关                {                    //0是空的地图                    //1是板砖                    //3是目标点                    state:[                        [0,0,0,0,1,1,1,1,1,1,1,0],                        [0,0,0,0,1,0,0,1,0,0,1,0],                        [0,0,0,0,1,0,0,0,0,0,1,0],                        [1,1,1,1,1,0,0,1,0,0,1,0],                        [3,3,3,1,1,0,0,0,0,0,1,1],                        [3,0,0,1,0,0,0,0,1,0,0,1],                        [3,0,0,0,0,0,0,0,0,0,0,1],                        [3,0,0,1,0,0,0,0,1,0,0,1],                        [3,3,3,1,1,1,0,1,0,0,1,1],                        [1,1,1,1,1,0,0,0,0,0,1,0],                        [0,0,0,0,1,0,0,1,0,0,1,0],                        [0,0,0,0,1,1,1,1,1,1,1,0]                    ],                    person: {x : 5, y : 10},                    box: [                        {x:5,  y:6},                        {x:6,  y:3},                        {x:6,  y:5},                        {x:6,  y:7},                        {x:6,  y:9},                        {x:7,  y:2},                        {x:8,  y:2},                        {x:9,  y:6}                    ]                }            ]

  有一个很重要的东西就是推箱子游戏的主要逻辑:因为小乌龟走的地方只能是空白的区域,而且乌龟前面有墙就不能走, 或者乌龟前面是箱子,就再判断箱子前面是否有墙, 如果没有墙乌龟和箱子都可以走往前走一步,如果有墙就不能走。每一次小乌龟走了都改变地图数据,然后重新生成界面,如此循环, 每一小乌龟走完都要检测地图数据中的箱子数据是否全对上了,对上了就给用户提示, 并进入下一关;

  游戏的模板引擎用了handlebarsJS, 可以去官网看API。 这个是写过的一篇博客,Handlebars的使用方法文档整理(Handlebars.js):打开, 模板内容:

    <script id="tpl" type="text/x-handlebars-template">        {{#initY}}{{/initY}}        {{#each this}}            {{#each this}}                <div class="{{#getClass this}}{{/getClass}}" data-x="{{@index}}" data-y="{{#getY}}{{/getY}}" style="left:{{#calc @index}}{{/calc}};top:{{#calc 1111}}{{/calc}}">                    <!--{{@index}}                    {{#getY}}{{/getY}}                    -->                </div>            {{/each}}            {{#addY}}{{/addY}}        {{/each}}    </script>

  为Handlebars定了几个helper,包括initY, getClass, getY,calc 、、、、,模板引擎主要是辅助的作用, 这边用Handlebars不是很明智啊, 代码的可读性变差了点, 这里面也利用了闭包保存变量, 避免全局变量的污染:

        (function() {            var y = 0;            Handlebars.registerHelper("initY", function() {                y = 0;            });            Handlebars.registerHelper("addY", function() {                y++;            });            Handlebars.registerHelper("getY", function() {                return y;            });            Handlebars.registerHelper("calc", function(arg) {                //console.log(arg)                if(arg!==1111) {                    return 50*arg + "px";                }else{                    return 50*y + "px";                };            });            Handlebars.registerHelper("getClass", function(arg) {                switch( arg ) {                    case 0 :                        return "bg"                    case 1 :                        return "block"                    case 2 :                        return "box"                    case 3 :                        return "target"                };            });            window.util = {                isMobile : function() {                    return navigator.userAgent.toLowerCase().indexOf("mobile") !== -1 || navigator.userAgent.toLowerCase().indexOf("android") !== -1  || navigator.userAgent.toLowerCase().indexOf("pad") !== -1;                }            }        })();

  因为要兼容移动端, 我们要检查是否是手机或者平板,如果是的话,我就添加对应的DOM元素(方向键DOM元素),然后绑定对应的事件, zeptoJS提供了touch模块,我们要去官网去找,然后额外引用进来,打开地址, 然后就可以使用swipeLeft,swipeUp,swipeDown, swipeRight 这几个事件:

                if( window.util.isMobile() ) {
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表