HTML5之2D物理引擎 Box2D for javascript Games 系列 第二部分

这是系列第二部分,之前部分在本博客中找

源码demo存放在https://github.com/willian12345/Box2D-for-Javascript-Games

向世界添加刚体



刚体(Bodies)是我们用Box2D创建物理游戏的重要对象。任何你可以移动的或交互 的对象都是刚体(Bodies)。

愤怒的小鸟(Angry Birds)中创建的小鸟和小猪是刚 体,同样在图腾破坏者(Totem Destroyer)中的黄金神像和图腾砖块也是刚体。

本章将带你学习创建各种类型的Box2D刚体,此外还有一些其它重要的特性,如下表所列

• 创建圆形刚体?

• 创建矩形刚体?

• 创建任意多边形刚体

• 使用DebugDraw()方法测试模拟

• 定义刚体的类型:static,dynamic或kinimatic?

• 设置材质属性:密度(density),摩擦系数(friction)和恢复系数(resitution)

• 度量单位?

• 创建合成对象

通过本章的学习,你将会创建一个你的第一个图腾破坏者类型的游戏。本章有较

多的知识点,那么我们废话少说,直接开始本章的学习吧!

你的第一个模拟—一个球落地



我们先从简单的任务开始,最简单的物理模拟:一个球落到地面。总之,虽然

这是一个简单小球落地的模拟,但是它将是你的第一个模拟,并且易于很快实

现它。

让我们看看在这次模拟中我们要做些什么:

• 世界的重力(gravity)?

• 一个受到作用力(例如:重力(gravity))的球

• 一个不受任何作用力的地面?

• 某种材质,正如我们希望小球在地面弹起的材质

在之前的学习中,你已经能够配置世界的重力了,所以我们从创建小球开始本章的代

码编写。

1. 无论我们是创建球形还是多边形,第一步都是创建一个刚体:

  var bodyDef =new b2BodyDef();

  b2BodyDef类是一个刚体的定义类,它将持有创建我们刚体所需要的所有数 据。

2. 现在可以将刚体添加到世界中。因为我们采用的舞台尺寸是640X480,我们将 把球放置在舞台的顶部的中心位置,该位置为(320,30),如下所示:

  bodyDef.position.Set(10.66,1);

  通过position属性显示的设置了刚体在世界中的位置,但是我确信你会对我之前 所说的位置为(320,30)的设置而变成(10.66,1)而感到困惑。

  这原因要关系 到度量单位上。虽然Flash是以像素(pixels)为度量单位,但是在Box2D中尝试 模拟真实的世界并采用米(meters)作为度量单位。

  对于米(meters)和像素 (pixels)之间的转换没有通用的标准,但是我们采用下面的转换标准可以有很 好的运行效果:

  1米 = 30像素

  所以,如果我们定义一个变量来帮助我们将米(meters)转换成像素 (pixels),我们便可以在Box2D世界(world)中进行操作时使用像素 (pixels)而不用使用米(meters)来作为度量单位。

  这样将使我们在制作 Flash游戏时,使用像素来思考,从而变得更加直观。

3. 打开你在第一章中创建的demo1-1.html,并像下面那样修改它:

  

<script>
         function init(){
            var b2Vec2 = Box2D.Common.Math.b2Vec2
            ,b2AABB = Box2D.Collision.b2AABB
            ,b2BodyDef = Box2D.Dynamics.b2BodyDef
            ,b2Body = Box2D.Dynamics.b2Body
            ,b2FixtureDef = Box2D.Dynamics.b2FixtureDef
            ,b2Fixture = Box2D.Dynamics.b2Fixture
            ,b2World = Box2D.Dynamics.b2World
            ,b2MassData = Box2D.Collision.Shapes.b2MassData
            ,b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
            ,b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
            ,b2DebugDraw = Box2D.Dynamics.b2DebugDraw
            ,b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef
            ;

            var world;
            var worldScale = 30;
            function main(){
               world = new b2World(new b2Vec2(0, 9.81), true);
               var bodyDef = new b2BodyDef();
               bodyDef.position.Set(320/worldScale,30/worldScale);

               setInterval(updateWorld, 1000 / 60);
            }
            function updateWorld() {
               world.Step(1/30,10,10);
               world.ClearForces(); // 清除作用力
            }

            main();
         }
         init();
</script>

