jQuery版推箱子游戏详解和源码

前言

偶然间看到很多用js写游戏的感觉很炫酷的样子,所以就想试试,就看了一些资料和某前端站点的视屏。于是乎就自己动手实践了一下,上推箱子截图

感觉很丑陋,但是功能是实现了。再说貌似大多都是这样的吧,这一关其实还是有点难度的,我做完之后想检测一下下一关正确么,居然还玩了以后才通关。

如果你看到这张图让你想起了你童年的回忆,说明你老了,这里可以试玩一下(很遗憾没有链接地址,最后又源码可以下载)。

css布局

主要考虑的是地图是怎么动态生成的,地图中有灰色的,还有墙,箱子,蓝色,红色背景,人物。先看css代码吧

* {
            padding: 0;
            margin: 0;
        }

        img {
            border: 0;
        }

        #container {
            position: relative;
            margin: 20px auto;
        }

        .pos1 {
            width: 50px;
            height: 50px;
            float: left;
            background: #666;
        }

        .pos2 {
            width: 50px;
            height: 50px;
            float: left;
            background: url(images/wall.png);
        }

        .pos3 {
            width: 50px;
            height: 50px;
            float: left;
            background: red;
        }

        .pos0 {
            width: 50px;
            height: 50px;
            float: left;
            background: blue;
        }

        .box {
            width: 50px;
            height: 50px;
            position: absolute;
            background: url(images/box.png);
        }

        .person {
            width: 50px;
            height: 50px;
            position: absolute;
            background: url(images/person.png);
        }

代码中的pos0/pos1/pos2/pos3/主要是墙,箱子,蓝色红色背景的样式,其中person和box就是人物和箱子的样式,

这里用样式下标来节省部分js代码

其次body中html布局,这里就很简单了,就是一个带id的div,其余的内容均动态生成,因为每个关卡的地图数据都是不一样的。

