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

  • 简介
    上一篇完成了碰撞点的初步获取,这回阅读的是碰撞点的第二步获取。
  • 碰撞点截取
    因为有一定可能使得取得的B上的碰撞点在A的宽度范围之外,这样一来,范围之外的点属于没有意义的点,所以需要根据A的宽度将点截断在A的宽度范围内。
  • 代码
/*参数列表:vOut[2]输出结果,vIn[2]输入的碰撞点候选点,normal侧方向上的向量(假设以矩形A坐标系为主)
offset侧方向上的坐标值。
这假设前面是以A坐标系为主,vIn[2]是获取自矩形B上的顶点且已经转换到世界坐标
*/
int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
	const Vec2& normal, float offset, char clipEdge)
{
	int numOut = 0;
	// Calculate the distance of end points to the line
	//将B的世界坐标vIn转换到A的局部坐标,仅限于sideNormal方向上的坐标值
	//这里normal在外面取的是矩阵的列向量,所以下面的计算实际上是原本矩阵中
	//某个轴方向上的逆运算,Dot(normal, vIn[0].v)就是算坐标(x,y)中的x或者y
	//从世界坐标变换到A坐标系的x或者y,offset实际存放的是A矩形在normal方向
	//上的矩形某个端点的x或者y坐标值(投影)。最终distance(0/1)得到的如果是小0的数字
	//说明两个点在矩形AsideNormal方向长度的范围内。
	float distance0 = Dot(normal, vIn[0].v) - offset;
	float distance1 = Dot(normal, vIn[1].v) - offset;

	//这里就是直接记录结果
	if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
	if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];

	//如果有一个点在范围之外
	if (distance0 * distance1 < 0.0f)
	{
		//这里算出矩形A的端点在两个碰撞点之间的位置
		float interp = distance0 / (distance0 - distance1);
		//然后求出那个A端点的位置,作为截断
		vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
		//存储一些相关信息
		if (distance0 > 0.0f)
		{
			vOut[numOut].fp = vIn[0].fp;
			vOut[numOut].fp.e.inEdge1 = clipEdge;
			vOut[numOut].fp.e.inEdge2 = NO_EDGE;
		}
		else
		{
			vOut[numOut].fp = vIn[1].fp;
			vOut[numOut].fp.e.outEdge1 = clipEdge;
			vOut[numOut].fp.e.outEdge2 = NO_EDGE;
		}
		++numOut;
	}
	return numOut;
}

对A的两边的边界分别计算,这样一来,点都会被调整到A的宽度范围内。下面连读两次调用了截断函数。分别是不同的sideNormal方向。

//4.筛选碰撞顶点,计算出合适的碰撞点
	//前面已经得到了两个矩形上的顶点,这两个顶点需要再加工一下
	//实际上就是将顶点限制在sideNormal方向上的negSide和posSide范围之间
	ClipVertex clipPoints1[2];
	ClipVertex clipPoints2[2];
	int np;//取得的点个数

	//clipPoints1此时是结果接收,incidentEdge是前面获得的与碰撞相关的
	//矩形顶点,输入sideNormal,这个类似剪裁,当在矩形A坐标系下,incidentEdge中B的
	//顶点如果超出了negSide和posSide的范围,就剪裁到范围内,剪裁方向是-sideNormal。
	np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, negSide, negEdge);
	if (np < 2)
		return 0;

	//经过上面的剪裁后,现在其基础上剪裁sideNormal方向
	np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, posSide, posEdge);
	if (np < 2)
		return 0;
  • 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、付费专栏及课程。

余额充值