热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HTML5物理游戏开发-越野山地自行车(二)创建一辆可操控的自行车

第二章又拖到现在才发布,话说本次更新离上次已经很久了。不知道大家还记得上一章讲的内容否?在上一章中,我们创建了各式各样的地形,今天我们就在这个地形之上,创建一辆自行车,并让它受到我们的控制。首先放上一

第二章又拖到现在才发布,话说本次更新离上次已经很久了。不知道大家还记得上一章讲的内容否?

在上一章中,我们创建了各式各样的地形,今天我们就在这个地形之上,创建一辆自行车,并让它受到我们的控制。首先放上一张截图:


没看过上一章的同学可以先移步到上一章。在了解上一章的内容之后,读起本章方可容易一些。

HTML5物理游戏开发 - 越野山地自行车(一)建立各式各样的地形

http://blog.csdn.net/yorhomwang/article/details/19710537


※再次声明,本次开发用到了lufylegend.js开源html5游戏引擎和box2dweb物理引擎,请到官方网站下载使用。官方网站地址已在第一章中说过了。


一,基础知识

首先我们来科普几个知识,只有了解这些知识之后,读起下面的内容才不会感觉头疼。

1,如何使刚体移动

在box2dweb中,要想使刚体移动,不能单纯地改变x、y坐标。其一,这样会使你的游戏失去了物理运动的效果;其二,在box2dweb中,直接调整刚体的位置是一个十分不好的方法,会违背物理运动原理,只有在刚体创建前的时候才用这个方法。所以在我们的自行车创建出来以后,想要移动刚体,最好的方法就是给刚体施加一个力。

在box2dweb中,施加力的方法有:ApplyForce、ApplyImpulse、SetLinearVelocity。本次使用的只有ApplyForce。其余的几种可以暂且不管。如果你确实想了解的话,可以看看ladeng6666的这篇文章:让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity

ApplyForce的用法如下:

ApplyForce(vec, pos)

这个函数的第个一个参数是给物体施加力的向量(b2Vec2);第二个pos是施加的位置,一般不确定位置的时候就取物体的重心(可以用b2Body的GetWorldCenter获取)。


2,如何构造像自行车这样形状复杂的物体

如何构造像自行车这样形状复杂的物体确实是一个值得思考的话题。对我们而言,第一个出现在脑子里的想法就是创建一个多边形刚体。当然这样实现起来极其麻烦,而且不仅仅是麻烦,做到最后更扫兴的是使用这种方法弄出来的刚体碰撞检测有问题,换言之,一个原本是凹凸多边形的刚体,突然就成了柔体,碰在其他物体上就会渗入其他物体里,so qipa~

那到底应该怎么办呢?我们不妨假设自己就真正地在制作一辆自行车。首先,我们要把材料和工具准备好。材料就是几个木块,工具就是一个锤子,一把铁钉。接下来,我们要做的就是用锤子铁钉把几个木块组装起来就ok了。这样看起来虽然so easy,但是有朋友会问,在box2dweb里到哪里去找锤子铁钉呢?锤子铁钉在box2dweb里倒是真没有,不过有一个更先进的东西——关节(joint)。

在这里主要就是需要两种关节:旋转关节(用于把轮子和支架绑起来),焊接关节(用于把各个支架固定起来)。

这两个关节在box2dweb里的使用方法依然不是那么简单,因此同样用到了lufylegend.js的封装。接下来就对这几个关节的用法进行说明。

■setRevoluteJoint(b2BodyA, b2BodyB, limits, motors)

b2BodyA:表示物体A (b2Body对象,可以用LSprite的box2dBody属性获取)
b2BodyB:表示物体B(b2Body对象,可以用LSprite的box2dBody属性获取)
limits:表示旋转角度限制数组,这个数组的内容是:[最小角度,最大角度],它在这里可以限制旋转关节旋转的角度(可以不传)
motors:表示马达数组,这个数组的内容是:[力度,速度],马达可以有很多用途,在这里,它可以是关节自动进行旋转(可以不传)

示例:

