本文译自 orx tutorials 的
physics tutorial
,六月的流光 译。最新版本见Orx 官方中文Wiki
。 本文转自六月的流光的博客
。原文链接在:http://yatusiter.blogbus.com/logs/68692886.html
。
Physics
tutorial
物理特性教程
Summary
综述
See previous
basic
tutorials
for more info about basic
object
creation
,
clock
handling
,
frames
hierarchy
,
animations
,
cameras
& viewports
,
sounds
& musics
and
FXs
.
查看之前关于
basic
object
creation
,
clock
handling
,
frames
hierarchy
,
animations
,
cameras
& viewports
,
sounds
& musics
and
FXs
.以获得更多的
信息。
This
tutorial shows how to add physical properties to objects and handle
collisions.
本
教程展示了如何为对象添加物理属性和处理碰撞。
As you can see, the physical properties are
completely data-driven. Thus, creating an object with physical
properties (ie. with a body) or without results in the exact same line
of code.
如你所见,物理
属性完全是数据驱动的。因此,可以在完全相同的一行代码创建一个拥有物理属性(即通过一个body)或没有物理属性的对象。
Objects
can be linked to a body which can be static or dynamic.
对象可以动态或
静态地链接到一个body(译注:body为Box2D中的一个概念,表示一个物理实体的概念)。
Each
body can be made of up to 8 parts.
每一个body可以由8部分组成。
A body
part is defined by:
一个body部分可以定义如下:
●
its shape (currently box,
sphere and mesh (ie. convex polygon) are the only available)
●
information about the shape size (corners for
the box, center and radius for the sphere, vertices for the mesh)
●
if no size data is specified, the shape will try
to fill the complete body (using the object size and scale)
●
collision “self” flags that defines this part
●
collision “check” mask that defines with which
other parts this one will collide
1)
(
two
parts in the same body will never collide
)
●
a flag (Solid) specifying if this shaped should
only give information about collisions or if it should impact on the
body physics simulation (bouncing, etc…)
●
various attributes such as
restitution, friction, density, …
●
它的形状(目前可用的只有箱子(
box,译注:长方体)、球体(sphere)和多边形(即 mesh,凸多边形))
●
关于形状大小的信息(箱子的拐角点,球体的球心和半径以及
凸多边形的顶点)
●
如果有没指定形状的大小数据,形状会尝试填满整个body(根据对象的大小和缩放)
●
“self”标记定义产生碰撞的部分
●
“check”掩码定义了与这部分产生碰撞的其他部分
(注释1 同一个物理的两个部分永远不会碰撞)
●
一个标记(Solid)指定了这个形状是否只给出碰撞的
信息还是应该影响body的模拟物理运动(弹跳等)
●
其他的各种属性如
弹性
(restitution)
、摩擦
(friction)、密度(density)……
In this tutorial we create static solid
walls around our screen. We then spawn boxes in the middle.
The
number of boxes created is tweakable through the config file and is 100
by default.
在
本教程中我们创建环绕我们屏幕的静态固体墙。然后我们在中间放置箱子。
要创建的箱子数目是可以通过配置文件调整的,默认为100。
The
only interaction possible is using left and right mouse buttons (or left
and right keys) to rotate the camera.
As we rotate it, we also update the
gravity vector of our simulation.
Doing so, it gives the impression that
the boxes will be always falling toward the bottom of our screen no
matter how the camera is rotated.
唯一可能的交互操作是使用鼠标的左右键(或者键盘左右方向键)来旋转摄像头。
在旋转时也将会
更新我们的模拟的重力矢量。
如此,会让我们有无论摄像头怎么旋转那些箱子都一直往我们屏幕底部掉落的感觉。
We also
register to the physics events to add a visual FXs on two colliding
objects.
By
default the FX is a fast color flash and is, as usual, tweakable in
realtime (ie. reloading the config history will apply the new settings
immediately as the FX isn't kept in cache by default).
我们也可以注册
物理事件来为两个碰撞的物体添加可视的特效(FXs)。
默认特效(FX)是一种快速的颜色闪烁,通常也是可以实时调整的(即,重新读取配置文
件会使新设置立即生效,因为特效默认是不保存在缓冲中的)。
Updating an object scale (including
changing its scale with FXs) will update its physical properties (ie.
its body).
Keep in mind that scaling an object with a
physical body is more expensive as we have to delete the current shapes
and recreate them at the correct size.
This is done this way as our current
single physics plugin is based on Box2D which doesn't allow realtime
rescaling of shapes.
更新一个对象的缩放比(包括通过FX改变它的缩放比)会更新它的物理属性(即 它的body)。
请注意改变一个
有物理特性的body对象代价是很高的,因为我们必须删除当前的形状并按正确的大小重建。
这么做是因为我
们目前唯一的物理引擎插件是基于Box2D的,它不支持实时重新缩放形状。
This tutorial does only show basic
physics and collision control, but, for example, you can also be
notified with events for object separating or keeping contact.
本教程只展示了
简单的物理特性和碰撞控制,但是,比如说,你也可以获取到对象碰撞和结束碰撞的事件。
Details
详细说明
As usual, we begin by loading our config
file, creating a clock and registering our Update function to it.
Please
refer to the
previous
tutorials
for more details.
就像往常一样,
我们会以加载配置文件,创建一个时钟并注册我们的更新函数作为开始。
请参考前面的教程(LINK)以获得更多信息。
We also
creates our walls. Actually we won't create them one by one, we'll
group them in a ChildList of a parent object.
我们也创建了我
们的墙。实时上我们并不是一个一个的创建,我们把它们在父对象中的一个ChildList组合起来。
orxObject_CreateFromConfig("Walls");
This
looks like we only create one object called Walls, but as we'll see in
the config file, it's actually a container that will spawn a couple of
walls.
这看起来我们只
是创建了一个叫做Walls的对象,但我们会在配置文件中看到,它实际上是一个会产生一堆墙的容器。
Lastly,
we create our boxes.
接着,我们创建我们的箱子。
for(i = 0; i <
orxConfig_GetU32("BoxNumber"); i++)
{
orxObject_CreateFromConfig("Box");
}
As you
can see, we don't specify anything regarding the physics properties of
our walls or boxes, this is entirely done in the config file and is
fully data-driven.
如你所见,我们并没有指定任何关于墙或箱子的属性,这些都在配置文件中完成了并且完全是数据驱动的。
We then
register to physics events.
然后我们注册到物理事件。
orxEvent_AddHandler(orxEVENT_TYPE_PHYSICS,
EventHandler);
Nothing
really new here, so let's have a look directly to our EventHandler
callback.
这
里没有什么新东西,所以我们直接看下EventHandler回调函数。
if(_pstEvent->eID ==
orxPHYSICS_EVENT_CONTACT_ADD)
{
orxOBJECT *pstObject1, *pstObject2;
pstObject1 = orxOBJECT(_pstEvent->hRecipient);
pstObject2 = orxOBJECT(_pstEvent->hSender);
orxObject_AddFX(pstObject1, "Bump");
orxObject_AddFX(pstObject2, "Bump");
}
Basically
we only handle the new contact event and we add a FX called Bump on
both colliding objects. This FX will make them flash in a random color.
基本上我们只处
理了新的联系事件并且我们增加了一个叫做Bump的FX在两个碰撞的对象上。这个FX会使得它们闪烁一种随机的颜色。
Let's
now see our Update function.
现在看看我们的Update函数。
void
orxFASTCALL Update(const orxCLOCK_INFO *_pstClockInfo, void
*_pstContext)
{
orxFLOAT fDeltaRotation = orxFLOAT_0;
if(orxInput_IsActive("RotateLeft"))
{
fDeltaRotation = orx2F(4.0f) *
_pstClockInfo->fDT;
}
if(orxInput_IsActive("RotateRight"))
{
fDeltaRotation = orx2F(-4.0f) * _pstClockInfo->fDT;
}
if(fDeltaRotation != orxFLOAT_0)
{
orxVECTOR vGravity;
orxCamera_SetRotation(pstCamera, orxCamera_GetRotation(pstCamera) +
fDeltaRotation);
if(orxPhysics_GetGravity(&vGravity))
{
orxVector_2DRotate(&vGravity, &vGravity, fDeltaRotation);
orxPhysics_SetGravity(&vGravity);
}
}
}
As you can see, we get the rotation
update from the RotateLeft and RotateRight inputs.
If a
rotation needs to be applied, we then update our camera with
orxCamera_SetRotation() and we update our physics simulation gravity
accordingly.
This way, our boxes will always look like they
fall toward the bottom of our screen, whichever the camera rotation is.
Note
the use of orxVector_2DRotate() so as to rotate the gravity vector.
如你所见,我们
从RotateLeft和RotateRight输入得到了旋转的更新。
如果需要旋转,那么我们就用orxCamera_SetRotation()
来更新摄像头并且我们更新相应的物理特性模拟的重力(矢量)。
这么做,无论摄像头怎么旋转,我们的箱子总会来看起来是向我们屏幕的底部运动。
注意使用
orxVector_2DRotate()以便旋转重力矢量。
NB: All rotations in orx's code are
always expressed in radians!
注意:orx代码中的所有的旋转总是用弧度表示!
Let's
now have a look at our config data. You can find more info on the config
parameters in the
body
section of config settings
.
First, we created implicitely many walls
using the ChildList property. See below how it is done.
现在我们看一下
我们的配置数据。你可以在
body
section of config settings
(LINK 配置设置中的body 配置段)找到更多关于配置参数的信息。
首先,我们通过
ChildList属性隐式地((译者注:原文中的implicitely应为implicitly,应该是作者笔误))创建了许多墙。实现如下:
[Walls]
ChildList
= Wall1 # Wall2 # Wall3 # Wall4; # Wall5 # Wall6
As we
can see, our Walls object is empty, it will just create Wall1, Wall2,
Wall3 and Wall4 (note the ';' ending the list there).You can remove this
';' to create 2 additional walls.
正如我们看到的,我们的墙对象为空,只是创建了Wall1、Wall2、Wall3
和Wall4 (注意 ‘;’ 在列表的结尾)。你可以移除这个 ‘;’ 新增两堵墙。
Let's now see how we define our walls
and their physical properties.
Let's begin with the shape we'll use for
both WallBody and BoxBody.
现在让我们看看怎么定义我们的墙和它们的物理属性。
让我们从我们将
要在WallBody和BoxBody中都用到的形状开始。
[FullBoxPart]
Type
= box
Restitution
= 0.0
Friction
= 1.0
SelfFlags
= 0x0001
CheckMask = 0xFFFF
Solid
= true
Density
= 1.0
Here we
request a part that will use a box shape with no Restitution (ie. no
bounciness) and some Friction.
We also define the SelfFlags and
CheckMask for this wall.
The first ones defines the identity
flags for this part, and the second ones define to which
idendity(应
该是 identity)
flags it'll be sensitive (ie. with who it'll
collide).
Basically, if we have two objects: Object1 and
Object2. They'll collide if the below expression is TRUE.
这里我们创造了
一个没有Restitution(弹性)和一点Friction(摩擦)的box (长方体)形状。
同样我们也为这
堵墙定义了 SelfFlags 和 CheckMask。
第一个(译注:SelfFlags)定义了标识标记,第二个定义了那些它会碰撞到的标
识标记
基
本上,如果我们有两个对象:Object1和Object2.如果以下条件为TRUE,它们就会发生碰撞。
(Object1.SeflFlags
& Object2.CheckMask) && (Object1.CheckMask &
Object2.SelfFlags)
NB: As we don't specify the TopLeft and
BottomRight attributes for this FullBoxPart part, it will use the full
size of the body/object that will reference it.
注意:我们没有
为这个FullBoxPart指定TopLeft 和 BottomRight 属性,所以它会使用所引用的body/object的完整尺寸。
Now we
need to define our bodies for the boxes and the walls.
现在我们需要为
这些箱子和墙定义我们的body。
[WallBody]
PartList
= FullBoxPart
[BoxBody]
PartList
= FullBoxPart
Dynamic = true
We can see they both use the same part
2)
. (they
can have up to 8 parts, but only 1 is used here)
As
Dynamic is set to true for the BoxBody, this object will move according
to the physics simulation.
For the WallBody, nothing is specified
for the Dynamic attribute, it'll then default to false, and walls won't
move no matter what happen to them.
NB: As there can't be any collision
between two non-dynamic (ie. static) objects, walls won't collide even
if they touch or overlap.
我们可以看到他们都使用相同的部分(注释2
它们最多可以使用8个部分,但这里只使用了一个)。
由于BoxBody(箱子的body)的Dynamic属性被设置为TRUE,这个对
象会根据物理特性的模拟移动。
对WallBody(墙的body),没有特别指定Dynamic属性(的值),则会默认设置为
FALSE,并且无论发生什么这些墙都不会移动。
注意:由于两个non-dynamic(即
static,译注设置Dynamic属性为FALSE或不设置)的对象之间不能发生碰撞,即便两堵墙接触或重叠它们也不会碰撞。
Now
that we have our bodies, let's see how we apply them to our objects.
First,
our boxes.
现在我们有了我们的body,让我们看看怎么把它们应用到我们的对象。
首先,我们的箱
子。
[Box]
Graphic
= BoxGraphic
Position = (50.0, 50.0, 0.0) ~ (750.0, 550.0,
0.0)
Body = BoxBody
Scale
= 2.0
As you
can see, our Box has a Body attribute set to BoxBody.
We can
also notice it's random position, which means everytime we create a new
box, it'll have a new random position in this range.
如你所见,我们
的箱子有一个被设置为BoxBody的Body属性。
我们也注意到它的位置随机,这意味着每一次我们创建一个新的箱子,它会有一个在这个范
围内的随机位置。
Let's
now see our walls.
现在看看我们的墙。
[WallTemplate]
Body =
WallBody
[VerticalWall@WallTemplate]
Graphic
= VerticalWallGraphic;
Scale = @VerticalWallGraphic.Repeat;
[HorizontalWall@WallTemplate]
Graphic
= HorizontalWallGraphic;
Scale = @HorizontalWallGraphic.Repeat;
[Wall1@VerticalWall]
Position
= (0, 24, 0)
[Wall2@VerticalWall]
Position
= (768, 24, 0)
[Wall3@HorizontalWall]
Position
= (0, -8, 0)
[Wall4@HorizontalWall]
Position
= (0, 568, 0)
[Wall5@VerticalWall]
Position
= (384, 24, 0)
[Wall6@HorizontalWall]
Position
= (0, 284, 0)
As
we can see we use inheritance once again.
First
we define a WallTemplate that contains our WallBody as a Body attribute.
We then
inherits from this section with HorizontalWall and VerticalWall. They
basically have the same physical property but a different Graphic
attribute.
Now that we have our wall templates for both
vertical and horizontal wall, we only need to specify them a bit more by
adding a position.
That's what we do with Wall1, Wall2, etc…
正如我们看到的
我们再一次使用到了继承。
首先我们定义一个包含设置为WallBody的Body属性的WallTemplate。
然后
HorizontalWall和VerticalWall从这个配置段继承。基本上它们除了一个不同的Graphic属性外拥有相同的物理属性。
现在我们有水平
和垂直的墙模板了,我们只需要再给它们添加一个位置。
这就是我们对Wall1、Wall2,等……所做的
Resources
资源
源代码:
08_Physics.c
配置文件
:
08_Physics.ini
术语:
restitution:
弹性
gravity vector :重力矢量
分享到:
相关推荐
1. **模块化设计**:Orx的核心理念之一就是模块化,它将游戏的各个部分如图形渲染、物理模拟、音频处理等分隔成独立的模块,每个模块都有明确的功能,方便开发者根据需求选择和定制。 2. **数据驱动**:Orx采用数据...
什么是ORx? ORx的名称为“ Oh-Rex”,代表Outernet ReceiverX。“ X”代表自制设备。支持的设备和配置请注意,Raspberry Pi v1是目前唯一受支持的版本。 v2具有不支持的ARM v7处理器。 此存储库中的脚本支持以下...
Orx是一款强大的便携式游戏引擎,专注于2D游戏开发,以其轻量级、灵活性和易用性而受到开发者们的欢迎。作为一个开源项目,Orx提供了完全透明的源代码,鼓励社区参与,促进了代码的持续改进和创新。 Orx的核心设计...
Orx 是一个轻量级的2D游戏引擎,它的设计目标是简洁、模块化和易于扩展。这个“非典型”之处在于它不采用常见的图形渲染管线,而是提供了一种更灵活的方式来构建游戏逻辑和视觉效果。Orx 以其小巧的体积、跨平台支持...
标题"Suz-OrX-archive-refs-heads-master.zip"似乎是一个Git仓库的归档文件,通常包含了一个Git仓库在特定提交点的所有文件和目录。这种类型的文件经常用于代码备份、版本控制或者分享代码库。"refs-heads-master...
在【标题】中提到的"IISURL重写组件(中文版)32位、64位rewrite_x32orx64_zh-CN",意味着这是适用于不同架构系统(32位和64位)的中文版本,方便中国用户使用。 【描述】中提到的"win2008以上的服务器IIS设置URL...
在协议选择方面,PELCON万用解码器支持多种品牌的协议,如PELCO-D、PELCO-P、SAMSUNG、PHILIPS、RM110、CCR-20G、HY9600、KALATEL、KODICOM、VICON、ORX-10、PANASONIC、PIH717、EASTERN、IDRS等。每个协议都有对应...
而"orx"通常是指Orx Portable Game Engine,这是一个轻量级、跨平台的游戏开发框架,它可能被用在这个项目中,作为图像处理的一部分。不过,考虑到这是一个关于图片局部放大的功能,Orx可能不是主要的库,而是可能...
声音,图形,物理,输入处理等等可以由Orx用C语言处理,而游戏逻辑则用OCaml编写。 这些绑定根据获得。 要求 奥克斯 您将需要一个有效的Orx版本。 正式的包含有关在系统上安装Orx及其依赖项的说明。 确保$ORX环境...
ORX配置对崇高文本的支持 安装 打开崇高文字, 单击菜单中的“首选项”,然后单击“浏览软件包...” 将ORX文件夹复制到那里, 完毕。 学分 我入侵了这个仓库[ ],然后添加了与ORX相关的内容。 什么是ORX? Orx...
在西门子PLC中,STL以其简洁、结构化的特性被广泛使用。以下是一些关于STL编程的基本概念和指令集: 1. **数据类型**: - **输入继电器I**: 用于接收来自输入设备的信号。 - **输出继电器Q**: 用于向输出设备发送...
在Windows操作系统中,richtx32.ocx是一个重要的ActiveX控件,主要用于处理Rich Text Format (RTF) 文档和文本编辑。这个控件在一些应用程序中是必需的,特别是那些依赖于旧版Microsoft RichEdit功能的软件。...
Run-time error '339': Component 'MSCOMCTL.OCX' or one of its dependencies not correctly registered:a file is missing or invalid. win8操作步骤 ①解压压缩包 ②将解压出来的文件,剪切至 ...
**标题解析:** "rewrite_x32orx64_zh-CN" 这个标题表明这是一个针对中文用户(zh-CN)的关于“rewrite”技术的软件包,它同时提供了32位(x32)和64位(x64)版本的解决方案。"rewrite"通常指的是URL重写技术,用于管理...
由于Bernese 5.0具有极高的数据处理精度,它在大地测量学、地球物理学、气候学、大气科学等多个领域有广泛的应用。特别是在全球和区域尺度的GPS数据处理中,软件能够提供精确的站点坐标、地壳形变和大气参数等。 综...
### Bernese GPS Software 版本 5.0 教程概览及知识点解析 #### 一、引言:示例活动介绍 在本教程中,将详细介绍如何使用 Bernese GPS 软件版本 5.0 来处理一组欧洲国际 GNSS (IGS) 网络中的八个站点数据。这些...
《ArcGIS 10 图框工具5.2详解与应用》 ArcGIS 10 图框工具5.2是一款专为ArcGIS 10及10.1版本设计的图框生成工具,它极大地简化了地图制图过程中的图框制作步骤,提高了工作效率。作为一款共享软件,它鼓励用户支持...
EPORNER 2.COM%20-%20[bpM0orx6f9R]%20
1. **设置BRx和ORx**:BRx(Base Register x)和ORx(Option Register x)用于定义内存映射的基础地址和选项,是进行UPM编程的基础。 2. **配置MxMR[OP]=01**:将操作模式设置为写入RAM阵列。 3. **向RAM阵列写入模式**...
欧罗调色板用于HTML颜色的定义。... 包含之后,您可以通过@Colors.MediumOrchid直接引用颜色名称。... 当您的编辑器支持颜色的可视化并且您可以原型化而无需使用颜色选择器工具切换到绘画程序时,这是很好的。