游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

如何用Box2D Library制作2D物理游戏

发布时间:2013-10-01 08:48:04 Tags:,,,,,

作者:Juan Felipe Belon Perez

从最热门游戏排行榜和flash游戏网站上,你能看到什么?许多2D游戏都有非常出色的物理学和美术设计。现在我们要学习那些游戏使用了什么物理学以及如何用Box2D制作它们。

除了知道是“什么”,更重要的是知道“如何做”,首先,我想问读者一个问题:如果你想复制物理游戏的机制或行为,你需要什么技术和方法?

一年以前,我问了自己同样的问题,《6 Dimensions》就是问题的答案。这款游戏是一个创意的盒子,每一面都包含一组使用Box2D物理学再加上视觉美学技术制作的不同的游戏机制。在此,我将与大家分享这款游戏。我做这款游戏是为了改进游戏引擎Codea(是由Crabitron开发的),而我写了这篇教程是为了向大家介绍写实物理学、美术和游戏设计……共同提高我们的游戏开发水平。

在我的游戏中,我设计了6个面,借同样的思路,我将给大家介绍我运用了哪些从其他游戏中复制而来的物理、机制和美术技术。

1、形状

《Thomas was alone》、《愤怒的小鸟》、《蜡笔物理学》

crayon physics(from gamasutra)

crayon physics(from gamasutra)

在《蜡笔物理学》中,你可以在屏幕上用手指或鼠标作画,比如画圆、三角形、矩形等,当你松开鼠标/拿开手指,线条就会变成立体物理对象(在虚拟世界中)。

这是怎么做的?

事实上相当简单,你要把鼠标/手指从开始到结束的绘画路径的各个坐标点保存起来,当释放事件发生,你就调用Box2D的一个根据这些点生成多边形的功能:

local body = physics.body(POLYGON, unpack( points ) )

你得先认识一下Box2D中的有什么形状:

POLYGON(多边形):

用于封闭形状如基本几何图形(非圆形),它使用一系列按各个API指定的顺序排列的顶点(x,y)

CIRCLE(圆):

可以做球、水珠、星体,等等。

EDGE(边):

用于制作墙、地面、只有起点和终点的线段。

CHAIN(链):

与边相同,但你可以闭合它(像多边形但不是凸多边形)或不闭合它(像边但点超过2)

知道了刚体形状(body shape)后,你还要了解它们的不同行为,或叫作刚体类型(body types):

STATIC(静态):如名称所示,这种刚体会在指定的x,y(地面、墙、柱基或绳基,等等)上保持静止不动。

DYNAMIC(动态):它与其他对象碰撞并移动

KINEMATIC(运动):碰撞但不随着动态对象移动,你只能通过改变它的x,y或者赋给它一个线性速度或对它施加力来使它移动。

真正的含义要在API的执行中理解,在本文中我使用这个是因为它是我能找到的最简单的代码了。但改变成任何语言的代码都非常简单,Box2D有几乎所有的语言版本(Flash as3、c++、objc、java、javascript、java+processing,等等)。

你得保存那个功能的结果为自定义变量如body.position(位置)、body.radius(半径)、body.linearVelocity(线性速度)、body.angularVelocity(角速度)、body.mass(质量),等等。

当刚体制作出来时,你可能想给它定义一些属性如restitution(恢复)、gravityScale(重力大小)和damping(衰减)等,这些属性可以赋给物理对象弹跳或漂浮状态。

Box2D的复杂度当然不止这些,具有这种物理游戏机制的其他游戏(《Magic Pen》)也比较复。在《Magic Pen》中,你可以画一些东西看起来像“node(节点)”的东西,但开发者叫它们“joint(关节)”,它们是用于连接刚体的,有若干种,取决于你想要的机制;还可以用于制作连接着的刚体之间的行为:

physics.joint(REVOLUTE,bodyA, bodyB,)

刚体围绕着一个固定点(anchor)旋转

例如:小车的车轮、《蜡笔物理学》和《Magic Pen》中的红色节点

physics.joint( PRISMATIC, bodyA, bodyB, anchorA, direction )

在刚体各自的固定点之间保持固定距离。两个joint之间的初始距离取决于虚拟空间中的这两个固定点之间的初始距离。给joint设置frequency率和damping率可以使它产生软弹簧的行为。

physics.joint(DISTANCE, bodyA, bodyB, anchorA, anchorB )

旋转joint迫使两个刚体沿着某两个固定点之间的轴作运动。允许伸缩运动,但限制两个刚体之间的相对旋转。