js代码部分

  1 $(function () {
  2             Game.init($("#container"));//初始化容器
  3         });
  4         var Game = {
  5             gk: [{//关卡
  6                 map: [//地图数据 按照坐标呈现的数组格式
  7                 1, 1, 2, 2, 2, 2, 1, 1,
  8                 1, 1, 2, 3, 3, 2, 1, 1,
  9                 1, 2, 2, 0, 3, 2, 2, 1,
 10                 1, 2, 0, 0, 0, 3, 2, 1,
 11                 2, 2, 0, 0, 0, 0, 2, 2,
 12                 2, 0, 0, 2, 0, 0, 0, 2,
 13                 2, 0, 0, 0, 0, 0, 0, 2,
 14                 2, 2, 2, 2, 2, 2, 2, 2
 15                 ],
 16                 box: [//箱子 坐标点对象
 17                     { x: 4, y: 3 },
 18                     { x: 3, y: 4 },
 19                     { x: 4, y: 5 },
 20                     { x: 5, y: 5 }
 21                 ],
 22                 person: { x: 3, y: 6 }//人物 坐标点对象
 23             },
 24             {
 25                 map: [
 26                 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1,
 27                 1, 1, 1, 1, 2, 0, 2, 2, 0, 0, 2, 1,
 28                 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 2, 1,
 29                 2, 2, 2, 2, 0, 0, 2, 0, 0, 0, 2, 1,
 30                 3, 3, 3, 2, 0, 0, 0, 0, 0, 0, 2, 2,
 31                 3, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2,
 32                 3, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2,
 33                 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2,
 34                 3, 3, 3, 2, 2, 2, 0, 0, 2, 0, 0, 2,
 35                 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 1,
 36                 1, 1, 1, 1, 2, 0, 0, 2, 0, 0, 2, 1,
 37                 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1,
 38                 ],
 39                 box: [
 40                     { x: 8, y: 3 },
 41                     { x: 9, y: 3 },
 42                     { x: 7, y: 4 },
 43                     { x: 6, y: 7 },
 44                     { x: 7, y: 5 },
 45                     { x: 7, y: 8 },
 46                     { x: 8, y: 9 },
 47                     { x: 4, y: 5 },
 48                     { x: 6, y: 6 }
 49
 50                 ],
 51                 person: { x: 3, y: 6 }
 52             }
 53             ],
 54             init: function (oParent) {
 55                 this.oParent = oParent;//此处将外层的对象引进来
 56                 this.iNow = 0;
 57                 this.createMap(this.iNow);
 58             },
 59             createMap: function (iNow) {
 60                 //创建地图 很关键的是 将元素的样式下标和地图的坐标点关联
 61  this.oParent.empty(); document.title = "第" + (iNow + 1) + "关";
 62                 this.newJson = this.gk[iNow];
 63
 64                 this.oParent.css("width", Math.sqrt(this.newJson.map.length) * 50);
 65                 var tempHtml = ‘‘;
 66                 $.each(this.newJson.map, $.proxy(function (i, elem) {
 67                     tempHtml += ‘<div class="pos‘ + elem + ‘"></div>‘;
 68                 }, this));
 69                 this.oParent.append(tempHtml);
 70                 this.createBox();
 71                 this.createPerson();
 72             },
 73             createBox: function () {//布局箱子所在的位置
 74                 $.each(this.newJson.box, $.proxy(function (i, elem) {
 75                     var oBox = $(‘<div class="box"></div>‘);
 76                     oBox.css({ ‘left‘: elem.x * 50, ‘top‘: elem.y * 50 });
 77                     this.oParent.append(oBox);
 78                 }, this));
 79             },
 80             createPerson: function () {//布局人物所在的位置
 81                 var oPerson = $(‘<div class="person"></div>‘);
 82                 var pos = this.newJson.person;
 83                 oPerson.css({ ‘left‘: pos.x * 50, ‘top‘: pos.y * 50 });
 84                 oPerson.data(‘x‘, pos.x);//缓存在oPerson上的数据
 85                 oPerson.data(‘y‘, pos.y);
 86                 this.oParent.append(oPerson);
 87                 this.bindPerson(oPerson);
 88             },
 89             bindPerson: function (oPerson) {//绑定对人物←↑→↓操作
 90                 $(document).keydown($.proxy(function (ev) {
 91                     switch (ev.which) {
 92                         case 37: //←
 93                             oPerson.css(‘backgroundPosition‘, ‘-150px 0‘);
 94                             this.movePerson(oPerson, { x: -1 });
 95                             break;
 96                         case 38: //↑
 97                             oPerson.css("backgroundPosition", "0 0");
 98                             this.movePerson(oPerson, { y: -1 });
 99                             break;
100                         case 39: //→
101                             oPerson.css("backgroundPosition", "-50px 0");
102                             this.movePerson(oPerson, { x: 1 });
103                             break;
104                         case 40: //↓
105                             oPerson.css("backgroundPosition", "100px 0");
106                             this.movePerson(oPerson, { y: 1 });
107                             break;
108                         default:
109                     }
110                 }, this));
111             },
112             movePerson: function (oP, opt) {//移动人物
113                 var xValue = opt.x || 0;
114                 var yValue = opt.y || 0;
115                 var length = Math.sqrt(this.newJson.map.length);
116                 var currentMapIndex = (oP.data(‘x‘) + xValue) + (oP.data(‘y‘) + yValue) * length;
117                 if (this.newJson.map[currentMapIndex] != 2) {//遇到墙的判断
118                     oP.data(‘x‘, oP.data(‘x‘) + xValue);
119                     oP.data(‘y‘, oP.data(‘y‘) + yValue);
120                     oP.css({ "left": oP.data("x") * 50, "top": oP.data("y") * 50 });
121                     $(".box").each($.proxy(function (i, elem) {
122                         //当和箱子发生碰撞时遇到墙的判断
123                         if (this.pz(oP, $(elem)) && this.newJson.map[(oP.data(‘x‘) + xValue) + (oP.data(‘y‘) + yValue) * length] != 2) {
124                             $(elem).css({ ‘left‘: (oP.data(‘x‘) + xValue) * 50, ‘top‘: (oP.data(‘y‘) + yValue) * 50 });
125                             $(".box").each($.proxy(function (j, elem2) {
126                                 if (this.pz($(elem), $(elem2)) && elem != elem2) {
127                                     //当遇到箱子和箱子的的碰撞时同时前面也不是强的判断
128                                     $(elem).css({ ‘left‘: oP.data(‘x‘) * 50, ‘top‘: oP.data(‘y‘) * 50 });
129                                     oP.data(‘x‘, oP.data(‘x‘) - xValue);
130                                     oP.data(‘y‘, oP.data(‘y‘) - yValue);
131                                     oP.css({ "left": oP.data("x") * 50, "top": oP.data("y") * 50 });
132                                 }
133                             }, this));
134                         }
135                         else if (this.pz(oP, $(elem))) {//和墙之间的碰撞
136                             oP.data(‘x‘, oP.data(‘x‘) - xValue);
137                             oP.data(‘y‘, oP.data(‘y‘) - yValue);
138                             oP.css({ "left": oP.data("x") * 50, "top": oP.data("y") * 50 });
139                         }
140                     }, this));
141                 }
142                 this.nextShow();
143             },
144             nextShow: function () {//判断是否赢
145                 var iNum = 0;
146                 //红色区域所在的位置是否全部被箱子所占据
147                 $(".box").each($.proxy(function (i, elem) {
148                     $(".pos3").each($.proxy(function (j, elem1) {
149                         if (this.pz($(elem), $(elem1))) {
150                             iNum++;
151                         }
152                     }, this));
153                 }, this));
154                 if (iNum == this.newJson.box.length) {
155                     this.iNow++;
156                     this.createMap(this.iNow);
157                 }
158             },
159             pz: function (obj1, obj2) { //碰撞检测
160                 var L1 = obj1.offset().left;
161                 var R1 = obj1.offset().left + obj1.width();
162                 var T1 = obj1.offset().top;
163                 var B1 = obj1.offset().top + obj1.height();
164
165                 var L2 = obj2.offset().left;
166                 var R2 = obj2.offset().left + obj2.width();
167                 var T2 = obj2.offset().top;
168                 var B2 = obj2.offset().top + obj2.height();
169                 if (L1 >= R2 || B2 <= T1 || T2 >= B1 || R1 <= L2)
170                 { return false; }
171                 else
172                 { return true; }
173             }
174         };

