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

linux编写弹球游戏,手把手教你开发一款基于Box2D的弹球游戏(一)

今天我们来介绍一款物理引擎,并基于它完成一个弹球游戏。提到物理引擎,就是在游戏中模拟真实世界的运动,碰撞,摩擦等等。Coco

今天我们来介绍一款物理引擎,并基于它完成一个弹球游戏。

提到物理引擎,就是在游戏中模拟真实世界的运动,碰撞,摩擦等等。Cocos2d集成了两款常用的物理引擎:Box2D和Chipmunk,两款引擎都是在2D下工作的,最主要的区别是Box2D是基于C++开发的,Chipmunk是基于C语言开发的。

在这个教程中,我们基于Box2D物理引擎完成游戏,Xcode版本是5.1。

首先我们简要介绍一下Box2D中的核心概念:

刚体(rigid body):不会产生形变的物体,刚体上任意两点之间的距离都是固定的,在Box2D中一般用物体(body)来简单描述刚体。

形状(shape):一个严格依附于物体的2D碰撞几何结构,具有密度,摩擦和弹力这些性质。

约束(constraint):一个约束就是消除物体自由度的物理连接。例如,在2D中,一个物体有三个自由度(水平,垂直和旋转),如果我们把一个物体钉在墙上,那么这个物体就只剩下了旋转自由度。

接触约束:一个防止刚体穿透,以及用于模拟摩擦和恢复的特殊约束。这种约束不需要我们创建,Box2D会在我们创建物体时自动创建该约束。

关节(joint):一种用于把两个或多个物体固定到一起的约束。Box2D中的关节如下:

距离关节(distance joint):两个物体上各有一点,两点之间的距离固定不变

旋转关节(revolute joint):强制两个物体共享一个锚点,及所谓的铰接点。旋转关节只有一个自由度:两个物体相对旋转。

移动关节(prismatic joint):允许两个物体沿指定轴相对移动,它会阻止相对旋转,移动关节只有一个自由度。

滑轮关节(pulley joint):滑轮关节用于创建理想滑轮,将两个物体接地并彼此链接,这样当一个物体上升,另一个物体就会下降。

齿轮关节(gear joint):齿轮关节需要两个被旋转关节或移动关节接地的物体。

线性关节(line joint):跟移动关节类似,但是没有旋转约束。

焊接关节(weld joint):使两个物体不能相对运动。

鼠标关节(mouse joint):驱使物体向鼠标所在位置移动的关节。

关节限制(joint limit):限定了一个关节的运动范围。

关节马达(joint motor):一个关节马达能按照关节的自由度来驱动所连接的物体。

世界(world):一个物理世界就是物体,形状和约束相互作用的集合。Box2D支持创建多个世界,但这通常是不必要的。

下面我们来看一下最终实现的效果:

6608717992840690563.png

第一步我们在Xcode中创建一个Box2D的工程:

6608540971468619449.png

工程名命名为PinballGame,device类型选IPad。

创建完成后我们看到所有的类定义文件都是以“.mm”结尾的,我们说过,Box2D是基于C++实现了,原因就在于此,如果我们创建Chipmunk框架的工程,则所有的类定义都是在“.m”文件中。因此,我们在后面创建类的时候,需要将默认的“.m”文件修改为“.mm”文件,不然无法通过编译。

创建完成后,我们删除默认创建出来的四个文件:

HelloWorldLayer.h

HelloWorldLayer.mm

IntroLayer.h

IntroLayer.mm

在Box2D中,我们通过定义碰撞多边形来定义物体的轮廓,通过指定一系列的点(vertex)来“描述”出一个物体的外轮廓。但是在实际的编写过程中,我们创建的物体的形状可能有简单的也有复杂的,简单的物体比如上面的圆形、三角形、圆角方形这些物体,复杂物体比如我们弧形的墙体。定义这些简单物体的外轮廓相对比较容易,但是定义复杂物体的外轮廓,如果通过手工编写代码,就是一个耗时耗力的工作了,因此我们这里介绍一个实用的工具:PhysicsEditor,帮助我们“绘制”物体的外轮廓并导出文件导入到Xcode中(听起来和TexturePacker挺像的,实际上我们看这两个Tool的图标还真是如出一辙)。

打开PhysicsEditor的界面:

6608189127748576321.png

我们首先修改右侧Parameters中的Exporter,选择“Box2D generic(PLIST)”,我们首先修改这个选项是因为不同的导出类型会决定其他选项设置。

接着我们修改PTM-Ratio值为256。解释一下这个参数,在Box2D中使用的长度单位不是像素(Pixel)或者点(Point),而是使用米(meter)作为基本单位,PTM代表的就是pixel to meter,这个值定义了转化比例,我们这里也就是定义256像素转化为1米,那么游戏屏幕尺寸也就是2048÷256=8米。实际在Cocos2D中,PTM-Ratio只有128,因为Cocos2D中坐标系的单位是点(Point),这是为了统一Retina屏和非Retina屏,使得两种屏幕的分辨率均为1024

Points×768 Points。