physics.joint( WELD, bodyA, bodyB, anchor )

接合joint限制两个刚体之间的运动和相对旋转,实际上使它们变成一个刚体。因为求解器的迭代性质,当置于压力之下时接合joint可能会变形;当承受的力太大或几个接合joint被链接成一个更大的对象时,接合joint可能会完全失效。

physics.joint( ROPE, bodyA, bodyB, anchorA, anchorB, maxLength )

绳子joint限制两个刚体之间的最大距离

例如:《割绳子》中的绳子

概述:

1)创建:带有触点刚体或盒子或任何其他多边形几何体(一组2D点:x,y),给它设置我们需要的物理属性(如《Thomas was alone》中的不同行为),比如,如果刚体是static类型,那么就可以设置它的质量、密度、重力大小,等等。

2)可选属性:依附(attach)到另一个刚体上,比如说,你可以把一个刚体依附到另一个被设置为传感器的static刚体(不影响游戏世界的物理,但有碰撞事件),然后激活REVOLUTE joint的enableMotor(能动)属性,这还需要motorSpeed(速度)、maxMotorTorque(转矩)和maxMotorForce(力量),才能确定这个对象的旋转情况。

3)美术(Visual Art):有了刚体后,如果你想绘制它,不是作为形状绘制出来,而是具有颜色或纹理的实体,你就要把这些点三角化生成多边形网格模型(mesh)并给它设置颜色和贴材质。

例子:

Box2D_POLYGONS(from gamasutra)

Box2D_POLYGONS(from gamasutra)

thomas Was Alone Boxes(from gamasutra)

thomas Was Alone Boxes(from gamasutra)

对于《Thomas Was Alone》中的盒子的行为,你可以设置一个简单的“juice”系统动画(从“中间帧”演化来的),这样,当你选择方块并按下跳跃键(或它与其他不同的物理刚体发生碰撞),它就会触发“juice command= animation”命令——产生挤压、摇晃等动画效果,各个动作都有自己的动画参数,比如质量、线性速度和衰减等物理属性。

box Examples(from gamasutra)

box Examples(from gamasutra)

对于《愤怒的小鸟》,你可以通过给盒子定义不同的属性来制作一个关卡,绘制不同的子画面或制作不同材质的mesh,这样,在碰撞事件中,盒子刚体就会更加生动,通过改变盒子的纹理使之与当前状态更加协调(断掉的木头、快碎的玻璃,等)。

你可以用简单的刚体applyForce(vec2(x,y)) 函数做出小鸟的发射。各种小鸟也都有自己的质量、衰减等属性……

2、水体

《Where is my water?》、《Sprinkle Ilsands》……

当你问网上的代码达人,如何制作上述游戏那样的水体物理时,他们会跟你谈Metaball(变形球):

Metaball_contact_sheet(from gamasutra)

Metaball_contact_sheet(from gamasutra)

但在游戏中使用Metaball技术既麻烦也不容易,而且要进行大量计算,除非你发现一些技巧和给它贴上一些美术材质。

那就是为什么运用水体物理学的游戏并不多见。几个月前我谈到这个问题,多亏了许多人的帮助,我得到了一个很棒的水体物理模型。在那个模型中,我用Box2D lib中的CIRCLE刚体做出动态球。

模型的代码很容易理解,球就是物理刚体,这些刚体具有使它产生水滴行为的参数如estitution(复原)、friction(摩擦)、damping(衰减)、linear velocity(线性速度),然后,我们用着色器(GLSL)的技术和材质绘制这些球,需要一个mesh,就像波纹fx或使用材质的其他GLSL着色器样本,我们把这个mesh的宽和高设为整个屏幕,从中间开始:

mesh:addRect(WIDTH / 2, HEIGHT / 2, WIDTH, HEIGHT)

这样,我们可以使用各个球的位置(x,y)在虚拟空间中绘制它们,各个球都有渐变的纹理效果。

for k,b in ipairs(balls) do
sprite(ballTexture, b.x, b.y)
end

然后,你得使用额外的扭曲模式,给这些着色的球添加材质,并与背景混合。

例子:

Box2D_water Physics(from gamasutra)

Box2D_water Physics(from gamasutra)

正如我所说的,各个球都有纹理(程序生成的渐变),可以与其他使用低级过滤器的球材质相融合。

where is my water(from gamasutra)

where is my water(from gamasutra)

《Where is my water?》

