IOS Box2D – 主体遵循一个特定的path,基于一个波动的速度点arrays

我有一个关于身体的问题,它遵循一个特定的path。 首先在这里将身体移动到目标点的方法:

const float destinationControl = 0.3f; b2Vec2 targetPosition = path[counter]; b2Vec2 missilePosition = _physicalBody->GetPosition(); b2Vec2 diff = targetPosition - missilePosition; float dist = diff.Length(); if (dist > 0) { if(dist < destinationControl){ ++counter; return; } // compute the aiming direction b2Vec2 direction = b2Vec2(diff.x / dist, diff.y / dist); // get the current missile velocity because we will apply a force to compensate this. b2Vec2 currentVelocity = _physicalBody->GetLinearVelocity(); // the missile ideal velocity is the direction to the target multiplied by the max speed b2Vec2 desireVelocity = b2Vec2(direction.x * maxSpeed, direction.y * maxSpeed); // compensate the current missile velocity by the desired velocity, based on the control factor b2Vec2 finalVelocity = control * (desireVelocity - currentVelocity); // transform our velocity into an impulse (get rid of the time and mass factor) float temp = (_physicalBody->GetMass() / normalDelta); b2Vec2 finalForce = b2Vec2(finalVelocity.x * temp, finalVelocity.y * temp); _physicalBody->ApplyForce(finalForce, _physicalBody->GetWorldCenter()); } 

数组path代表顾名思义当用户触发触摸事件时身体遵循的特定path。

我的问题是variablesmaxSpeed不是恒定的。 所以当path非常短并且maxSpeed非常高时,物体移动到当前目标点上。 用我身体上方的方法返回到当前的目标点,并不关注下一个点。

目前,我有一个常数destinationControl控制,它控制身体和当前目标点之间的距离足够短,以聚焦下一个目标点。

重点是增加一个代表目标点指标的计数器。

所以我最后的问题是:你能想象另一个可能的解决scheme,因为我的安全性不是很高。 有没有办法找出身体是否移动到目前的目标点?

提前感谢您,并为我的英语不好而感到遗憾。

在我放在一起的演示之后,我遇到了类似的问题( 这里是项目 ,这里是video )。

我发现最可行的解决scheme是使用2个function的组合。 第一个检测实体是否“接近”他们想要到达的下一个点。

 bool MovingEntity::IsNearTarget() { Vec2 toTarget = GetTargetPos() - GetBody()->GetPosition(); if(toTarget.LengthSquared() < GetMinSeekDistanceSquared()) { return true; } return false; } 

这个实体正在使用“seek”操作来移动点。 如果接近该点,则该函数返回true。 它使用距离的平方来避免长度的平方根。

第二个函数是每次更新后执行的path跟随函数:

 void MovingEntity::ExecuteNavigateToPoint() { vector<Vec2>& path = GetPath(); bool isNearTarget = IsNearTarget(); bool isNearNavTarget = IsNearTarget(_navigatePos,5.0); /* If the state tick timer expires, it means we * have spent too long trying to reach the next waypoint * and we need to replan on how to get to it. */ if(IsStateTickTimerExpired()) { CCLOG("Tick Timer Expired!!!"); ChangeState(ST_NAVIGATE_TO_POINT); } /* If we are close to the navigation target point, * just seek to it. */ if(isNearNavTarget || path.size() == 0) { // Must be really close...just seek to it. CommandSeek(_navigatePos); } else if(!IsNodePassable(GetTargetPos(),false)) { ChangeState(ST_NAVIGATE_TO_POINT); } else { // If we are near the target and there are more points // on the list, pop the next point and navigate to it. if(isNearTarget && path.size() > 0) { // Still more points on the list. GetTargetPos() = path.back(); path.pop_back(); ResetStateTickTimer(2*TICKS_PER_SECOND); /* If we can't get past the current nodes, replan. */ if(path.size() > 0 && !IsNodePassable(path.back(),false)) { ChangeState(ST_NAVIGATE_TO_POINT); } } ApplyThrust(); ApplyTurnTorque(); } } 

这是一个有点har but,但是它究竟是检查实体是否已经达到最终目标(_navigatePos),到达下一个path点,或由于某种原因无法接近目标点,所以它超时重新规划它的path。

这是仿真一艘飞船通过一个移动的小行星场飞行的一部分,所以风景正在改变,船在某些情况下可能会“卡住”,所以它不得不重新调整。

这个代码库位于github上。

这个有帮助吗?

我想你可能想要做的就是比较你的maxSpeed和可能移动的距离。 当移动的距离超过可用距离时,将misslePosition设置为targetPosition并检索path中的下一个目标位置,然后减去已经从maxSpeed移动的距离。

 if (maxSpeed > dist) { maxSpeed -= dist; misslePosition = targetPosition; targetPosition = path[counter + 1]; } 

另一个可能的解决scheme是在totalDistanceCovered <maxSpeed的时候做更小的步骤和执行一个循环,虽然使用更多的CPU时间,但是捕获更多的边缘情况可能会稍微容易一些。

 const float stepDistance(0.1f); //Some relatively small value depending on your units. float totalDistance(0.0f); while (totalDistance < maxSpeed) { totalDistance += stepDistance; //Perform the same movement logic you already have. } 

—我下面的原始答案—

如果您试图与dynamic目标相冲突,您可能需要将_physicalBody的定义设置为项目符号。

默认情况下,Box2D使用连续碰撞检测(CCD)来防止dynamic物体穿过静态物体。 这是通过从旧位置到新位置的形状完成的。 扫描期间引擎会查找新的碰撞,并计算这些碰撞的冲击时间(TOI)。 机构被移动到他们的第一个TOI,然后在剩下的时间内停下来。

通常情况下CCD不能在dynamic物体之间使用。 这样做是为了保持性能合理。 在某些游戏场景中,您需要使用CCD的dynamic物体。 例如,您可能想要在一堆dynamic砖头上拍摄高速子弹。 没有CCD,子弹就可能穿过砖头。

来自box2d.org/manual