基本代码中都有注释,应该是可以理解的,具体如果你有疑问那么请留言,我定会回复。

我个人认为其中的精华部分就是首先地图数据的构造用一维数组来确定地图坐标,其中的内容的数据和样式中pos的下标的数据对应起来感觉很赞。

其次是逻辑判断,比如当人物推箱子是发现前面是墙,推箱子遇到箱子时前面也是箱子,此时如果又遇到了墙怎么处理。最后判断输赢就是如果红色区域的位置全部被箱子所占据那么也就

表示通过,进入下一关,当然下一关的数据我是自己随意填充的。如果你有兴趣请自行解决。

结论

这种类似的小游戏重在思路,如果复杂的话就要考虑架构性能等问题了,我猜的。因为没有做大的游戏,如有错误请指出。如果你觉得不错就支持推荐一下。

download PushBox

jQuery版推箱子游戏详解和源码

时间: 2024-08-25 05:07:42

jQuery版推箱子游戏详解和源码的相关文章

Android Widget 开发实例:桌面便签程序的实现详解和源码

桌面便签软件是Android上常用软件的一种,比如比较早的Sticky Note,就曾非常流行,而实际上使用android平台对widget开发的支持,桌面便签类软件是非常易于开发的. 本文通过逐步实现一个简单的桌面便签软件,和大家分享进行widget开发的过程和方法. 同时本程序提供完整的工程源码下载 免费下载地址在 http://linux.linuxidc.com/ 用户名与密码都是www.linuxidc.com 具体下载目录在 /pub/Android源码集锦/2011年/10月/An