你可以对各种行为使用不同的层,或者把所有液体或所有动态地形做成同一层来做出相同的水体fx,然后在着色器中改变过滤值和颜色(水体、岩浆,等等)。

举一个碰撞的例子,当两个刚体发生碰撞时,你必须查看碰撞的bodyA和bodyB是什么类型的刚体,如果一个是气体(gravityScale/mass/density值实际上是0,所以它会飘浮)而另一个是“冰”,那么你就把这个球变成水……

再举一个例子,如果bodyA是岩浆,那么bodyB就变成气体……就像改变球的属性一样简单,所以它会改变在box2d中响应,你要重新绘制游戏状态。

地形的例子:

静态地形可以是一个POLYGON刚体,它是用一个读取整个地形图象和建立一系列非透明像素的x,y (vec2)的函数制作的,然后返回给box2d函数。

动态地形可以只是一个mesh,当你碰它时,你会移除座标x,y上的触点,你必须用新的mesh重制这个物理刚体。

例如,当一个水滴(物理刚体CIRCLE)溅到一只鸭子(具有激活的传感器的物体刚体),你必须删除那个水滴,并改变鸭子的动画,使新状态呈现,直到它完全被水充满,然后删除鸭子并记录结果。

水滴有很小的痕迹,这些是用linearVelocity和angularVelocity属性绘制的,你可以得到方向和速度,这样你就可以计算痕迹的角度和距离。

事实上,你想要什么行为都有。

sprinkle_islands_boss(from gamasutra)

sprinkle_islands_boss(from gamasutra)

在《Sprinkle Ilsands》中,水体着色器跟我们所学习的那个是不同的,它除了使用粒子fx,还多了linearVelocity属性。但行为可能还是一样的,当水球(刚体CIRCLE)击中火传感器,那么火就会熄灭,海里的水mesh也一样。至于岩石,你可以添加一些细节如颗粒效果等。

在这一面,我们找不到任何joint,那就是为什么它可能不必要,在《Sprinkle Ilsands》,软管就是绳子,这是我们在下一面中要分析的。

3、橡皮筋

《Contre Jour》、《割绳子》、《水果忍者》

我花了一个月时间才做出上述游戏的绳子原型,但我做完绳子后,我就觉得软刚体很容易做了,因为我更加理解接头了。

要制作一个逼真的绳子,你得创建一组刚体(CIRCLE或者POLYGON都行),把它们都依附在作为基座的STATIC刚体上。用于结合这些绳子刚体的joint有两种,DISTANCE或者REVOLUTE,但处于最末端(DYNAMIC)的连接基座(STATIC)的joint只能是制作弹力绳的ROPE joint。通过restitution 和frequency属性来调整response(反应)/damping(衰减)/elasticity(弹性)。

例子:

Box2D_ElasticRopes(from gamasutra)

Box2D_ElasticRopes(from gamasutra)

为了制作一个软刚体,你得围绕另一个中心刚体(可以是STATIC或DYNAMIC)制作一系列CIRCLE刚体,它当然会影响其他刚体,如果你改变joint的类型,你会发现这个刚体会自动变形,你必须用mesh绘制整组刚体。

Contre-Jour(from gamasutra)

Contre-Jour(from gamasutra)

《Contre Jour》

在这款游戏中,你可以找到软刚体:可变形的地形;两种类型的绳子:弹性绳和固定绳。这些固定绳使用的技术比弹性绳的更高级。

snotDiagram(from gamasutra)

snotDiagram(from gamasutra)

js Rope Segmented(from gamasutra)

js Rope Segmented(from gamasutra)

《割绳子》

cut-the-rope(from gamasutra)

cut-the-rope(from gamasutra)

这是Box2d物理做绳子的最佳案例。游戏中的绳子也是动态的,你可以看到沿着基座到球的mesh,球的一端是连着糖果的。

你可以像上一个例子一样做出这种绳子,设置球(糖果)的物理属性—-mass、density、gravityScale,可以做出泡泡效果。你可以用多层混合模式绘制出泡泡。另一种方法是把刚体变成传感器,并且你自己的重力算法移动它,但我们到第五面时才学习这种技术。

如果泡泡-刚体-球与青蛙或蜘蛛碰撞,或者玩家触击到泡泡,泡泡就会爆炸,为此你要给泡泡添加爆炸动画并再次改变糖果的物理属性……

案例代码:

if (vec2:distance( bFrog_Mouth,  bCandy ) < maxDistance) then

– 把青蛙的动画从“空闲”改为“吃”

– 暂停输入