var backLayer,cLayer;    function main(){    
LGlobal.setDebug(true);
backLayer = new LSprite();
addChild(backLayer);

LGlobal.box2d = new LBox2d();
cLayer = new LSprite();
cLayer.x = 300;
cLayer.y = 390;
backLayer.addChild(cLayer);
cLayer.addBodyPolygon(600,10,0,5,0.4,0.2);
//加入一个动态的圆形物体1
box01 = new LSprite();
box01.x = 250;
box01.y = 200;
backLayer.addChild(box01);
box01.addBodyCircle(100,0,0,1,1,0.4,0.2);
box01.setBodyMouseJoint(true);
//加入一个静态的圆形物体2
box02 = new LSprite();
box02.x = 250;
box02.y = 150;
backLayer.addChild(box02);
box02.addBodyCircle(10,0,0,0,1,0.4,0.2);
//加入一个旋转关节
LGlobal.box2d.setRevoluteJoint(box01.box2dBody, box02.box2dBody ,[-360,720*5],[450,2]);
}

■setWeldJoint (b2BodyA, b2BodyB)

b2BodyA:表示捆绑对象物体A(b2Body对象,可以用LSprite的box2dBody属性获取)
b2BodyB:表示捆绑对象物体B(b2Body对象,可以用LSprite的box2dBody属性获取)

示例:

