Box2D-Lite源码阅读笔记(3)

0.简介

这次来看step函数。

1.step开始

step函数里看起来如下的样子,当然我们只关注一块。

void World::Step(float dt)
{
	float inv_dt = dt > 0.0f ? 1.0f / dt : 0.0f;

	// 碰撞检测
	BroadPhase();
    ...

}

BroadPhase函数是碰撞碰撞检测函数。具体讲解在代码注释

void World::BroadPhase()
{
	//这是一个O(n^2)的循环
	for (int i = 0; i < (int)bodies.size(); ++i)
	{
		//获取一个物体
		Body* bi = bodies[i];
		for (int j = i + 1; j < (int)bodies.size(); ++j)
		{
			//获取第二个物体
			Body* bj = bodies[j];
			//如果两个物体的质量倒数的0,就是两个质量无穷大的物体,不进行碰撞检测了
			if (bi->invMass == 0.0f && bj->invMass == 0.0f)
				continue;
			//这里是创建一个值(val)和一个键(key)
			//值中主要存储两个物体的指针和两个物体的碰撞信息
			Arbiter newArb(bi, bj);
			//键中存放的是两个物体的指针,以便用于哈希表查找的键
			//而且为了避免(bi,bj),(bj,bi)不同,构造key的时候将指针值较小的放在前面
			ArbiterKey key(bi, bj);
			//arbiters里面主要存放两个物体的碰撞信息(存入哈希表中),
			//arbiters是一个map,键是ArbiterKey,值是Arbiter
			if (newArb.numContacts > 0)//当两个物体bi,bj有碰撞产生时
			{
				//这里先获取哈希表查找(bi,bj)键后的结果
				ArbIter iter = arbiters.find(key);
				if (iter == arbiters.end())//如果没找到对应的两个物体已有的碰撞
				{
					arbiters.insert(ArbPair(key, newArb));//将两个物体新的碰撞信息加入
				}
				else//如果找到对应的键
				{
					//更新键中的碰撞结果
					iter->second.Update(newArb.contacts, newArb.numContacts);
				}
			}
			else//如果两个物体没有碰撞,则删除哈希表中已有的记录
			{
				arbiters.erase(key);
			}
		}
	}
}

ArbiterKey就是如下的一个小结构体。

struct ArbiterKey
{
	ArbiterKey(Body* b1, Body* b2)
	{
		//永远让指针值小的在前
		if (b1 < b2)
		{
			body1 = b1; body2 = b2;
		}
		else
		{
			body1 = b2; body2 = b1;
		}
	}

	Body* body1;//物体1指针
	Body* body2;//物体2指针
};

Arbiter中我有重大发现。其构造函数里有碰撞检测调用过程。

struct Arbiter
{
	enum {MAX_POINTS = 2};

	Arbiter(Body* b1, Body* b2);//构造函数里有碰撞检测过程

	...

	Body* body1;//物体1指针
	Body* body2;//物体2指针
    ...
};

走进Arbiter的构造函数。

Arbiter::Arbiter(Body* b1, Body* b2)
{
	//指针值较小的存储在body1中,和键中的对应上
	//个人觉得这个类完全可以继承ArbiterKey,然后生成键和值的时候就不用
	//分别构造两次了,只构造一次就能同时生成基类的键和子类值,body1和body2还可以复用
	if (b1 < b2)
	{
		body1 = b1;
		body2 = b2;
	}
	else
	{
		body1 = b2;
		body2 = b1;
	}
	//碰撞检测函数,会返回碰撞点个数,contacts进去的指针,最后会获取具体碰撞点的信息
	numContacts = Collide(contacts, body1, body2);
	//两个物体之前的摩擦系数计算
	friction = sqrtf(body1->friction * body2->friction);
}

下一篇

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Box2D-js是Box2D物理引擎的JavaScript端口,可以在Vue中使用。你需要先安装Box2D-js库。你可以通过npm安装,使用以下命令: ``` npm install box2d-js ``` 然后在Vue组件中使用Box2D-js,你需要引入Box2D-js库并创建Box2D世界。以下是一个简单的示例: ```html <template> <div> <canvas ref="canvas" width="800" height="600"></canvas> </div> </template> <script> import { b2Vec2, b2World, b2BodyDef, b2BodyType, b2PolygonShape, b2FixtureDef } from 'box2d-js' export default { mounted() { const canvas = this.$refs.canvas const ctx = canvas.getContext('2d') // 创建Box2D世界 const gravity = new b2Vec2(0, 10) const world = new b2World(gravity) // 创建地面刚体 const groundBodyDef = new b2BodyDef() groundBodyDef.position.Set(400 / 30, 550 / 30) const groundBody = world.CreateBody(groundBodyDef) const groundShape = new b2PolygonShape() groundShape.SetAsBox(400 / 30, 10 / 30) const groundFixtureDef = new b2FixtureDef() groundFixtureDef.shape = groundShape groundFixtureDef.density = 0 groundFixtureDef.friction = 0.5 groundFixtureDef.restitution = 0.2 groundBody.CreateFixture(groundFixtureDef) // 创建方块刚体 const boxBodyDef = new b2BodyDef() boxBodyDef.type = b2BodyType.b2_dynamicBody boxBodyDef.position.Set(200 / 30, 50 / 30) const boxBody = world.CreateBody(boxBodyDef) const boxShape = new b2PolygonShape() boxShape.SetAsBox(50 / 30, 50 / 30) const boxFixtureDef = new b2FixtureDef() boxFixtureDef.shape = boxShape boxFixtureDef.density = 1 boxFixtureDef.friction = 0.5 boxFixtureDef.restitution = 0.2 boxBody.CreateFixture(boxFixtureDef) // 模拟世界 setInterval(() => { world.Step(1 / 60, 10, 10) ctx.clearRect(0, 0, canvas.width, canvas.height) // 绘制地面 ctx.beginPath() ctx.moveTo(0, 550) ctx.lineTo(800, 550) ctx.stroke() // 绘制方块 ctx.save() ctx.translate(boxBody.GetPosition().x * 30, boxBody.GetPosition().y * 30) ctx.rotate(boxBody.GetAngle()) ctx.fillRect(-50, -50, 100, 100) ctx.restore() }, 1000 / 60) } } </script> ``` 这个示例创建了一个Box2D世界并在Canvas上绘制了一个方块和地面。你可以根据自己的需求修改这个示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值