– 补间并触发游戏结束动画

end

4、重力

在这一面,我们可以发现许多使用力来对抗重力的游戏,但这是一种游戏玩法。例如,你可以根据box2d的正弦函数生成简单的地形,它会返回链或边形状的STATIC刚体。

tiny wings 2(from gamasutra)

tiny wings 2(from gamasutra)

你可以用Box2d做出你自己的《Tiny Wings》。基本原理就是,球(CIRCLE刚体)在重力的作用下下落,你可以通过触击屏幕增加下落的linearVelocity(线性速度),当触击在山丘合适的部分(你可以查看你的正弦函数的高度)释放时,下落速度会增加……另一种方法是只使用力。

例子:

Box2D_JumpRun(from gamasutra)

Box2D_JumpRun(from gamasutra)

为了绘制循环,给拾取、发热状态等添加颗粒效果。材质可以用程序成生随机颜色图像做出来,用高斯噪声添加细节、边界,等等……

Jetpack-Joyride(from gamasutra)

Jetpack-Joyride(from gamasutra)

《Jetpack Joyride》

你可以看出这款游戏的特征吗?如果你已经读过前面的例子了,那么你应该知道角色刚体球有相同的行为,你一定是用力对抗重力、各个飞行器的不同物理属性、导弹和各种交通工具,等等。

《Madcoaster》、《Rocket Chicken》、《Whale Trail》等游戏都是一样的。

但这个面还有其他机制,如行星物理、引力。

你可以使用简单的公式来模拟零重力physics.gravity(0,0),行量的吸引力如下图所示:

Box2D_Forces_Gravity(from gamasutra)

Box2D_Forces_Gravity(from gamasutra)

function Planet:attract(m)
– Direction of the force
local force = self.body.position – m.body.position
local d     = force:len() — = m.body.position:dist(self.body.position)
force = force:normalize()
local dir   = vec2(self.mass/m.body.mass, self.mass/m.body.mass)

– Magnitude of the force
local strength = (GRAVITY * self.mass * m.body.mass)/(d*d)
force = force * strength
m.body:applyForce(force)

stroke((1+math.floor(force.y))*110, (1+math.floor(force.x))*110, 10, 255)

– draw line between attractor/mover
line(m.body.x+force.x, m.body.y+force.y, (self.body.x), (self.body.y))
end

这个函数会使角色球绕着行星转。

5、线面

《拯救种子》、《蜡笔物理学》……

只有线:通过绘制线条,你可以做出形状类CHAIN的刚体和刚体类STATIC或DYNAMIC。

对于关卡设计,障碍物也是STATIC,可以是EDGE或POLYGON……

saving-seeds-hd-doodle-physics-screenshot(from gamasutra)

saving-seeds-hd-doodle-physics-screenshot(from gamasutra)

用那种结构,你可以复制出一款像《拯救种子》一样的游戏。

Box2D_Lines(from gamasutra)

Box2D_Lines(from gamasutra)

代码和第一面的是一样的,但你必须改变游戏的规则,你要从暂停的物理引擎开始,然后绘制和生成CHAIN静止形状,当玩家按下开始键时,游戏必须生成玩家的球(以及恢复、重力、质量等参数),重新开启物理引擎,只要一个指令(physics.pause() and physics.resume())就能完成了。

它只留在游戏循环中,用于确认碰撞和线性速率、改变游戏状态……

你可以通过打开或关闭重力,来改变整个游戏的现实,就像《Thomas was alone》或《ibb and obb》那样。

6、交通工具

《小轮车冒险》、《登山赛车》

如果你已经看到这里了,那么做一款关于疯狂交通工具的游戏吧。

做交通工作,只要把接头和轮子想成CIRCLE刚体,用锚点正确的旋转接头把POLYGON(小车、自行车等的形状)和它们连接起来。

用带纹理的mesh绘制自行车/小车的主要刚体、车轮的子画面,除非你使用软刚体做这些,否则添加痕迹、颗粒fx等。

代码生成的例子:

Box2D_BezierRampage(from gamasutra)

Box2D_BezierRampage(from gamasutra)

对于道路,使用一些噪点或正弦,可以是STATIC或DYNAMIC,你可以使用Bezier曲线。

code example(from gamasutra)

code example(from gamasutra)

《小轮车冒险》

我会知道这款游戏和它的物理,多亏看了某人的一篇文章。

但文章作者没有提到任何有关Box2D的东西,但我猜这款游戏就是使用了Cocos2d(和Corona SDK)。无论如何,你现在知道怎么制作交通工具和横冲直撞的效果了。