var backLayer,cLayer;function main(){        LGlobal.setDebug(true);     backLayer = new LSprite();      addChild(backLayer);         LGlobal.box2d = new LBox2d();    cLayer = new LSprite();    cLayer.x = 300;    cLayer.y = 390;    backLayer.addChild(cLayer);    cLayer.addBodyPolygon(600,10,0,5,0.4,0.2);    //加入一个动态的圆形物体1    box01 = new LSprite();    box01.x = 200;    box01.y = 100;    backLayer.addChild(box01);    box01.addBodyCircle(50,0,0,1,1,0.4,0.2);    box01.setBodyMouseJoint(true);    //加入一个动态的圆形物体2    box02 = new LSprite();    box02.x = 250;    box02.y = 100;    backLayer.addChild(box02);    box02.addBodyCircle(50,0,0,1,1,0.4,0.2);    box02.setBodyMouseJoint(true);    //加入一个焊接关节    LGlobal.box2d.setWeldJoint(box01.box2dBody, box02.box2dBody);}

ok,基础知识差不多讲完了。进入正题吧。


二,修改Main类

上一章中的Main类大家还记得否?上次我没有加入真正的自行车,而是拿一个圆形小球在那里充当着,主要是给大家看看镜头跟随效果和各式各样的地形。这次既然要实现一个自行车,那么就要先把小球换掉,于是更改addBicycle函数,更新后如下:

Main.prototype.addBicycle = function(){var s = this;//创建自行车对象s.bicycleObj = new Bicycle(50,385);s.addChild(s.bicycleObj);};
这里明显用到了Bicycle这个类。那么,我就立刻把笔尖指向Bicycle类吧,这个类是本章的重点内容,前面的基础讲解就是为这个类作铺垫的。


三,自行车类(Bicycle)

先看看构造器:

function Bicycle(sx,sy){var s = this;base(s,LSprite,[]);/**初始坐标*/s.sx = sx;s.sy = sy;/**刚体所属LSprite对象列表*/s.bodyList = new Array();/**添加左右移动力度向量*/s.moveVec = new LStage.box2d.b2Vec2();/**添加拉压操作力度向量*/s.tcVec = new LStage.box2d.b2Vec2();/**添加事件*///键盘按下事件LEvent.addEventListener(window,LKeyboardEvent.KEY_DOWN,function(e){s.onKeydown(e,s);});//键盘松开事件LEvent.addEventListener(window,LKeyboardEvent.KEY_UP,function(e){s.onKeyup(e,s);});//初始化s.init();}

构造器代码加入了详细的注释,所以我们直接进入讲解Bicycle的init函数。这是代码:

Bicycle.prototype.init = function(){var s = this;var sx = s.sx;var sy = s.sy; /**轮子半径*/var wheelR = 20;/**轮子之间的距离*/var gapBetweenWheelAndWheel = 100;/**车手柄到轮子的距离*/var gapBetweenWheelAndHandlebar = 50;/**车把尺寸*/var handlebarbicycle";}/**设置主刚体*/s.mainBody = frameAObj.box2dBody;/**设置拉压操作刚体*/s.tcBody = wheelBObj.box2dBody;};
这个函数看上去超长,但是逻辑却异常简单,大部分是重复的代码,再通过上面的基础讲解外加注释,看上去应该是无压力了吧,当然如果有不懂的,欢迎在本文下方留言。其中,我为了大家测试时的简化操作,给每一块刚体都设置了鼠标拖动,但是又由于刚体有很多,所以我把它们统统装在bodyList这个数组了,然后最后用遍历的方式给每一个刚体都设置了鼠标拖动。
最后来看看如何实现键盘操作。不难发现,在构造器里有这么一段代码:

/**添加事件*///键盘按下事件LEvent.addEventListener(window,LKeyboardEvent.KEY_DOWN,function(e){s.onKeydown(e,s);});//键盘松开事件LEvent.addEventListener(window,LKeyboardEvent.KEY_UP,function(e){s.onKeyup(e,s);});
在段代码里,我们还用到了onKeydown和onKeyup这两个函数。代码如下:

Bicycle.prototype.OnKeydown= function(e,s){var force = 50;switch(e.keyCode){//向右case 39:s.moveVec.x = force;break;//向左case 37:s.moveVec.x = -force;break;//向上case 38:s.tcVec.y = -force;break;//向下case 40:s.tcVec.y = force;break;default:return;}/**施加移动的力*/s.mainBody.ApplyForce(s.moveVec,s.mainBody.GetWorldCenter());/**施加拉压的力*/s.tcBody.ApplyForce(s.tcVec,s.tcBody.GetWorldCenter());};Bicycle.prototype.OnKeyup= function(e,s){/**清空力度相量*/s.moveVec.SetZero();s.tcVec.SetZero();};

在这里我们用到了之前讲过的ApplyForce。之前讲的时候,没有具体讲第一个参数是因为没有实际用到讲了等于徒劳。现在可以看到,这个b2Vec2有x,y属性,这两个属性可以控制力的方向。x<0向左,x>0向右,y>0向下,y<0向上。

当然,tcVec和moveVec是两个不同的向量,也就是说控制的不是同一个效果。moveVec是控制移动自行车的,这个不用多说。而tcVec是用于拉、压自行车的,我们知道,当在游戏中要开翻车的时候,往往可以用拉、压的方式来操控自行车,使其重新平衡,这个tcVec就是干这活儿的。

BTW,如果你不知道tcBody和mainBody是什么,可以看看Bicycle里init函数的代码。

添加完键盘事件后,我们就可以通过方向键来控制自行车了。操作方式为:上-拉,下-压,左-后退,右-前进。大家可以打开本文最下方的测试链接进行测试。

ok,至此,运行一下代码,得到的就是本文最上方图片所示的效果了。(什么?太丑了?你指的是我还是这个游戏?这个游戏啊,没贴图当然丑呢。)


奉上源代码下载地址:http://files.cnblogs.com/yorhom/box2dBicycle%282%29.rar

测试地址:http://www.cnblogs.com/yorhom/articles/box2dweb_bike2.html


下一章预告:目前,咋们的自行车是金刚不坏之身,你怎么摔它,它就是摔不碎(除非你把显示器抱起来,然后使劲往地上摔)。但是这不科学对吧……所以在下一章,我们就来看看,如何把这个自行车摔得支离破碎,体无完肤。哈哈,尽情期待~


本章就先到这里了。如果文章有任何疏漏之处,欢迎指正。当然,有不懂之处也欢迎各位在本文下方留言,我会尽力回复大家的。

----------------------------------------------------------------

欢迎大家转载我的文章。

转载请注明:转自Yorhom's Game Box

http://blog.csdn.net/yorhomwang

欢迎继续关注我的博客


推荐阅读
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • HowcanIaligntwoinline-blockssothatoneisleftandtheotherisrightonthesameline?Whyi ... [详细]
  • 前端监控数据网络(要求阻拦)
    所谓web,纵然你我素未谋面,便知志趣相投;深居简出,亦知天下之大。01—为何阻拦要求如今的web运用,大都是经由过程要求(http)去猎取资本,拿到资本后再显现给用户,一个页面中 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • javascript – 关于微信浏览器的疑问
    后端开发|php教程php,javascript,html5后端开发-php教程现在正在开发移动端webapp,遇到了比较麻烦的问题:用户输入帐号密码登陆后,自动跳转到首页,,QQ ... [详细]
  • js中运行机制的详细分析(示例解析)
    web前端|js教程node.js,html5,html,css,javascriptweb前端-js教程本篇文章给大家带来的内容是关于js中运行机制的详细分析(示例解析),有一定 ... [详细]
author-avatar
兔女郎不会吧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有