前言

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

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

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

css布局

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

* {
padding:;
margin:;
} img {
border:;
} #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代码部分

 $(function () {
Game.init($("#container"));//初始化容器
});
var Game = {
gk: [{//关卡
map: [//地图数据 按照坐标呈现的数组格式
1, 1, 2, 2, 2, 2, 1, 1,
1, 1, 2, 3, 3, 2, 1, 1,
1, 2, 2, 0, 3, 2, 2, 1,
1, 2, 0, 0, 0, 3, 2, 1,
2, 2, 0, 0, 0, 0, 2, 2,
2, 0, 0, 2, 0, 0, 0, 2,
2, 0, 0, 0, 0, 0, 0, 2,
2, 2, 2, 2, 2, 2, 2, 2
],
box: [//箱子 坐标点对象
{ x: 4, y: 3 },
{ x: 3, y: 4 },
{ x: 4, y: 5 },
{ x: 5, y: 5 }
],
person: { x: 3, y: 6 }//人物 坐标点对象
},
{
map: [
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1,
1, 1, 1, 1, 2, 0, 2, 2, 0, 0, 2, 1,
1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 2, 1,
2, 2, 2, 2, 0, 0, 2, 0, 0, 0, 2, 1,
3, 3, 3, 2, 0, 0, 0, 0, 0, 0, 2, 2,
3, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2,
3, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2,
3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2,
3, 3, 3, 2, 2, 2, 0, 0, 2, 0, 0, 2,
2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 1,
1, 1, 1, 1, 2, 0, 0, 2, 0, 0, 2, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1,
],
box: [
{ x: 8, y: 3 },
{ x: 9, y: 3 },
{ x: 7, y: 4 },
{ x: 6, y: 7 },
{ x: 7, y: 5 },
{ x: 7, y: 8 },
{ x: 8, y: 9 },
{ x: 4, y: 5 },
{ x: 6, y: 6 } ],
person: { x: 3, y: 6 }
}
],
init: function (oParent) {
this.oParent = oParent;//此处将外层的对象引进来
this.iNow = 0;
this.createMap(this.iNow);
},
createMap: function (iNow) {
//创建地图 很关键的是 将元素的样式下标和地图的坐标点关联
this.oParent.empty(); document.title = "第" + (iNow + 1) + "关";
this.newJson = this.gk[iNow]; this.oParent.css("width", Math.sqrt(this.newJson.map.length) * 50);
var tempHtml = '';
$.each(this.newJson.map, $.proxy(function (i, elem) {
tempHtml += '<div class="pos' + elem + '"></div>';
}, this));
this.oParent.append(tempHtml);
this.createBox();
this.createPerson();
},
createBox: function () {//布局箱子所在的位置
$.each(this.newJson.box, $.proxy(function (i, elem) {
var oBox = $('<div class="box"></div>');
oBox.css({ 'left': elem.x * 50, 'top': elem.y * 50 });
this.oParent.append(oBox);
}, this));
},
createPerson: function () {//布局人物所在的位置
var oPerson = $('<div class="person"></div>');
var pos = this.newJson.person;
oPerson.css({ 'left': pos.x * 50, 'top': pos.y * 50 });
oPerson.data('x', pos.x);//缓存在oPerson上的数据
oPerson.data('y', pos.y);
this.oParent.append(oPerson);
this.bindPerson(oPerson);
},
bindPerson: function (oPerson) {//绑定对人物←↑→↓操作
$(document).keydown($.proxy(function (ev) {
switch (ev.which) {
case 37: //←
oPerson.css('backgroundPosition', '-150px 0');
this.movePerson(oPerson, { x: -1 });
break;
case 38: //↑
oPerson.css("backgroundPosition", "0 0");
this.movePerson(oPerson, { y: -1 });
break;
case 39: //→
oPerson.css("backgroundPosition", "-50px 0");
this.movePerson(oPerson, { x: 1 });
break;
case 40: //↓
oPerson.css("backgroundPosition", "100px 0");
this.movePerson(oPerson, { y: 1 });
break;
default:
}
}, this));
},
movePerson: function (oP, opt) {//移动人物
var xValue = opt.x || 0;
var yValue = opt.y || 0;
var length = Math.sqrt(this.newJson.map.length);
var currentMapIndex = (oP.data('x') + xValue) + (oP.data('y') + yValue) * length;
if (this.newJson.map[currentMapIndex] != 2) {//遇到墙的判断
oP.data('x', oP.data('x') + xValue);
oP.data('y', oP.data('y') + yValue);
oP.css({ "left": oP.data("x") * 50, "top": oP.data("y") * 50 });
$(".box").each($.proxy(function (i, elem) {
//当和箱子发生碰撞时遇到墙的判断
if (this.pz(oP, $(elem)) && this.newJson.map[(oP.data('x') + xValue) + (oP.data('y') + yValue) * length] != 2) {
$(elem).css({ 'left': (oP.data('x') + xValue) * 50, 'top': (oP.data('y') + yValue) * 50 });
$(".box").each($.proxy(function (j, elem2) {
if (this.pz($(elem), $(elem2)) && elem != elem2) {
//当遇到箱子和箱子的的碰撞时同时前面也不是强的判断
$(elem).css({ 'left': oP.data('x') * 50, 'top': oP.data('y') * 50 });
oP.data('x', oP.data('x') - xValue);
oP.data('y', oP.data('y') - yValue);
oP.css({ "left": oP.data("x") * 50, "top": oP.data("y") * 50 });
}
}, this));
}
else if (this.pz(oP, $(elem))) {//和墙之间的碰撞
oP.data('x', oP.data('x') - xValue);
oP.data('y', oP.data('y') - yValue);
oP.css({ "left": oP.data("x") * 50, "top": oP.data("y") * 50 });
}
}, this));
}
this.nextShow();
},
nextShow: function () {//判断是否赢
var iNum = 0;
//红色区域所在的位置是否全部被箱子所占据
$(".box").each($.proxy(function (i, elem) {
$(".pos3").each($.proxy(function (j, elem1) {
if (this.pz($(elem), $(elem1))) {
iNum++;
}
}, this));
}, this));
if (iNum == this.newJson.box.length) {
this.iNow++;
this.createMap(this.iNow);
}
},
pz: function (obj1, obj2) { //碰撞检测
var L1 = obj1.offset().left;
var R1 = obj1.offset().left + obj1.width();
var T1 = obj1.offset().top;
var B1 = obj1.offset().top + obj1.height(); var L2 = obj2.offset().left;
var R2 = obj2.offset().left + obj2.width();
var T2 = obj2.offset().top;
var B2 = obj2.offset().top + obj2.height();
if (L1 >= R2 || B2 <= T1 || T2 >= B1 || R1 <= L2)
{ return false; }
else
{ return true; }
}
};

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

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

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

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