在Box2D物理引擎中,定义1米到10米之间的物体模拟的物理效果最好,当然你也可以定义更大的或者更小的物体,但是模拟的精度可能就会大打折扣了。

首先我们来定义弹射器,我们将弹射器的图片拖拽到Physics

Editor最左边的列表中,图片素材:

plunger.png(我们的发射通道的有角度的,所以发射器也是倾斜的):

6599284183075690042.png

然后我们点击中间上方的“add

polygon”(

2675982603688520031.png)来创建碰撞多边形,点击按钮后默认生成一个三角形,我们双击任意一条边即可添加一个顶点,双击任何一个节点可以删除那个节点,然后我们拖拽4个顶点对齐到弹射器的4个顶点上:

6599308372331503705.png

这里我们看到,有一个紫色的中间有十字的圆点,这个点是这个图形的锚点(anchor

point),与图形的锚点一致,我们可以拖拽进行重新定位,我们将锚点拖拽到弹射器的底边中点。如果更精确的控制,我们可以在右侧的参数菜单中进行编辑。

在右侧的参数菜单最下方,我们可以定义碰撞标记(collision

bit),通过碰撞标记我们定义哪些种类的物体之间能够发生碰撞,我们看到默认的碰撞标记名字为bit_i,i=0,1,2,3…,15,我们将其重命名,以便我们在后面的修改中能够区分不同种类的物体。重命名之后如下图:

6608515682701180703.png

接着,我们在Cat.(Categoty)中选中Plunger对应的checkbox,表明当前物体是弹射器,然后在Mask中只勾选Ball(可以利用右下角的快捷按钮进行全选,全不选,反选操作),表示我们的Plunger只会和Ball发生碰撞。

我们来继续定义墙体(Wall),这里注意一个细节:我们将右侧的墙体分成两部分,避免因为图形过于复杂影响计算速度,三张墙体素材(由于版面原因,对图片做了适当缩放):

left-wall.png:right-wall1.png:right-wall2.png:

3777957137510534024.png 6608846635701140690.png 6608927999561595942.png

我们将三张墙体图片拖拽到左侧列表中,这个时候,我们如果像创建弹射器的碰撞多边形那样去做,既费时间,又可能因为操作不细致导致创建的不够完美。好在Physics

Editor为我们提供了一个好用的工具,我们在“add

polygon”按钮的旁边找到一个类似魔棒的按钮“shape

tracer”(

1339820889243034922.png),点击之后,出现下面这个设置界面:

6599295178191971138.png

这里面Tolerance决定了图形的精确程度,这个值越高,精确度越差,生成的碰撞多边形的节点数也就越少,但是计算效率就越高。另外Alpha

threshold决定了边缘的处理方式,我们的墙体图片带有一点点外发光,所以我们将这个值设置为255,忽略墙体发光的部分。Animation

phase允许针对同一个物体不同帧进行设置。

如图设置完成后,点击确定回到主界面。回到主界面中,我们将生成的碰撞多边形的边界节点向屏幕外面外拖拽一些,避免因为计算的不精确导致不必要的抖动。并且我们删掉了一些不必要的节点(右下角半圆区域内的那些节点),因为这个区域是墙体跟我们的挡板的接触区域,没有必要检测这两类物体的碰撞修改后的结果如图:

6599325964517543413.png

接着我们修改墙体的碰撞标记,在“Cat.”中勾选Wall,在“Mask”中勾选Ball。

左边墙体完成后,我们用类似的操作将右边的墙体的碰撞多边形创建出来(不要忘记修改碰撞标记和锚点):

6608605842654658134.png

6608185829213693801.png

同理我们绘制左右两个挡板的碰撞多边形,挡板图片:

flipper-left.png:

6608201222376482794.png

flipper-right.png:

6608572857305824472.png

创建之后修改节点如下图所示(不要忘记修改碰撞标记为Cat.:Flipper,Mask:Ball,锚点的修改如图所示):

6608260596004381605.png

6599310571354759416.png

接下来我们继续制作缓冲器(Bumper):

缓冲器图片如下:

round-bumper.png:

1336161714545822972.png

bumper-group-left.png:bumper-group-right.png:

2668945729270752336.png

1496320976294397136.png

bumper-left-base.png:bumper-right-base.png:

3670996646360691072.png 6608460707119791138.png

bumper-left.png:bumper-right.png:

6608581653398846716.png 6608623434840702535.png

我们分别为这些缓冲器创建碰撞多边形(尽量用最少覆盖),修改碰撞标记(均为Cat.:Bumpers,Mask:Ball),修改锚点(锚点的修改没有统一的标准,只要方便我们加入元素的时候定位即可,另外对于左右对称的缓冲器,其锚点最好在属性编辑器中修改,避免人工拖拽的误差),这里限于篇幅不一一列出了。单独说一下round-bumper和左右两个bumper-group:round-bumper我们不必用polygon tracer,用add circle来生成圆形的碰撞图形;bumper-group中由于存在多个组成部分,因此需要用多次polygon

tracer为其添加碰撞多边形。

接下来我们把最后两个元素添加上去:

ball.png:

6599334760610565663.png

roller.png:



推荐阅读
author-avatar
潜伏在人间_144
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有