Box2D v2.1.0用户手册(7)——物体(Bodies)_box2d 物体类型-程序员宅基地

技术标签: 物理系统  Box2D  

第07章 物体(Bodies)


7.1 关于

物体具有位置和速度。你可以将力(forces), 扭矩(torques),冲量(impulses)应用到物体上。 物体可以是静态的(static), 运动但不受力的(kinematic), 和动态的(dynamic)。这是物体的类型定义:

b2_staticBody

static物体在模拟时不会运动,就好像它具有无穷大的质量。在Box2D内部,会将static物体的质量存储为零。static物体可以让用户手动移动,它速度为零,另外也不会和其它static或kinematic物体相互碰撞。

b2_kinematicBody

kinematic物体在模拟时以一定速度运动, 但不受力的作用。它们可以让用户手动移动,但通常的做法是设置一定速度。kinematic物体的行为表现就好像它具有无穷大的质量,Box2D将它的质量存储为零。kinematic物体并不会和其它static或kinematic物体相互碰撞。

b2_dynamicBody

dynamic物体被完全模拟。它们可以让用户手动移动,但通常它们都是受力的作用而运动。dynamic物体可以和其它所有类型的物体相互碰撞。dynamic物体的质量总是有限大的,非零的。如果你试图将它的质量设置为零,它会自动地将质量修改成一千克。

物体是fixtures的骨架,带着fixture在世界中运动。Box2D中的物体总是刚体(rigid body)。也就是说,同一刚体上的两个fixture,永远不会相对移动。

fixture有可碰撞的几何形状和密度(density)。物体通常从它的fixture中获得质量属性。当物体构建之后,你也可以改写它的质量属性。这将在下面讨论到。

通常你会保存所有你所创建物体的指针,这样你就能查询物体的位置,用于更新图形实体的位置。另外在不需要它们的时候,你也可以使用指针去摧毁它们。


7.2 物体定义(Body Definition)

在创建物体之前你需要先创建物体定义(b2BodyDef)。物体定义含有初始化物体所需的数据。

Box2D会从物体定义中拷贝出数据, 并不会保存它的指针。这意味着你可以重复使用同一个物体定义去创建多个物体。

让我们看一些物体定义的关键成员。

物体类型(Body Type)

本章开始已经说过,有三种物体类型: static, kinematic, 和dynamic。 你应该在创建时就确定好物体类型,因为以后再修改的话,代价会很高。

bodyDef.type = b2_dynamicBody;

物体类型是一定要设置的。

位置和角度(Position and Angle)

物体定义为你提供了一个在创建时初始化位置的机会。这比在world原点下创建物体后再移动到某个位置更高效。

注意

不要在原点创建物体后在移动它。如果你在原点上同时创建了几个物体,性能会很差。

物体上主要有两个让人感兴趣的点。第一个是物体的原点。fixture和关节都是相对于原点而依附到物体上面的。第二个是物体的质心。质心由形状的质量分布决定,或显式地由b2MassData设置。Box2D内部许多计算都要使用物体的质心, 例如b2Body会存储质心的线速度。

当你构造物体定义的时候,可能你并不知道质心在哪里。你可以会指定物体的原点,也可以会以弧度指定物体的角度, 角度并不受质心位置的影响。如果随后你改变了物体的质量属性,那么质心也会随之移动,但是原点以及物体上的形状和关节都不会改变。

bodyDef.position.Set(0.0f, 2.0f);// body的原点

bodyDef.angle = 0.25f * b2_pi;// 弧度制下body的角

阻尼(Damping)

阻尼用于减小物体在世界中的速度。阻尼跟摩擦有所不同,摩擦仅在物体有接触的时候才会发生。阻尼并不能取代摩擦,往往这两个效果需要同时使用。

阻尼参数的范围可以在0到无穷大之间, 0表示没有阻尼,无穷大表示满阻尼。通常来说,阻尼的值应 该在0到0.1之间。通常我不使用线性阻尼, 因为它会使物体看起来有点漂浮。

bodyDef.linearDamping = 0.0f;

bodyDef.angularDamping = 0.01f;

阻尼类似稳定性与性能, 在值较小的时候阻尼效应几乎不依赖于时间步, 值较大的时候阻尼效应将随着时间步而变化。如果你使用固定的时间步(推荐)这就不是问题了。

休眠参数(Sleep Parameters)

休眠是什么意思? 模拟物体的成本是高昂的,所以如果物体更少,那模拟的效果就能更好。当物体停止了运动时, 我们会希望停止模拟它。

当Box2D确定一个物体(或一组物体)已停止移动时,物体就会进入休眠状态。休眠物体只消耗很小的 CPU开销。如果一个醒着的物体接触到了一个休眠中的物体,那么休眠中的物体就会醒过来。当物体上的关节或触点被摧毁的时候,它们同样会醒过来。你也可以手动地唤醒物体。

通过物体定义,你可以指定一个物体是否可以休眠,或者创建一个休眠的物体。

bodyDef.allowSleep = true;

bodyDef.awake = true;

固定旋转(Fixed Rotation)

你可能想一个刚体,比如某个角色,具有固定的旋转角。这样物体即使在负载下,也不会旋转。 你可以设置fixedRotation来达到这目的:

bodyDef.fixedRotation = true;

固定旋转标记使得转动惯量被设置成零。

子弹(Bullets)

游戏模拟通常以一定帧率(frame rate)产生一系列的图片。这就是所谓的离散模拟。在离散模拟中,在一个时间步内刚体可能移动较大距离。如果一个物理引擎没有处理好大幅度的运动,你就可能会看见一些物体错误地穿过了彼此。这被称为隧穿效应(tunneling)。

默认情况下,Box2D会通过连续碰撞检测(CCD)来防止动态物体穿越静态物体。这是通过扫描形状从旧 位置到新位置的过程来完成的。引擎会查找扫描中的新碰撞,并为这些碰撞计算碰撞时间 (TOI)。物体会先被移动到它们的第一个TOI,然后一直模拟到原时间步的结束。

一般情况下,dynamic物体之间不会应用CCD,这是为了保持性能。在一些游戏环境中你需要在动态物体上也使用CCD。比如,你可能想用一颗高速的子弹去射击一块动态的砖头。没有CCD,子弹就可能会隧穿砖头。

在Box2D中,高速移动的物体可以标记成子弹(bullet)。子弹跟static或者dynamic物体之间都会执行CCD。你需要按照游戏的设计来决定哪些物体是子弹。如果你决定一个物体应该按照子弹去处理,使用下面的设置。

bodyDef.bullet = true;

子弹标记只影响dynamic物体。

Box2D执行连续碰撞检测,所以子弹也有可能会错过快速移动的物体。

活动状态(Activation)

你可能希望创建一个物体并不参与碰撞和动态模拟。这状态跟休眠有点类似,但并不会被其它物体唤醒,它上面的fixture也不会 被放到broad-phase中。也就是说,物体不会参于碰撞检测,光线投射(ray casts)等等。

你可以创建一个非活动的物体,之后再激活它。

bodyDef.active = true;

关节也可以连接到非活动的物体。但这些关节并不会被模拟。你要小心,当激活物体时,它的关节不会被扭曲(distorted)。

用户数据(User Data)

用户数据是个void指针。它让你将物体和你的应用程序关联起来。你应该保持一致性,所有物体的用户数据都指向相同的对象类型。

b2BodyDef bodyDef;

bodyDef.userData = &myActor;


7.3 物体工厂(Body Factory)

物体使用world类提供的工厂来创建和摧毁。这让world可以通过一个高效的分配器来创建物体,并且把物体加入到world的数据结构中。

物体可以是dynamic或static的,这取决于质量属性。两种类型物体的创建和摧毁方法都是一样的。


b2Body* dynamicBody =myWorld->CreateBody(&bodyDef);

... do stuff ...

myWorld->DestroyBody(dynamicBody);

dynamicBody = NULL;

注意

永远不要使用new或malloc来创建物体, 否则世界不会知道这个物体的存在,并且物体也不会被适当地初始化。

static物体不会受其它物体的作用而移动。你可以手动地移动static物体,但你必须小心,不要挤压到static物体之间的dynamic物体。另外,当你移动static物体的时候,摩擦不会正确工作。static物体不会和其它static或kinematic物体碰撞。在单个static物体上附加数个形状, 要比多个static物体都只附加单个形状,有更好的性能。在内部, Box2D会设置static物体的质量为零。这使得大部分算法都不必把静态物体当成特殊情况来看待。

Box2D并不保存物体定义的引用,也不保存其任何数据(除了用户数据指针)。所以你可以创建临时的 物体定义, 并重复利用它。

Box2D允许你通过删除b2World对象来摧毁物体,它会为你做所有的清理工作。然而, 你必须小心地将保存在游戏引擎的body指针清零。

当你摧毁物体时,依附其上的fixture和joint都会自动被摧毁。了解这点,对你如何管理fixture和joint指针有重要意义。


7.4 使用物体(Using a Body)

在创建完一个物体之后,你可以对它进行许多操作。其中包括设置质量,访问其位置和速度,施加力,以及转换点和向量。

质量数据(Mass Data)

每个物体都有质量(标量), 质心(二维向量)和转动惯性(标量)。对于static物体,它的质量和转动惯性都是零。当物体设置成固定旋转(fixed rotation),它的转动惯性也是零。

通常情况下,当fixture添加到物体上时,物体的质量属性会自动地确定。你也可以在运行时(run-time)调整物体的质量。你有特殊的游戏方案,需要改变质量时,可以这样做。

void SetMassData(const b2MassData* data);

直接设置物体的质量后,你可能希望再次使用fixture来指定质量。可以这样做:

void ResetMassData();

要得到物体的质量数据,可以通过下面的函数:

float32 GetMass() const;

float32 GetInertia() const;

const b2Vec2& GetLocalCenter()const;

void GetMassData(b2MassData* data)const;

状态信息(State Information)

物体的有多个方面状态。你可以通过下面的函数高效地访问状态数据:

void SetType(b2BodyType type);

b2BodyType GetType();

 

void SetBullet(bool flag);

bool IsBullet() const;

 

void SetSleepingAllowed(bool flag);

bool IsSleepingAllowed() const;

 

void SetAwake(bool flag);

bool IsAwake() const;

 

void SetActive(bool flag);

bool IsActive() const;

 

void SetFixedRotation(bool flag);

bool IsFixedRotation() const;

位置和速度(Position and Velocity)

你可以访问一个物体的位置和旋转角, 这在你渲染相关游戏角色时很常用。通常情况下,你都是使用Box2D来模拟运动,也可以设置位置, 但不怎么常用。

bool SetTransform(const b2Vec2&position, float32 angle);

const b2Transform&GetTransform() const;

const b2Vec2& GetPosition()const;

float32 GetAngle() const;

你可以访问本地坐标系及世界坐标下的质心。许多Box2D的内部模拟都使用质心。通常你不必访问质心。取而代之, 你一般应该关心物体变换。比如,你有个正方形的物体。物体的原点可能在正方形的一个角点,而质心却位于正方形的中心点。

const b2Vec2& GetWorldCenter()const;

const b2Vec2& GetLocalCenter()const;

你可以访问线速度与角速度,线速度是对于质心所言的。所以质量属性改变了,线速度有可能也会改变。


转载:http://blog.csdn.net/complex_ok/article/details/6723390

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/linmy1211/article/details/39080945

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签