在《Canvas Rider》中,有两种自行车模型,你可以在游戏中改变,你会发现自行车的刚体是一个允许一定damping的接头结构,当你改变自行车时,这个动态刚体就被破坏了,然后游戏就生成新的自行车类型。

另外,你在游戏中的自行车可以触到的线是静态CHAIN,当你设计道路时,鼠标触击的是x,y……像我们之前做的那样。

以上。希望你能用Box2D做出一些成果。

当然,使用Box2D,通过不同的方法制作的游戏还有很多,但它们可能综合使用了上述几种,例如,《时空幻境》、《超级食肉男孩》等,用可以用合适的刚体、机制和着色器制作出来。(本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

How to create 2D Physics Games with Box2D Library

by Juan Felipe Belon Perez

If you take a look to the list of the top games in the markets, flash-games portals,etc, what can you see?, there are a lot of 2D games with an outstanding use of physics and visual arts!.

We are here today to study the physics of those games and to understand what are they made of, with Box2D.

But, more than the “what”, it is much better to know the “how”, first of all, let me ask you a question: if you would have to replicate a physics game mechanic or behaviour, will you have the skills and techniques to do so?

…I asked myself this same question more than a year ago, and the game 6 Dimensions is the answer ,it is a creative box where each dimension contains a different set of game mechanics using Box2d physics, mixed with visual art techniques, that I am sharing with you, because I made this game to improve a game engine called Codea (the guys from Crabitron), and finally, to write tutorials like this, where I wanted you and me to learn about realistic physics, art and game design…,together we are going to improve our game development skills.

I have designed 6 dimensions in my game, I’m using the same idea like a process capable of bring to your mind how are made features, so, before you say anything I’m writting near the dimension , the games from which we are replicating its physics, mechanics and art techniques.

1.The SHAPE Dimension

Thomas was alone, Angry Birds, Crayon Physics

In Crayon Physics: you can craw something in the screen with your fingers or the mouse, for example a circle, a triangle or a rectangle,and, as you release the mouse/touch, the lines will turn into a solid physical object (in the virtual world).

How do you do that?

It is pretty simple actually, you have to save each point coordinate of the trace from the mouse/touch start to end, when the release event occurs, then you call to a function of Box2D that creates a polygon with a serie of points, something like this:

local body = physics.body(POLYGON, unpack( points ) )

Some definitions:

You have to know that there is some kind of shape types in Box2D :

POLYGON:

used for closed shapes like basic geometry (not circles), it uses a list of vertices (x,y) defined with the order specified by each API

CIRCLE:

balls, water drops, planets, etc.

EDGE:

for walls, grounds,etc, Lines with only 2 points: start and end.

CHAIN:

Like edge but you can close (would be like a POLYGON but is not a convex hull) or not (like EDGE but with more than 2 points)

Once you have defined a body shape, there are different behaviours,or body types:

STATIC  : as it names says, this body will remain static in the assigned x,y (ground, wall, base for a pole or rope,etc.)

DYNAMIC : it will collide with other objects and move

KINEMATIC : collide but not move with the dynamics, you can move it not only chaging it x,y but assigning a linearVelocity or applying a force to it too well,…the exact sintaxis depends of the implementation of the API, in this article I’m using this because it is the simplest code I can find. But it would be so simple to change to actual code for any language, you can find a Box2D lib for almost every language (Flash as3, c++, objc, java, javascript, java+processing,etc), this is in ObjC. I recommend you to open the level definitions of the game Crayon Physics to understand how it works.

You have to save the result of that function to a var, then, in the draw loop of the game the properties of that body are accesible, like body.position, body.radius, body.linearVelocity, body.angularVelocity, body.mass, etc.

When the body is created, you may want to define some of its properties, there are interesting things like the restitution,gravityScale and damping, these can turn our physical object into a bouncing or floating one, for example.

Here is a sample of what can be done with this feature of Box2d.

At this point you might want go to the Ray Wenderlich site and follow some of the box2d tutorials and then come back and continue reading with more knowledge…or no.

There are more complexity in Box2D and other games ( Magic Pen ) within this dimension of physics game mechanics, you can draw some things that look likes “nodes” but developers call them “joints”, this things are used to put magic glue between bodies, there are some kind of them, depending on the mechanics you want (Codea reference for physics with Box2d , or the Nature of Code videos – processing) and they can be used to create a behaviour between the connected bodies:

physics.joint( REVOLUTE, bodyA, bodyB, anchor )

the bodies rotate about a single anchor point

- example : a wheel of a car, the red node in crayon physics and magic pen

physics.joint( PRISMATIC, bodyA, bodyB, anchorA, direction )

the bodies maintain a fixed distance between their respective anchor points. The length of a distance joint is taken from the initial distance between the two anchor points in world space. Setting the frequency and damping ratio of the joint allows for soft spring-like behaviour.

physics.joint( DISTANCE, bodyA, bodyB, anchorA, anchorB )

Prismatic joints constrain the motion of two bodies along the axis between the two specified anchor points. This allows for telescopic motion, while restricting relative rotation between the two bodies physics.joint( WELD, bodyA, bodyB, anchor )

Weld joints constrain the motion and relative rotation between two bodies, effectively turning them into a single body. Due to the iterative nature of the solver, weld joints can bend when put under stress and may fail completely when large forces are involved or several weld joints are chained together to form a larger object physics.joint( ROPE, bodyA, bodyB, anchorA, anchorB, maxLength )

Rope joints constrain the maximum distance between two bodies

Example: the ropes of Cut the Rope

Summarizing:

1) Create: a body with the points of the touch or a box definition or any other polygonal geometry (a set of 2d points:x,y), set physics properties for what we want it to (different behaviours like Thomas was alone are possible), like if the body is static, it mass, density, gravityScale, and so on.