并且,注意我是怎样创建世界和调用step方法的。这比之前少用了几行代码。

一旦你创建了刚体定义,那么是时候给它一个形状了。

创建一个圆形形状



形状(shape)是一个2D几何对象,例如一个圆形或者多边形,在这里必须是凸多边

形(每一个内角小于180度)。记住,Box2D只能处理凸多边形

现在,我们从小球开始,所以我们创建一个圆形:

var circleShape =new b2CircleShape(25/worldScale);

b2CircleShape是用来创建圆形形状,并且它的构造函数需要一个半径(radius)作为 参数。

在之前的代码中,我们创建了一个圆形,它的半径为25像素(pixels),由于设 置了worldScale变量。

从现在起,每次你想要使用像素进行操作时,你只要将它们除以 worldScale即可。你也可以定义一个方法名为pixelsToMeters的方法,在每次你需要将像 素(pixels)转换成米(meters)时调用。

当我们有了刚体定义和形状时,我们将使用夹具(fixture)来将它们粘合起来。

创建夹具



夹具(fixture)用于将形状绑定到刚体上,然后定义它的材质,设置密度 (density),摩擦系数(friction)以及恢复系数(restitution)。

此刻我们无需去 担心材质,让我们把注意力集中到夹具(fixture)上:

1.首先,我们创建夹具(fixture):?

  

var fixtureDef = new b2FixtureDef();
fixtureDef.shape=circleShape;

  一旦我们通过构造函数创建了夹具(fixture),我们将分配之前创建 的形状给它的shape属性。

2.最后,我们准备将球添加到世界中:?

  

var theBall =world.CreateBody(bodyDef);
theBall.CreateFixture(fixtureDef);

b2Body是刚体的实体:是物质,是通过使用bodyDef属性创建的具 体刚体。

3.再次说明一下,使用以下步骤将刚体添加到世界中:

  I 创建一个刚体定义,它将持有刚体信息,例如刚体的位置信息。

  II 创建一个形状,它将决定刚体的显示形状

  III. 创建一个夹具,将形状附加到刚体定义上。

  IV. 创建刚体在世界中的实体,使用夹具。

一旦你知道了每一步的重要性,添加刚体到你的Box2D世界中将会 很容易和有趣

回到我们的项目。现在的main函数内应该看起来和下面一样:

function main(){
               world = new b2World(new b2Vec2(0, 9.81), true);
               var bodyDef = new b2BodyDef();
               bodyDef.position.Set(320/worldScale,30/worldScale);
               var circleShape = new b2CircleShape(25/worldScale);
               var fixtureDef = new b2FixtureDef();
               fixtureDef.shape = circleShape;
               fixtureDef.density = 1;
               fixtureDef.restitution = .6;
               fixtureDef.friction = .1;
               var theBall = world.CreateBody(bodyDef);
               theBall.CreateFixture(fixtureDef);

               setInterval(updateWorld, 1000 / 60);
}

定时保存项目并测试它。准备好看看你的第一个Box2D刚体的活动?运行影片!

额…,然而你现在运行时还是看不到任何东西。。让我告诉你原因,Box2D只负责模拟物理世界,而不负责显示任何东西。

这意味着,你的刚体正活跃在你的Box2D世界中,只是你看不到而已。

使用调试绘图测试你的模拟



幸运的是,Box2D有一个特性,调试绘图(debug draw),它将帮助你显示出模拟的情况:

在网页中首先要添加一个canvas如

<canvas id="canvas" width="640" height="480" style="" ></canvas>

1.调试绘图(debug draw)将Box2D世界中发生的事情显示出来,在

updateWorld方法中,我们可以在Step()方法之后调用世界(world)的 DrawDebugData()方法:

world.DrawDebugData();

2. 一旦我们告知世界在每次遍历之后显示调试绘图(debug draw),我们需要通 过调试绘图(debug draw)定义视觉设置。如下添加代码到你的main函数内:

var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
debugDraw.SetDrawScale(worldScale);
debugDraw.SetFillAlpha(0.5);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);

3.这里有很多代码,所以让我们来解释一下发生了什么。你已经知道 DrawDebugData()方法代表什么,所以我们将解释其它行代码代表的意思:

  

var debugDraw = new b2DebugDraw();

b2DebugDraw是一个类,它支持调试绘图(debug draw)出你的游戏中的物理 实体。

 var debugSprite:Sprite = new Sprite();