结论

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

download PushBox

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

  1. Django模型验证器详解和源码分析

    转发请注明来源 在Django的模型字段参数中,有一个参数叫做validators,这个参数是用来指定当前字段需要使用的验证器,也就是对字段数据的合法性进行验证,比如大小.类型等. Django的验证 ...

  2. 微服务生态组件之Spring Cloud OpenFeign详解和源码分析

    Spring Cloud OpenFeign 概述 Spring Cloud OpenFeign 官网地址 https://spring.io/projects/spring-cloud-openfe ...

  3. 微服务生态组件之Spring Cloud LoadBalancer详解和源码分析

    Spring Cloud LoadBalancer 概述 Spring Cloud LoadBalancer目前Spring官方是放在spring-cloud-commons里,Spring Clou ...

  4. jquery $.trim()去除字符串空格详解

    jquery $.trim()去除字符串空格详解 语法 jQuery.trim()函数用于去除字符串两端的空白字符. 作用 该函数可以去除字符串开始和末尾两端的空白字符(直到遇到第一个非空白字符串为止 ...

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

    推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用 ...

  6. MySql绿色版配置及使用详解

    原文:MySql绿色版配置及使用详解 最近在做项目开发时用到了MySql数据库,在看了一些有关MySql的文章后,很快就上手使用了.在使用的过程中还是出现了一些问题,因为使用的是绿色免安装版的MySq ...

  7. 用HTML5+原生js实现的推箱子游戏

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. C# 推箱子游戏&对战游戏

    推箱子游戏提纲,只有向右向上的操作,向左向下同理,后期需完善. namespace 推箱子 { class Program { static void Main(string[] args) { // ...

  9. 【CCpp程序设计2017】推箱子游戏

    我的还……支持撤销!用链表实现! 题目:推箱子小游戏(基于console) 功能要求: 将p09迷宫游戏改造为“推箱子”游戏: 在地图中增加箱子.箱子目标位置等图形: 当玩家将所有箱子归位,则显示玩家 ...

随机推荐

  1. MongoDB最新版本3.2.9下载地址

    https://downloads.mongodb.com/win32/mongodb-win32-x86_64-enterprise-windows-64-3.2.9.zip?_ga=1.22538 ...

  2. Android - 分享内容 - 接收其他APP的内容

    就象程序可以发送数据给其他程序,所以也可以接收其他程序的数据.想一下用户如何和程序交互,以及想从其他程序接收什么样类型的数据.例如,一个社交程序可能对接收其他程序的文字(比如有趣的网址)感兴趣.Goo ...

  3. javascript的位操作、整数、二进制

    位与(x&y):对操作数进行二进制与的操作,如果两个操作数的某一位两个都为1,将对应的结果位设为1. 0x0007 & 0x0003 = 0x0003 \ 一个小型年老棕色的狗:64 ...

  4. mac eclipse svn subeclipse: Failed to load JavaHL Library.

    Failed to load JavaHL Library. These are the errors that were encountered: no libsvnjavahl-1 in java ...

  5. 2014百度之星预赛(第二场)——Best Financing

    2014百度之星预赛(第二场)--Best Financing Problem Description 小A想通过合理投资银行理財产品达到收益最大化.已知小A在未来一段时间中的收入情况,描写叙述为两个 ...

  6. Python学习笔记12:标准库之对象序列化(pickle包,cPickle包)

    计算机的内存中存储的是二进制的序列. 我们能够直接将某个对象所相应位置的数据抓取下来,转换成文本流 (这个过程叫做serialize),然后将文本流存入到文件里. 因为Python在创建对象时,要參考 ...

  7. 设计Kafka的High Level Consumer

    原文:https://cwiki.apache.org/confluence/display/KAFKA/Consumer+Group+Example 为什么使用High Level Consumer ...

  8. 从session实现机制分析模拟请求验证码的可行性(转)

    悲剧了,发现写完这篇blog没有配上这个格调超高的标题.   1.0问题背景 现在要实现一个带验证码网站的的自动登陆功能.验证码识别过程不再这篇文章的讨论之中.(之后有篇文章我会详细的总结验证码的识别 ...

  9. 介绍4种HTML5 Canvas库

    1.bHive.js Library http://www.bhivecanvas.com/ bHive能创建丰富的用户体验.动画.游戏,能够使开发更简单. demo: http://www.bhiv ...

  10. R0-R37它是Arm 寄存器,那是,CPU内部。和GPIO注册所有外设。换句话说,要是arm的cpu,它包含了其他芯片公司将有R0-R37,和GPIO寄存器只有一个特定的芯片。

    R0-R37它是Arm 寄存器.那是,CPU内部.和GPIO注册所有外设. 换句话说,要是arm的cpu,它包含了其他芯片公司将有R0-R37,和GPIO有. 版权声明:本文博主原创文章.博客,未经同 ...