3) Optional: attach to another body, for example, you can attach the body to a static body which is set as a sensor (not affecting world physics but has collision events) and activate the enableMotor property of the REVOLUTE joint, this also needs motorSpeed, maxMotorTorque and maxMotorForce, defines a rotation for this object. This is a result (dont pay attention to the water, we are going into it next).

3) Visual Art: You have the body, if you want to draw it, not as a shape but like a filled body with color or a texture you may want to triangularize the points to create a POLYGON-shape (mesh) and set the colors or the texture to it.

Examples:

For the behaviour of boxes from Thomas Was Alone you can set a simple “juice” system animation (evolution of tweeners), so, when you choose a cube and press the jump button (or the collision with the different physics bodies happens), it triggers the juice command = animation like squash, roll, etc., each character has its own animation params, the same goes for physics: mass, linearVelocity, damping, etc.

Angry Birds, (Ray Wenderlich has a tutorial to make that too) , you can create a level by defining different properties to the boxes, draw different sprites or meshes with textures, so, in the collision events you can drown an amount of the “life” or “resistance” of the box-body and change the texture with another one, more appropiate to the current state (broken wood, almost broken glass, broking sprite animation,etc).

You can do the launching of the bird with a simple body:applyForce(vec2(x,y)) function. Each bird has it own mass, damping, info and properties as well…

2.The WATER Dimension

Where is my water? , Sprinkle Ilsands…

When you ask to the Internet coding sages how to make water physics like those games, they end up talking you about Metaballs:

But using metaballs in a game is not so trivial and not too easy to get neither, it has high computational cost, unless you discover some trick and apply it with some art.
That’s why you dont see so many games with water physics. I started talking about this some months ago in this forum, and thanks to a lot of people I get a good water physics model for a game.

You can get it here,in the example I am using dynamic balls with CIRCLE bodies from Box2D lib (code inside videolink).

The code is easy to understand, look, the balls are just physic bodies generated with parameters to give them the behaviour of water drops, it is: restitution, friction, damping, linear velocity, then, to draw these balls we are using a technique with a shader (GLSL) and a texture, you will need a mesh to apply the shader, just like a ripple fx or other glsl shader samples that uses textures, we are setting the width and height of the area of the mesh to the whole screen, from the middle:

mesh:addRect(WIDTH / 2, HEIGHT / 2, WIDTH, HEIGHT)

this way we can use the (x,y) position of each ball to paint in the virtual space of the texture (with setContext) of the mesh rect, so, each ball is represented in the texture as a ball painted with a gradient inside the image generated of the ball (200*200) -ballTex -

for k,b in ipairs(balls) do
sprite(ballTexture, b.x, b.y)
end

then , you have to use the additive blend mode to add all the painted balls to the texture and mix them with a background and a colour.

Example:

As I said, each ball has a texture (procedurally generated) , a gradient, this was it can be mixed with other ball textures using a low level filter (the glsl shader).

Where is my water?

You can do the same water fx using different layers for each type of behaviour, or make one layer for all the liquids and one for all the dynamic terrains, then in the shader change the filter values and colors (water, lava, dirty,etc.).