debugSprite被添加到显示列表(Display List),准备显示在canvas上。

debugDraw.SetSprite(debugSprite);

SetSprite()方法告知debugSprite将要被用来显示调试绘图 (debug draw)。

debugDraw.SetDrawScale(worldScale);

因为我们要将米(meters)转变为像素(pixels),我们需要通知调试绘 图(debug draw)我们使用的换算比例。 debugDraw.SetFlags(b2DebugDraw.e_shapeBit);

SetFlag()方法允许我们决定我们将在调试绘图(debug draw)中描绘的物 理实体的类型。此刻,我们只需要绘制形状。

补充说明:

setFlag()方法选择性的绘制Box2D对象的内容。这样可以节省CPU开支。setFlag()方法有一个16进制的参数,这参数的取值只能是b2DebugDraw中定义的下面几个常量

另外,我们还可以用”或”运算符,同时使用多个Flag

debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);

debugDraw.SetFillAlpha(0.5);

SetFillAlpha()方法是为了便于观看而设置的。形状的轮廓是不透明的,填 充的颜色是半透明的。这将使得调试绘图输出更加易于理解。

world.SetDebugDraw(debugDraw);

最后,我们将指派调试绘图(Debug draw)到我们刚刚创建的世界(world)

4.现在是时候来测试一下你影片了,然后你应该会看到下图所示的样子:

就这样!你设法看到了你放置在Box2D世界中的刚体。

目前,球体还无法在重力的作用下下落,但是不要担心,我们将在稍后修改它。

现在,让我们来创建一些可以作为地面的东西,例如一个放置在舞台底部边缘的大矩

形。从现在开始一切将更加简单,作为新的刚体将会很快的自动显示在它所添加的世界中。

完整源码在demo2-1.html中查看

创建矩形形状



让我执行下面的步骤:

  1.首先,刚体和夹具的定义可以重指定到我们定义的新的刚体上。这样,我 们无需再去定义bodyDef变量,但是我们要改变原先在创建球时使用的坐 标:?

bodyDef.position.Set(320/worldScale,470/worldScale); 

  2.我们将用b2PolygonShape类创建一个多边形:  

var polygonShape = new b2PolygonShape(); 

  这样,我们以之前创建圆形形状时,相同的方法创建了一个多边形形状。

  3.多边形形状必须遵守一些限制,但是目前,因为我们只需要一个轴对称的矩 形,SetAsBox()方法便能满足我们的需要: ? 

polygonShape.SetAsBox(320/worldScale,10/worldScale);

  这个方法需要两个参数:矩形的半宽长和半高长。最后,我们的新多边形形状 的中心在像素(320,470),它的宽度为640像素和高度为20像素——这是我们 刚刚创建的地面的尺寸。 ?

  4.现在,我们改变定义的夹具的shape属性,附加新的多边形形状: 

fixtureDef.shape = polygonShape; 

  5.最后,我们可以创建刚体并将夹具附加上去,就像我们在球形上做的那样。

var theFloor = world.CreateBody(bodyDef);
theFloor.CreateFixture(fixtureDef); 

  6.你的main方法应该向下面这样:

function main(){
               world = new b2World(new b2Vec2(0, 9.81), true);
               var bodyDef = new b2BodyDef();
               bodyDef.position.Set(320/worldScale,30/worldScale);
               var circleShape = new b2CircleShape(25/worldScale);
               var fixtureDef = new b2FixtureDef();
               fixtureDef.shape = circleShape;
               fixtureDef.density = 1;
               fixtureDef.restitution = .6;
               fixtureDef.friction = .1;
               var theBall = world.CreateBody(bodyDef);
               theBall.CreateFixture(fixtureDef);

               // 定义矩形地面
               bodyDef.position.Set(320/worldScale, 470/worldScale);
               bodyDef.type = b2Body.b2_staticBody;
               var polygonShape = new b2PolygonShape();
               polygonShape.SetAsBox(320/worldScale, 10/worldScale);
               fixtureDef.shape = polygonShape; // 复用夹具

               var theFloor = world.CreateBody(bodyDef);
               theFloor.CreateFixture(fixtureDef);

                //setup debug draw
               var debugDraw = new b2DebugDraw();
               debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
               debugDraw.SetDrawScale(worldScale);
               debugDraw.SetFillAlpha(0.5);
               debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
               world.SetDebugDraw(debugDraw);

               setInterval(updateWorld, 1000 / 60);
            }

  7.测试影片,你将会看到地面:

  