13、C#简易版 推箱子游戏(请高手指点)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 推箱子2._0 { class Program { static void Main(string[] args) { #region//1 int y = 5, x = 5; string[,] a = new string[10, 11]{ {

致佳音: 推箱子游戏自动求解算法设计(四)

这一节是本文的核心内容,即推箱子游戏求解算法的设计思路过程 前面已经说过过,判断局面重复的最好标准不是局面完全一致,而是坐标排序相同且角色坐标通行 如下图,角色无论怎么移动,不推动箱子的时候,都能回到原来的位置,算作同一个局面: 再如下图,两个箱子互换位置,结果与没有移动箱子是一样的,所以排序箱子坐标以后一致,还是相同局面 问:有必要判断局面重复吗?是不是只是提升一下效率? 答:不是为了提升效率,而是为了能解出来,如果使用递归,重复的局面反复耗尽堆栈,而队列则耗尽内存 正如上图,反复推这两个箱子

致佳音: 推箱子游戏自己主动求解算法设计(四)

这一节是本文的核心内容,即推箱子游戏求解算法的设计思路过程 前面已经说过过,推断局面反复的最好标准不是局面全然一致,而是坐标排序同样且角色坐标通行 例如以下图.角色不管怎么移动,不推动箱子的时候.都能回到原来的位置.算作同一个局面: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJzbmlwZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast"

推送原理解析 极光推送使用详解

推送原理解析 极光推送使用详解 原军锋 12016.09.22 18:10:07字数 5,705阅读 19,494 推送技术产生场景: --服务器端主动性: 客户端与服务器交互都是客户端主动的, 服务器一般不能主动与客户端进行数据交互, 因为服务器端无法得知客户端的 IP 地址 及 状态; --数据实时性: 如果服务器端有紧急数据要传递给客户端, 就必须主动向客户端发送数据; --基本原理: 使客户端实时获取服务器端消息, Pull 方式, 小周期轮询, 费电费流量; 另一个就是 Push 方式

JQuery中$.ajax()方法参数详解

url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 delete也可以使用,但仅部分浏览器支持. timeout: 要求为Number类型的参数,设置请求超时时间(毫秒).此设置将覆盖$.ajaxSetup()方法的全局设 置. async:要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求. 如果需要发送同步请求,请将此选项

jQuery Mobile的默认配置项详解,jQuery Mobile的中文配置api,jQuery Mobile的配置说明,配置大全

学习jQuery Mobile也有一段时间了,越来越上手了,也越来越喜欢他了.我根本就没有理由拒绝他的好.这里我有分享一下我对它的配置项的使用说明一下. 看代码解释: $(document).live("pageinit",function(event){ $.mobile.loadingMessage = "正在加载数据,请稍候......"; $.mobile.pageLoadErrorMessage="很抱歉,系统好像再打小瞌睡......"

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

推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用了zepto的touch模块, 通过手指滑动屏幕就可以控制乌龟走不同的方向: 因为推箱子这个游戏比较简单, 直接用了过程式的方式写代码, 模块也就是两个View 和 Model, 剩下就是用户的事件Controller, 用户每一次按下键盘的方向键都会改变数据模型的数据,然后重新生成游戏的静态htm

使用【百度云推送】第三方SDK实现推送功能详解

之前介绍过如何使用shareSDK实现新浪微博分享功能,今天介绍如何使用百度云推送SDK实现Android手机后台推送功能. 运行效果如下 第一步,如果使用百度的SDK,当然要先成为百度的开发者啦,这个就不详述了.成为开发者之后,我们要建立一个应用,如下图所示 第二步,创建好应用之后,我们点击开方者服务管理,进入工程管理页面,然后点击左侧云推送,进入云推送功能页面,具体如下图 进入云推送详细页面之后,我们点击推送设置,设置好我们的应用的包名,然后点击快速实例,将系统给我们产生的示例代码下载下来