Это полностью возможно в Box2d, но требует некоторой работы, чтобы все заработало.
Игра, над которой я работаю, под названием «Космические пауки должны умереть!», Требовала, чтобы «космические пауки» могли ходить по астроидам, прыгая между ними.
Первое, что вам нужно, это путевые точки.Это точки на теле, которые вы хотите передвигать, или в вашем случае, прямо возле ваших стен, по которым вы хотите, чтобы ваш персонаж двигался по ним.Наличие «статичности» точек (не на движущемся теле) значительно сокращает объем работы.
Предположим, вы хотите перемещаться между двумя точками p0 и p1 с течением времени T. Ваш временной шаг dT (фиксированный)).Соблазнительно использовать SetTransform (...) на теле, делая что-то вроде:
// Initialize for new points
int steps = T/dT;
Vec2 toTarget = p1-p0;
toTarget.Normalize();
int stepsTaken = 0;
float32 bodyAngle = atan2f(toTarget.y,toTarget.x)
// Each time step
stepsTaken++;
Vec2 pos = p0 + stepsTaken*dT*toTarget;
body.SetTransform(pos,bodyAngle);
if(stepsTaken >= steps)
{
// Set up next set of points.
}
ОДНАКО, если вы сделаете это, я думаю, вы обнаружите, что физический движок больше не взаимодействует с вашим теломдля столкновений.Я полагаю, что это потому, что SetTransform (...) заставляет двигатель «пропустить удар» в отношении обнаружения столкновений.
Итак, решение, которое я нашел, было создать b2PrismaticJoint в p0, прикрепленный ктело, и указывая в направлении р1.Максимальная длина соединения была установлена на расстояние между точками.
Это код из проекта, в котором я делал это:
void CreateNextMovingJoint(float32 motorStrength = 1.0f)
{
b2PrismaticJointDef jointDef;
// We need to figure out some geometry here.
_pathIter = _pathDataList.begin();
PATH_DATA_T& pd = *_pathIter;
_pathIter++;
// Anchor
Vec2 pAnchor = pd.point;
// End point of the anchor, used for the axis.
Vec2 pEnd = pd.point + pd.distToNext[_direction]*pd.normalAlongPath[_direction];
jointDef.bodyA = _bodyMovingOn;
jointDef.bodyB = _bodyMoving;
jointDef.localAnchorA = pAnchor;
jointDef.localAnchorB = Vec2(0.0,0.0);
jointDef.localAxisA = pEnd-pAnchor;
jointDef.referenceAngle = 0;
jointDef.enableMotor = true;
jointDef.enableLimit = true;
jointDef.motorSpeed = _maxSpeed;
jointDef.maxMotorForce = motorStrength*(_maxSpeed/4)*_bodyMoving->GetMass();
jointDef.lowerTranslation = -0.1*pd.distToNext[_direction];
jointDef.upperTranslation = 1.1*pd.distToNext[_direction];
jointDef.collideConnected = true;
_bodyMoving->GetWorld()->CreateJoint(&jointDef);
}
После каждого обновления физического движка,вам нужно проверить, насколько близко движущееся тело находится к следующей точке.Когда он подойдет достаточно близко, уничтожьте существующее призматическое соединение и создайте новое до следующей точки.
Это часть большой базы кода, но идея должна быть хорошо представлена здесь.В моем случае я сохранил все данные для каждого сегмента точка-точка в структуре под названием PATH_DATA_T.Был список из них, который я повторил.Когда паук приближается к следующей точке, итератор переходит к следующему элементу и обрабатывает его.Это работало ОЧЕНЬ хорошо ( см. Видео здесь ).
Было ли это полезно?