完整源码在demo2-2.html中查看

你看是不是很简单?我们花了将近一章半去防止我们的第一个刚体,然后只花了很

少的几行代码添加另一个刚体。

不同的刚体类型——static,dynamic和 kinematic



有三种Box2D刚体的类型:staitc,dynamic和kinematic。

一个static类型的刚体不受任何力,冲量或撞击的影响并且不会移动。它只能通过 用户手动移动。默认情况下,所有的Box2D刚体都是static类型的刚体,这就是为什 么球不移动的原因。一个static类型的刚体不会和别的static或kinematic类型的刚体发 生碰撞。

一个dynamic类型的刚体受力,冲量,撞击以及任何世界事件的影响。它可以通过 手动移动,虽然我建议让它们通过世界的重力,和任何类型刚体的碰撞来移动。

一个kinematic类型的刚体是一个介于static和dynamic刚体之间的混合刚体。它不 受理的影响,但是可以通过手动和设置它们的速率来移动。它不能和static和 kinematic类型的刚体碰撞。

现在回到我们的 模拟钟来。那种类型是我们要指派给球和地面的呢?

地面是static类型的刚体,它无需移动,然而通过世界重力球要移动,所以是 dynamic类型的刚体。

你只需要设置刚体定义的type属性就能告知Box2D每一个刚体的类型,属性值可以是

b2Body.b2_staticBody, b2Body.b2_dynamicBody或b2Body.b2_kinematicBody分别对应 static,dynamic或kinematic刚体。

为球添加上bodyDef.type=b2Body.b2_dynamicBody;?

地面添加上bodyDef.type=b2Body.b2_staticBody;?

你的新main方法向下面这样:

function main(){
               world = new b2World(new b2Vec2(0, 9.81), true);
               var bodyDef = new b2BodyDef();
               bodyDef.position.Set(320/worldScale,30/worldScale);
               bodyDef.type = b2Body.b2_dynamicBody;
               var circleShape = new b2CircleShape(25/worldScale);
               var fixtureDef = new b2FixtureDef();
               fixtureDef.shape = circleShape;
               var theBall = world.CreateBody(bodyDef);
               theBall.CreateFixture(fixtureDef);

               // 定义矩形地面
               bodyDef.position.Set(320/worldScale, 470/worldScale); // 复用定义刚体
               bodyDef.type = b2Body.b2_staticBody;
               var polygonShape = new b2PolygonShape();
               polygonShape.SetAsBox(320/worldScale, 10/worldScale);
               fixtureDef.shape = polygonShape; // 复用夹具

               var theFloor = world.CreateBody(bodyDef);
               theFloor.CreateFixture(fixtureDef);

                //setup debug draw
               var debugDraw = new b2DebugDraw();
               debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
               debugDraw.SetDrawScale(worldScale);
               debugDraw.SetFillAlpha(0.5);
               debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
               world.SetDebugDraw(debugDraw);

               setInterval(updateWorld, 1000 / 60);
}

在恭喜你运行成功你的第一个模拟之前,让我们花点时间来说一下关于当使用调试 绘图(debug draw)时的不同颜色。

static类型的刚体将会绘制成绿色。dynamic类型的刚体,当它们没有在睡眠状态 时将会绘制成红色,在睡眠状态时将会绘制成灰色。

kinematic类型的刚体,在之 前的屏幕截图中没有显示,它将会被显示为蓝色。

现在,我们知道当刚体进入睡眠状态并节约CPU资源这个概念。正如你所见, 当球撞击地面,没有别的里影响它时,所以求可以进入睡眠状态,知道有什么 发生为止。

现在,有一个新的问题。球在落地后没有弹起。如果我们想要运行一个完美的模

拟,我们需要给我们的刚体一些更多的属性。

密度,摩擦和恢复



正如你已经知道怎样向世界添加刚体,那么我想向你介绍三种将会改变刚体行为

的属性:密度,摩擦和恢复。

密度(density)用来设置刚体的质量,按照公斤没平方米。越高的密度意味着越 重的刚体,并且该值不能为负。