An example of handling the collision within a behaviour can be:

In the collision events you must check what kind of ball is bodyA and bodyB, if one is gas (gravityScale/mass/density is practically zero, so it floats) and the other body is an “ice” polygon, then you turn the ball into water…

Another example:

if bodyA is lava and bodyB is water, you must turn bodyB into gas, …it is as easy as change the properties of the ball, so it will change the response in box2d and you do the new drawing the drawLoop of the game.

Terrain example:

the static terrains could be just a POLYGON body created with a function that read an image of the whole terrain and build a set of pairs x,y (vec2) of the non-transparent pixels, then return this to the box2d function.

Dynamic terrain could be just a mesh and when you touch it, you will remove the points over that coordinates x,y of  the touch, you have to rebuild the physics body with the new set of pairs of the mesh.

And you have just see how to create the water so, here it is an example with all together: water physics and real time terrain modification based on box2d physics.

Pickups, powerups, etc. example:

When a drop of water (physics body CIRCLE) hit a duck (physics body with sensor activated) you must delete that ball and change the animation of the duck for the new state ,until it is completly filled with water, then delete the duck and record the achievement.

Water drops have a little trail,these are drawn using the linearVelocity and angularVelocity properties, you can get the direction and the speed so you can calculate the angle and distance of the trail (opposite direction and distance based on speed).

In fact, there are as many behaviours as you want.

In Sprinkle Ilsands the water shader is different as the one we have studied, only changes something with the particles fx, it has the linearVelocity detail added too, in another way.

But the behaviour could be the same, when the water balls (physics body CIRCLE) hit a fire sensor , it applies whatever it makes the fire goes down, the same for a water mesh in the sea, in the case of a rock you could add some details like particle effects or something like that.

In this dimension we can’t find any joint,  that’s why it may be not necessary, well, in Sprinkle Islands the hose is a rope, which we are going to analyze in the next dimension, and there is a REVOLUTE joint in the hose cone…

3.The ELASTIC Dimension

Contre Jour, Cut the Rope, Ninja Fruit,…

It took me another month to have a working prototype of a rope like those top games…see this one (code inside the video info), but the soft body was easy made once I got the rope finished, as I understand the joints better.

To make a realistic rope you have to create a set of bodies (CIRCLE or POLYGON,your choice) all attached to a STATIC body, the base. The joints used to joining the bodies of the rope can be of two types, DISTANCE or REVOLUTE, but the joint that join the base (STATIC) with the final part (DYNAMIC) must be a ROPE joint to create an elastic rope. Use the restitution property and frequency (hz) to adjust the response/damping/elasticity.

Example:

Here is the ROPE (code), and this is the result (video).

To create a soft body, you have to build a set of CIRCLE bodies around another center body (circle is better), which can be STATIC or DYNAMIC, it will affect the rest of the bodies for sure, if you change the types of the joints you will realise how the body can be deformed automatically, you need to draw the whole set with a mesh.

Contre Jour

In this game, you can find soft bodies: deformable terrains; and two types of ropes:elastics and ropes with a limit, fixed. These fixed ropes uses a more advanced technique than the elastics, to draw the texture in it shapes you have the properties of the bodies and the joints, i.e., points, types, properties, etc., the method must build a mesh and apply the texture in real time, like in the previous example of the video of the soft body but these guys do this thing better:

Take a look to this: the tech behind the visual art of Contre Jour.

Cut the Rope

This is the perfect example of an Box2d physics set for a rope, the texture is dynamic also, and you can notice the weakness of it in the colors used along the mesh from the base to the ball, where it is attached the sugar.

You can build this rope as we have done in the previous example, the bubble effect can be achieved by setting the physics properties to the ball (candy): mass, density, gravityScale, it will float and you may draw the bubble after the candy with a multiply blend mode. Another way is change the body to a sensor and move it with your own gravity formula, but we are going to study this technique in the fifth dimension.

If the bubble-body-ball collides with the frog or the spikes, or the user touch the bubble, then you would animate the bubble explosion and change the physics properties of the candy again…

Example code:

if (vec2:distance( bFrog_Mouth,  bCandy ) < maxDistance) then
– change animation of the frog from “idle” to “eat”
– pause input
– tween and trigger the end of game at the end of the animation
end

4.The GRAVITY Dimension

Tiny Wings, JetPack JoyRide, Madcoaster, Whale Trail, …

