前言

偶然间看到很多用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. JDK5什么是新的线程锁技术(两)

    一个. Lock线程同步实现互斥 Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也是一个对象. 两个线程运行的代码片段要实现同步相互排斥的效果.他们必须用 ...

  2. EasyUI实战经验总结(转)

    最近公司培训EasyUI,就做下总结吧,给有需要的人,源码在文章最后. 1.最常用的表格 ? 1 2 3 <div class="easyui-panel" data-opt ...

  3. UVA 11249 - Game(游戏)

    UVA 11249 - Game 题目链接 题意:两堆石头.a和b.每次能取一堆随意数量,或者两堆同一时候取.可是绝对值差不能超过k,最后不能取的人输,问先手能否赢 思路:先如果(a, b)石子,a是 ...

  4. [原] Jenkins Android 自动打包配置(转)

    一.Jenkins自动打包配置 目标:1. 自动打包:2. 自动上传:3. 友好下载 1. Jenkins简介 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作. 减少重复劳 ...

  5. WebGL 在 OpenGL ES 指令 iOS 在 C 分歧版指令分析

    WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途 ...

  6. Sonar——代码质量管理平台

    Sonar——代码质量管理平台 一.基本认识 Sonar (SonarQube)是一个开源平台,用于管理源代码的质量. Sonar 不只是一个质量数据报告工具,更是代码质量管理平台.通过插件机制,So ...

  7. SQL Server 日期相关

    原文:SQL Server 日期相关 原帖出处:http://blog.csdn.net/dba_huangzj/article/details/7657979 对于开发人员来说,日期处理或许简单,或 ...

  8. angular cors跨域资源共享设置 和formdata设定

    非常easy,下来容易找到: <pre name="code" class="javascript">.config(['$routeProvide ...

  9. 【cocos2d-js公文】十八、Cocos2d-JS v3.0物业风格API

    1. 新的API风格 我们直接来看看你能够怎样使用Cocos2d-JS v3.0: 曾经的API 新的API node.setPosition(x, y); node.x = x; node.y = ...

  10. CSV文件格式分析器执行:从字符串Split至FSM

    本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee/article/details/38309147 本文分为5小节,基本上就是我刚接触C ...