摩擦(friction)在两个刚体在彼此的表面上移动时产生,它是通过一个系数来定 义的,通常它的范围在0(没有摩擦)-1(最大摩擦)之间。它不能为负数。

恢复(restitution)决定刚体在发生碰撞时反弹的程度。与密度(density)和摩擦 (friction)一样,它不能为负数并且它是一个介于0-1的系数来定义的。

一个小球 在恢复为0时落向地面,不发生反弹(无弹性碰撞),反之恢复为1时小球将会以此刻撞击时相同的速率弹起(完全弹性碰撞)。

密度(density),摩擦(friction)和恢复(restitution)必须添加到夹具上,所以在main方法中添加以下几行代码:?

fixtureDef.density=1;?

fixtureDef.restitution=0.6;?

fixtureDef.friction=0.1;?

在你的main函数内看起来应该这样

function main(){
               world = new b2World(new b2Vec2(0, 9.81), true);
               var bodyDef = new b2BodyDef();
               bodyDef.position.Set(320/worldScale,30/worldScale);
               bodyDef.type = b2Body.b2_dynamicBody;
               var circleShape = new b2CircleShape(25/worldScale);
               var fixtureDef = new b2FixtureDef();
               fixtureDef.shape = circleShape;
               fixtureDef.density = 1;
               fixtureDef.restitution = .6;
               fixtureDef.friction = .1;
               var theBall = world.CreateBody(bodyDef);
               theBall.CreateFixture(fixtureDef);

               // 定义矩形地面
               bodyDef.position.Set(320/worldScale, 470/worldScale); // 复用定义刚体
               bodyDef.type = b2Body.b2_staticBody;
               var polygonShape = new b2PolygonShape();
               polygonShape.SetAsBox(320/worldScale, 10/worldScale);
               fixtureDef.shape = polygonShape; // 复用夹具

               var theFloor = world.CreateBody(bodyDef);
               theFloor.CreateFixture(fixtureDef);

                //setup debug draw
               var debugDraw = new b2DebugDraw();
               debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
               debugDraw.SetDrawScale(worldScale);
               debugDraw.SetFillAlpha(0.5);
               debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
               world.SetDebugDraw(debugDraw);

               setInterval(updateWorld, 1000 / 60);
            }

我向夹具指派一次属性,而所有的刚体都将使用这个相同的夹具。在本书的整个

讲解过程中,我们将要处理很多夹具的属性,但是目前让我们只需要设置小球弹跳即可。

测试demo2-3.html,你就会发现小球在弹跳

祝贺你!你刚刚完成了你的第一个真实的Box2D项目,那么现在你有能力去创建 基础的形状和为它们分配特性和属性。

接下去让我开始来创建一个准游戏吧…



注:转载请注明出处博客园:sheldon-二狗-偷饭猫([email protected])

https://github.com/willian12345

时间: 2024-10-21 16:51:21

HTML5之2D物理引擎 Box2D for javascript Games 系列 第二部分的相关文章

HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js

太久没有更新了,新年回来工作,突然有收到网友的邮件提问,居然还有人在关注,惭愧,找了下电脑上还有一点儿存着,顺便先发这一个番外篇吧,好歹可以看到真实的效果,等我考完英语,一定会更新下一章,"愤怒的小鸟篇" 此篇,并不是书中的篇符,而是通过希望通过结合实际的canvas 绘图库实现box2d物理引擎在各绘图库上应用,绘图库网上有很多现成的 如:createjs, pixi.js 等,Egret或者其它游戏引擎有自己的物理引擎扩展库,所以就不说了. 现在通过之前的学习,基本掌握了刚体等基础

Matter.js – 你不能错过的 2D 物理引擎

Matter.js 是一个 JavaScript 2D 刚体物理引擎的网页.Matter.Engine 模块包含用于创建和操作引擎的方法.这个引擎是一个管理更新和渲染世界的模拟控制器. Matter.js 目前是测试版本,这意味着 API 仍在开发中,可能偶尔会发生变化. 在线演示      源码下载 您可能感兴趣的相关文章 网站开发中很有用的 jQuery 效果[附源码] 分享35个让人惊讶的 CSS3 动画效果演示 十分惊艳的8个 HTML5 & JavaScript 特效 Web 开发中很

cocos2dx-3.x物理引擎Box2D介绍