In this dimension we can find a lot of games that uses forces against the gravity, but this is something that you can play with. For example, you can generate a simple terrain based on a sine function passed to the box2d function and it will return a CHAIN or EDGE shape types, STATIC bodies.

You can make your own Tiny Wings with Box2d, there is a tutorial here, and another here, the basis is that, a ball (CIRCLE body) falls with the force of gravity, you can increase the linearVelocity by touching the screen, and when the touch is released in the appropiate part (you can check the height of your sine function) of a hill it would be better for that increase amount…Another way is using only forces.

Example:

For the draw loop, add particle effects to the picking, fever states (trails), and so on. The textures can be generated using procedurally images with random colors, gaussian noises to add details, borders, etc…you can see an example here.

Jetpack Joyride

You can follow the pattern for this game?, If you have readed the previous examples you must fall into account, you have the same behaviour for the character-body-ball (CIRCLE physics body or other you want),you must be applying forces against gravity, different physics properties for each jetpack, the missile and each vehicle, etc.

The same goes for Madcoaster, Rocket Chicken, Whale Trail and those kind of games…

But this dimension includes other mechanics, like the planetary physics, gravition is a strong field :)

You can use a simple formula to simulate zero gravity with physics.gravity(0,0), the force of attraction of a planet is something like this:

More in this example.

function Planet:attract(m)
– Direction of the force
local force = self.body.position – m.body.position
local d     = force:len() — = m.body.position:dist(self.body.position)
force = force:normalize()
local dir   = vec2(self.mass/m.body.mass, self.mass/m.body.mass)

– Magnitude of the force
local strength = (GRAVITY * self.mass * m.body.mass)/(d*d)
force = force * strength
m.body:applyForce(force)

stroke((1+math.floor(force.y))*110, (1+math.floor(force.x))*110, 10, 255)

– draw line between attractor/mover
line(m.body.x+force.x, m.body.y+force.y, (self.body.x), (self.body.y))
end

this function will make the character ball to move around a planet.

5.The LINE Dimension

Saving Seeds, Crayon Physics, …

Only lines: to draw lines you can create bodies of the shape type CHAIN and body type STATIC or DYNAMIC.

For level-design, obstacles are STATIC too, could be EDGE or POLYGON…

You can replicate a game like Saving Seeds with that configuration.

Here it is an example.

The code is the same as in the first dimension but you have to change the rules of the game, you start with the physics engine paused, then draw and create the CHAIN static shapes, and when the user press the start button, the game must create the ball of the player (with it restitution, gravity, mass, etc. params) and resume the physics engine, it can be done with a single command (physics.pause() and physics.resume()).

It only remains in the game loop, to check collisions and linear Velocity, change the game state…

You can change the whole game reality by turning the gravity on or off, even for each player, like it happens in Thomas was alone or ibb and obb games.

6.The VEHICLE Dimension

Pumped BMX,  Hill Climb Racing

Make a game with rampages and vehicles, if you reach this point, you are able to do this and whatever you want with the Box2d library.

To make a vehicle, just think in joints, the wheels are CIRCLE bodies, connect them with a POLYGON ( shape of the car, bike, etc. ) using a REVOLUTE joint with the correct anchors, and you got it, the motor is enabled only for one of the wheels, back , normally.

To draw the main body of the bike/car use a mesh with a texture, sprites for the wheels, unless you are using softbodies for those, add a trail, particle fx, etc.
Example from code:

For the roads, use some noise, or a sine, and it could be STATIC or DYNAMIC, you can use a Bezier spline like this example [code].

Pumped BMX

I know this game and its physics thanks to this author article in Gamasutra.

Although he did not mention anything about Box2D, I guess is what it is used because uses Cocos2d, (and Corona SDK), which uses the lib...anyway, now you know how to create a vehicle and the rampages, go and do some tests!

Check out this game too: Canvas Rider. There are two bike models, you can change it in the game, then you will notice that the bodies of the bike set are being a joint configuration that allow some damping , when you change the bike the dynamic bodies are destructed and then the game is creating the new ones of the new bike.
Also, the lines you can touch with your bike in this game are just static CHAINs, the touches of the mouse when you are designing the road are the x,y...as we have done before.

And that's all for now, hope you enjoy coding some physics with Box2D.

Of course, there are much more games using the lib in different ways as I have mention here, but they might be using the techniques above, in a combination of our "dimensions", for example, games like Braid, Meat Boy, etc., can be done with proper definitions of bodies and mechanics, and shaders as well.(source:gamasutra)


上一篇:

下一篇: