zoukankan      html  css  js  c++  java
  • 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() ) {
                        $(window).on("swipeLeft",function() {
                            _this.step("left");
                        }).on("swipeRight",function() {
                            _this.step("right");
                        }).on("swipeUp",function() {
                            _this.step("top");
                        }).on("swipeDown",function() {
                            _this.step("bottom");
                        });
                        mobileDOM();
    
                        $(".arrow-up").tap(function() {
                            _this.step("top");
                        });
                        $(".arrow-down").tap(function() {
                            _this.step("bottom");
                        });
                        $(".arrow-left").tap(function() {
                            _this.step("left");
                        });
                        $(".arrow-right").tap(function() {
                            _this.step("right");
                        });
                    }else{
                        $(window).on("keydown", function(ev) {
                            var state = "";
                            switch( ev.keyCode ) {
                                case 37 :
                                    state = "left";
                                break;
                                case 39 :
                                    state = "right";
                                break;
                                case 38 :
                                    state = "top";
                                break;
                                case 40 :
                                    state = "bottom";
                                break;
                            };
                            _this.step(state)
                        });
                    };

      因为要保存用户的当前关卡, 也额外引用了jQuery-cookies插件, 每一次闯关成功,我们就保存一次当前的闯关记录, 当用户不想玩或者别的原因关闭了浏览器, 过几天想重新玩的时候可以继续玩;

                            if( G.now+1 > G.level.length-1 ) {
                                alert("闯关成功");
                                return ;
                            }else{
                                //如果可用的等级大于当前的等级,就把level设置进去;
                                if( G.now+1 > parseInt( $.cookie('level') || 0 )) {
                                    $.cookie('level' , G.now+1 , { expires: 7 });
                                };
                                start( G.now+1 );
                                return ;
                            };

      所有的代码在这里:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css">
        <link rel="stylesheet" href="http://sqqihao.github.io/games/rusBlock/libs/Tiny-Alert/css/zepto.alert.css"/>
        <script src="libs/jquery-1.9.1.min.js"></script>
        <script src="libs/handlebars.js"></script>
        <script src="libs/jquery-cookie.js"></script>
        <script src="http://sqqihao.github.io/games/rusBlock/libs/Tiny-Alert/js/zepto.alert.js"></script>
        <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>
        <script>
            (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;
                    }
                }
            })();
        </script>
    </head>
    <style>
        #game{
            display: none;
        }
        #house{
            position: relative;
        }
        .bg{
            position: absolute;
            50px;
            height:50px;
            box-sizing: border-box;
        }
        .block{
            position: absolute;
            background-image: url(imgs/wall.png);
            50px;
            height:50px;
            box-sizing: border-box;
        }
        .box{
            position: absolute;
            background: #fbd500;
            50px;
            height:50px;
            background-image: url(imgs/box.png);
        }
        .target{
            position: absolute;
            background: url(imgs/target.jpg);
            background-size: 50px 50px;;
            50px;
            height:50px;
            box-sizing: border-box;
        }
        #person{
            background-image: url(imgs/person.png);
            50px;
            height:50px;
            position: absolute;
        }
        #person.up{
            background-position: 0 0;
        }
        #person.right{
            background-position:-50px  0 ;
        }
        #person.bottom{
            background-position:-100px 0 ;
        }
        #person.left{
            background-position:-150px 0 ;
        }
        /*移动端的DOM*/
        .operate-bar{
            font-size:30px;
        }
        .height20percent{
            height:30%;
        }
        .height30percent{
            height:30%;
        }
        .height40percent{
            height:40%;
        }
        .height100percent{
            height:100%;
        }
        .font30{
            font-size:30px;
            color:#34495e;
        }
    </style>
    <body>
        <div id="select">
            <div class="container">
                <div class="row">
                    <p class="text-info">
                        已经解锁的关卡:
                    <p id="level">
                    </p>
                    </p>
                    <button id="start" class="btn btn-default">
                        开始游戏
                    </button>
                </div>
            </div>
        </div>
        <div id="game" class="container">
            <div class="row">
                <button onclick="location.reload()" class="btn btn-info" >
                    返回选择关卡重新
                </button>
                <div id="house">
                </div>
            </div>
        </div>
    
        <script>
            G = {
                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}
                        ]
                    }
                ],
                //map data
                mapData : (function() {
                    var data = {};
                    return {
                        get: function () {
                            return data;
                        },
                        set: function (arg) {
                            data = arg;
                        },
                        //穿进来的数据在界面中是否存在;
                        collision: function (x, y) {
                            if( data.state[y][x] === 1)return true;
                            return false;
                        },
                        collisionBox : function(x,y) {
                            for(var i= 0, len= data.box.length; i< len; i++) {
                                if( data.box[i].x === x&& data.box[i].y === y)return data.box[i];
                            };
                            return false;
                        }
                    }
                })(),
                view : {
                    initMap : function(map) {
                        document.getElementById("house").innerHTML = Handlebars.compile( document.getElementById("tpl").innerHTML )( map );
                    },
                    initPerson : function(personXY) {
                        var per = document.createElement("div");
                        per.id = "person";
                        G.per = per;
                        document.getElementById("house").appendChild(per);
                        per.style.left = 50* personXY.x+"px";
                        per.style.top = 50* personXY.y+"px";
                    },
                    initBox : function(boxs) {
                        for(var i=0;i<boxs.length; i++) {
                            var box = document.createElement("div");
                            box.className = "box";
                            G.box = box;
                            document.getElementById("house").appendChild(box);
                            box.style.left = boxs[i].x*50 + "px";
                            box.style.top = boxs[i].y*50 + "px";
                        };
                    },
                    deleteBox : function() {
                        var eBoxs = document.getElementsByClassName("box");
                        var len = eBoxs.length;
                        while( len-- ) {
                            eBoxs[len].parentNode.removeChild( eBoxs[len] );
                        };
                    }
                },
                /*
                * 0;向上
                * 1:向右
                * 2:向下
                * 3:向左
                * */
                direction : 0,
                step : function(xy) {
                    //这里面要做很多判断
                    /*包括:
                     用户当前的方向和以前是否一样,如果不一样要先转头;
                     如果一样的话,判断前面是否有石头, 是否有箱子;
                         如果前面有墙壁或者
                         前面有箱子,而且箱子前面有墙壁就return
                     把人物往前移动
                     如果人物的位置上有一个箱子,把箱子也移动一下;
                     */
                    var mapData = this.mapData.get();
                    //对参数进行处理;
                    if ( typeof xy === "string" ) {
                        var x = 0, y = 0, xx = 0, yy = 0;
                        switch( xy ) {
                            case "left" :
                                    if(this.direction==0){
                                        x = -1;
                                        xx = -2;
                                    }else{
                                        x = 0;
                                    };
                                this.direction = 0;
                                break;
                            case "top" :
                                    if(this.direction===1){
                                        y = -1;
                                        yy = -2
                                    }else{
                                        y = 0;
                                    };
                                    this.direction = 1;
                                break;
                            case "right" :
                                    if(this.direction === 2) {
                                        x = 1;
                                        xx = 2;
                                    }else{
                                        x = 0;
                                    };
                                this.direction = 2;
                                break;
                            case "bottom" :
                                    if(this.direction ===3 ) {
                                        y = 1;
                                        yy = 2;
                                    }else{
                                        y = 0;
                                    };
                                this.direction = 3;
                        };
                        //如果是墙壁就不能走
                        if( this.mapData.collision(mapData.person.x + x, mapData.person.y+y) ) {
                            return;
                        };
                        //如果碰到的是箱子, 而且箱子前面是墙壁, 就return
                        if( this.mapData.collisionBox(mapData.person.x+x, mapData.person.y+y) &&  this.mapData.collision(mapData.person.x+xx, mapData.person.y+yy)) {
                            return;
                        };
                        if( this.mapData.collisionBox(mapData.person.x+x, mapData.person.y+y) &&  this.mapData.collisionBox(mapData.person.x+xx, mapData.person.y+yy)) {
                            return
                        }
                        //mapData.x+xx, mapData.y+yy
                        mapData.person.x = mapData.person.x + x;
                        mapData.person.y = mapData.person.y + y;
    
                        this.per.style.left = 50* mapData.person.x+"px";
                        this.per.style.top = 50* mapData.person.y+"px";
                        this.per.className = {
                            0:"up",
                            1:"right",
                            2:"bottom",
                            3:"left"
                        }[this.direction];
                        var theBox = {};
                        if(theBox = this.mapData.collisionBox(mapData.person.x, mapData.person.y)) {
                            theBox.x = mapData.person.x+x;
                            theBox.y = mapData.person.y+y;
                            this.view.deleteBox();
                            this.view.initBox(mapData.box);
                            this.testSuccess();
                        };
                        //如果碰到了箱子,而且箱子前面不能走就return, 否则就走箱子和人物;
                    };
                },
                /*
                * return Boolean;
                * */
                //遍历所有的box,如果在box中的所有x,y在地图中对应的值为3,全部通过就返回true
                testSuccess : function() {
                    var mapData = this.mapData.get();
                    for(var i=0; i<mapData.box.length; i++) {
                        if(mapData.state[mapData.box[i].y][mapData.box[i].x] != 3) {
                            return false;
                        };
                    };
                    $.dialog({
                        content : '游戏成功, 进入下一关!',
                        title : 'alert',
                        ok : function() {
                            if( G.now+1 > G.level.length-1 ) {
                                alert("闯关成功");
                                return ;
                            }else{
                                //如果可用的等级大于当前的等级,就把level设置进去;
                                if( G.now+1 > parseInt( $.cookie('level') || 0 )) {
                                    $.cookie('level' , G.now+1 , { expires: 7 });
                                };
                                start( G.now+1 );
                                return ;
                            };
                        },
                        cancel : function(){
                            location.reload();
                        },
                        lock : true
                    });
                },
                //这里面需要处理 map, 人物数据, box数据
                init : function() {
                    //更新地图;
                    //this.level[0].state
                    this.view.initMap( this.mapData.get().state  );
                    this.view.initPerson( this.mapData.get().person );
                    this.view.initBox( this.mapData.get().box );
                    //this.person = this.factory.Person(0,0);
                    //this.box = this.factory.Box([{x:0,y:1},{x:1,y:1},{x:0,y:2},{x:1,y:2}]);
                    if( this.hasBind ) {
                        return
                    };
                    this.hasBind = true;
                    this.controller();
                },
                controller : function() {
                    function mobileDOM() {
                        var mobileDOMString = '
                            <div class="navbar-fixed-bottom height20percent operate-bar"  >
                                <div class="container height100percent">
                                    <div class="row text-center height100percent">
                                        <div class="height40percent arrow-up">
                                            <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
                                        </div>
                                        <div  class="height30percent">
                                            <div class="col-xs-6 arrow-left">
                                                <span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
                                            </div>
                                            <div class="col-xs-6 arrow-right">
                                                <span class="glyphicon glyphicon-arrow-right" aria-hidden="true"></span>
                                            </div>
                                        </div>
                                        <div  class="height30percent arrow-down">
                                            <span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            ';
                            +function addDOM() {
                                $("#game").append( mobileDOMString );
                            }();
                    };
                    var _this = this;
                    if( window.util.isMobile() ) {
                        $(window).on("swipeLeft",function() {
                            _this.step("left");
                        }).on("swipeRight",function() {
                            _this.step("right");
                        }).on("swipeUp",function() {
                            _this.step("top");
                        }).on("swipeDown",function() {
                            _this.step("bottom");
                        });
                        mobileDOM();
    
                        $(".arrow-up").tap(function() {
                            _this.step("top");
                        });
                        $(".arrow-down").tap(function() {
                            _this.step("bottom");
                        });
                        $(".arrow-left").tap(function() {
                            _this.step("left");
                        });
                        $(".arrow-right").tap(function() {
                            _this.step("right");
                        });
                    }else{
                        $(window).on("keydown", function(ev) {
                            var state = "";
                            switch( ev.keyCode ) {
                                case 37 :
                                    state = "left";
                                break;
                                case 39 :
                                    state = "right";
                                break;
                                case 38 :
                                    state = "top";
                                break;
                                case 40 :
                                    state = "bottom";
                                break;
                            };
                            _this.step(state)
                        });
                    };
                }
            };
    
            function start( level ) {
                G.now = level;
                G.mapData.set(G.level[level] );
                G.init();
                $("#game").show();
                $("#select").hide();
            };
    
            function init() {
                var cookieLevel = $.cookie('level') || 0;
                start( cookieLevel );
            };
            $("#start").click(function() {
                init();
            });
            String.prototype.repeat = String.prototype.repeat || function(num) {
                return  (new Array(num+1)).join( this.toString() );
            };
    
            window.onload = function() {
                var cookieLevel = $.cookie('level') || 0;
                $("#level").html( function() {
                    var index = 0;
                   return "<a href='###' class='btn btn-info' onclick='start({{i}})'>关卡</a>&nbsp;&nbsp;&nbsp;&nbsp;".repeat((parseInt($.cookie('level')) || 0)+1).replace(/{{i}}/gi, function() {
                       return index++;
                   })
                });
            }
        </script>
    </body>
    </html>
    View Code

      游戏一共有6关, 每一关成功通过即可解锁下一关, 地图的话其实可以多找些的,哈哈;

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

      参考:

        别人写的推箱子:打开

        妙味的杜鹏老师的推箱子视频:打开

  • 相关阅读:
    OpenGL模板 Mac Cmake OpenGL(Glut) Template
    CodeForces 277A Learning Languages (并检查集合)
    Linux netstat订购具体解释
    POJ 1936 All in All
    他的第一个NDK的Demo
    [ACM] POJ 2418 Hardwood Species (Trie树或map)
    Swift
    Swift
    Swift
    Swift
  • 原文地址:https://www.cnblogs.com/diligenceday/p/4604484.html
Copyright © 2011-2022 走看看