物理引擎 Cocos2d-x引擎内置了两种物理引擎,它们分别是Box2D和Chipmunk,都是非常优秀的2D物理引擎,而且x引擎将它们都内置在SDK中.Box2D使用较为广泛,在这里选择Box2D来进行学习.  物理引擎模拟的内容: 重力:在游戏中模拟重力加速度,当游戏中人物跳跃起来后会受到重力影响而向下移动,在没有地面的场景,人物和物体会由于重力而做自由落体运动.牵引力(动力):在游戏中比如汽车的引擎,人物本身能够提供向前进行的动力,这种牵引力是持续不断地作用在物体上的,物体因此可以向作用力

2D物理引擎--开坑篇

你们还记力学和向量吗?有了这两宝就可以写物理引擎了诶~给读书无用论一个漂亮的耳光. 最近闲来无事,一拍脑门,不如写一个 2D 的物理引擎吧.自己刚好会一门图形编程的框架– QtQuick ,于是决定使用 QtQuick+JavaScript 写一个简单的 2D 物理引擎,支持圆形的碰撞检测与碰撞反应. 虽然网络上有提供一些文章介绍怎么做一个简单的 2D 物理引擎, 例如: 为 JavaScript 游戏构建一个简单的 2D 物理引擎 但是为了构造一个简单的 2D 物理引擎,至少需要具备如下知识:

制作简单的2D物理引擎(零)

最近发现了Github上的开源物理引擎项目Matter.js,对它很感兴趣,发现源码并不算长,算上注释大约1万行左右,值得剖析一番.Matter.js实现一个最小化的2D物理引擎,性能不错,故打算用C#重写并学习之. 由于JS是弱类型,而C#是强类型的,所以不得不还原相应的类型.在重写过程中,我也发现了源码中的一些问题,以及代码冗余,不过都无关紧要.在一万行之内实现一个简单的物理引擎本来就很令人激动了,这样可以以最小的工作量来熟悉物理引擎. 重写过程中,渲染用自带GDI实现,所以只需考虑物理引擎

深入理解javascript作用域系列第二篇——词法作用域和动态作用域

× 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极易出错.这实际上是由两种作用域工作模型导致的,作用域分为词法作用域和动态作用域,分清这两种作用域模型就能够对变量查找过程有清晰的认识.本文是深入理解javascript作用域系列第二篇——词法作用域和动态作用域 词法作用域 第一篇介绍过,编译器的第一个工作阶段叫作分词,就是把由字符组成的字符串分解成

一个不靠谱的2D物理引擎(4) - 裁剪出碰撞点(manifold)

主要参考: http://www.codezealot.org/archives/394 , 建议阅读 第一篇已经解决了如何判断两个图形是否相交以及求嵌入深度. 之后还需要求两物体的接触点. 实际上物体的接触部分可以是一个面, 叫做manifold. 2D下就是一条线段. 对于两个多边形的碰撞, 首先要找出两个多边形相互离得最近的两条边. 在第一篇的修改版的getAxisLeastPenetration函数已经完成了这个工作. 把polyA和polyB相互交换作为该函数的参数执行2次, 取dis

一个不靠谱的2D物理引擎(2) - 分离被碰撞物体与求碰撞冲量

如果已经知道了两个相互碰撞的物体进行碰撞前的 线速度, 角速度, 质心坐标, 被碰撞点的坐标, 碰撞方向, 质量, 转动惯量, 恢复系数, 那么可以用以下公式求得两个物体对对方造成的碰撞冲量大小: J = -vr (e + 1) / ( 1/m1 + 1/m2 + n * ((r1 × n) / I1) × r1 + n * ((r2 × n) / I2) × r2 ) 其中: m1与m2是两物体的质量 I1与I2是两物体的转动惯量 e是恢复系数 r1与r2是从物体质心指向被碰撞点的向量, 也就

一个不靠谱的2D物理引擎(5) - 约束(Constraints)

参考: http://blog.sina.com.cn/s/blog_61feffe10100msbz.html, http://allenchou.net/2013/12/game-physics-constraints-sequential-impulse/ 约束就是限制物体的运动方式, 可以用来处理碰撞, 模拟关节等的东西. 例如碰撞就是两个物体最小距离至少是0, 关节是两个物体被一颗钉子钉在一起只能绕这个钉子旋转, 弹簧是两个物体的距离要保持在某一范围内. 对于一个3D刚体有6个自由度,