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

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

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

  如下是效果图:

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

  这个拖箱子游戏做了移动端的适配, 我使用了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 ;

                        };

 

  所有的代码在这里:

JavaScript写一个小乌龟推箱子游戏
<!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;

        width:50px;

        height:50px;

        box-sizing: border-box;

    }

    .block{

        position: absolute;

        background-image: url(imgs/wall.png);

        width:50px;

        height:50px;

        box-sizing: border-box;

    }

    .box{

        position: absolute;

        background: #fbd500;

        width:50px;

        height:50px;

        background-image: url(imgs/box.png);

    }

    .target{

        position: absolute;

        background: url(imgs/target.jpg);

        background-size: 50px 50px;;

        width:50px;

        height:50px;

        box-sizing: border-box;

    }

    #person{

        background-image: url(imgs/person.png);

        width: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 : 打开

  参考:

    别人写的推箱子:打开

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

 

你可能感兴趣的:(JavaScript)