Movement through forces and impulses

I'm trying to get some decent-looking movement in my game using this tutorial. In the image below... something crazy is going on. What should happen is that the NPC should start on the left side of the screen (he does), face towards the end of the black line (he does not) and then walk towards it (definitely does not).

You can't see if in the GIF, but the original angle of his body is 0 (pointing upwards), so he should smoothly rotate to the right and walk towards his target.

Here's my messy code:

#define DEGTORAD 0.0174532925199432957f

void AiSystem::steerToNextNode(ComponentEntity *npc, QSharedPointer<Action> action) const
{
Path *path = action->path();
Q_ASSERT(!path->isEmpty());

QSharedPointer<PhysicsComponent> npcPhysics = npc->component<PhysicsComponent>();
Box2dBody *npcBody = npcPhysics->body();
QSharedPointer<PathNode> nextNode = path->front();

if (!isNextToTargetPos(npc, nextNode->pos())) {
float desiredAngle = Geometry::directionTo(npcBody->getWorldCenter(), nextNode->pos());
float nextAngle = npcBody->body()->GetAngle() + npcBody->body()->GetAngularVelocity() / 60.0;
float totalRotation = desiredAngle - nextAngle;
while ( totalRotation < -180 * DEGTORAD ) totalRotation += 360 * DEGTORAD;
while ( totalRotation >  180 * DEGTORAD ) totalRotation -= 360 * DEGTORAD;
float desiredAngularVelocity = totalRotation * 60;
float change = 10 * DEGTORAD; //allow 10 degree rotation per time step
desiredAngularVelocity = qMin( change, qMax(-change, desiredAngularVelocity));
float impulse = npcBody->body()->GetInertia() * desiredAngularVelocity;
npcBody->body()->ApplyAngularImpulse(impulse, true);

qDebug() << "angle =" << npcBody->body()->GetAngle() << "desiredAngle =" << desiredAngle << "impulse =" << impulse;

PhysicsSystem::moveForward(npcPhysics);

#ifdef VISUAL_AI_SYSTEM_DEBUG
mFacingIndicator->setLine(QLineF(npcBody->getWorldCenter(), nextNode->pos()));
#endif
} else {
qCDebug(AI_MOVEMENT_DEBUG) << "We're at the next node (" << npcBody->getWorldCenter() << "," << nextNode->pos() << ")";
// At the next node.
path->popFront();

if (path->isEmpty()) {
qCDebug(AI_MOVEMENT_DEBUG) << "I've finished moving... completed requisite.";
npc->component<AiComponent>()->primaryAction()->completeNextRequisite();
}
}
}


AiSystem::steerToNextNode() gets called every game step.

PhysicsSystem::moveForward() just applies a force in the direction the NPC should go:

void PhysicsSystem::moveForward(QSharedPointer<PhysicsComponent> physicsComponent)
{
float32 force = stupidForce(physicsComponent->body()->getMass());
float rotation = physicsComponent->body()->rotation();
QPointF directionVector = Geometry::directionVector(rotation);
physicsComponent->body()->applyForce(directionVector * force, physicsComponent->body()->position());
}


I've included some debug output as well (the first column is seconds:milliseconds):

38:905 angle = 0 desiredAngle = 1.5708 impulse = 0.320723
38:905 angle = 0.00268855 desiredAngle = 1.5708 impulse = 0.320723
38:905 angle = 0.00707863 desiredAngle = 1.57086 impulse = 0.320723
38:905 angle = 0.0121143 desiredAngle = 1.57108 impulse = 0.320723
38:905 angle = 0.0172392 desiredAngle = 1.57156 impulse = 0.320723
38:905 angle = 0.0225657 desiredAngle = 1.57236 impulse = 0.320723
38:905 angle = 0.0288589 desiredAngle = 1.57352 impulse = 0.320723
38:912 angle = 0.0377198 desiredAngle = 1.57504 impulse = 0.320723
38:926 angle = 0.0522711 desiredAngle = 1.57684 impulse = 0.320723
38:935 angle = 0.0778547 desiredAngle = 1.57861 impulse = 0.320723
38:945 angle = 0.115431 desiredAngle = 1.5799 impulse = 0.320723
38:956 angle = 0.150862 desiredAngle = 1.58127 impulse = 0.320723
39:029 angle = 0.191038 desiredAngle = 1.58286 impulse = 0.320723
39:029 angle = 0.240995 desiredAngle = 1.58396 impulse = 0.320723
39:029 angle = 0.287684 desiredAngle = 1.58541 impulse = 0.320723
39:029 angle = 0.34548 desiredAngle = 1.58649 impulse = 0.320723
39:030 angle = 0.398631 desiredAngle = 1.58787 impulse = 0.320723
39:030 angle = 0.462286 desiredAngle = 1.58886 impulse = 0.320723
39:030 angle = 0.521839 desiredAngle = 1.59022 impulse = 0.320723
39:043 angle = 0.588865 desiredAngle = 1.59109 impulse = 0.320723
39:050 angle = 0.657489 desiredAngle = 1.59223 impulse = 0.320723
39:055 angle = 0.722711 desiredAngle = 1.5933 impulse = 0.320723
39:069 angle = 0.797178 desiredAngle = 1.5941 impulse = 0.320723
39:079 angle = 0.868241 desiredAngle = 1.59527 impulse = 0.320723
39:090 angle = 0.938824 desiredAngle = 1.59618 impulse = 0.320723
39:099 angle = 1.01775 desiredAngle = 1.59689 impulse = 0.320723
39:109 angle = 1.09329 desiredAngle = 1.59797 impulse = 0.320723
39:124 angle = 1.16575 desiredAngle = 1.59893 impulse = 0.320723
39:134 angle = 1.24696 desiredAngle = 1.59953 impulse = 0.320723
39:145 angle = 1.32854 desiredAngle = 1.6004 impulse = 0.320723
39:154 angle = 1.40323 desiredAngle = 1.60151 impulse = 0.320723
39:170 angle = 1.4826 desiredAngle = 1.60217 impulse = -0.320723
39:180 angle = 1.55267 desiredAngle = 1.60274 impulse = -0.320723
39:189 angle = 1.60119 desiredAngle = 1.60363 impulse = -0.320723
39:199 angle = 1.64469 desiredAngle = 1.60423 impulse = -0.320723
39:209 angle = 1.67114 desiredAngle = 1.6048 impulse = -0.320723
39:226 angle = 1.68165 desiredAngle = 1.60577 impulse = -0.320723
39:231 angle = 1.68143 desiredAngle = 1.60704 impulse = -0.320723
39:244 angle = 1.67134 desiredAngle = 1.6086 impulse = -0.320723
39:254 angle = 1.6487 desiredAngle = 1.6105 impulse = -0.0510629
39:264 angle = 1.62061 desiredAngle = 1.61242 impulse = 0.320723
39:274 angle = 1.60724 desiredAngle = 1.61384 impulse = 0.320723
39:289 angle = 1.6103 desiredAngle = 1.61484 impulse = -0.0613149
39:299 angle = 1.61847 desiredAngle = 1.6154 impulse = -0.320723
39:309 angle = 1.62292 desiredAngle = 1.61552 impulse = -0.320723
39:319 angle = 1.62243 desiredAngle = 1.61524 impulse = -0.320723
39:329 angle = 1.61763 desiredAngle = 1.61458 impulse = 0.320723


If I change the rotation to 1 degree per time step, I get the following:

This I can understand, since he's probably not turning quickly enough to move in the correct direction. But what's going on in the first case? What am I doing wrong here?

Update: As per Hedede's advice, I've corrected the moveForward() function to pass radians instead of degrees:

void PhysicsSystem::moveForward(QSharedPointer<PhysicsComponent> physicsComponent)
{
float32 force = stupidForce(physicsComponent->body()->getMass());
float rotation = physicsComponent->body()->rotation();
physicsComponent->body()->applyForce(directionVector * force, physicsComponent->body()->position());
}


My directionVector() function looks like this:

QPointF Geometry::directionVector(qreal angle)
{
return QPointF(qCos(angle), qSin(angle));
}


Thanks for spotting that. Unfortunately, it still doesn't solve the problem:

I've included the output with the direction vector before applyForce() is called:

56:586 AiSystem::steerToNextNode: angle = 0 desiredAngle = 1.5708 impulse = 0.320723
56:586 PhysicsSystem::moveForward: QPointF(1,0)
56:587 AiSystem::steerToNextNode: angle = 0.00268855 desiredAngle = 1.5708 impulse = 0.320723
56:588 PhysicsSystem::moveForward: QPointF(0.999996,-0.00268855)
56:590 AiSystem::steerToNextNode: angle = 0.00780716 desiredAngle = 1.5708 impulse = 0.320723
56:591 PhysicsSystem::moveForward: QPointF(0.99997,-0.00780709)
56:593 AiSystem::steerToNextNode: angle = 0.0151082 desiredAngle = 1.5708 impulse = 0.320723
56:594 PhysicsSystem::moveForward: QPointF(0.999886,-0.0151076)
56:595 AiSystem::steerToNextNode: angle = 0.0243554 desiredAngle = 1.57081 impulse = 0.320723
56:597 PhysicsSystem::moveForward: QPointF(0.999703,-0.024353)
56:599 AiSystem::steerToNextNode: angle = 0.0353244 desiredAngle = 1.57083 impulse = 0.320723
56:599 PhysicsSystem::moveForward: QPointF(0.999376,-0.0353171)
56:602 AiSystem::steerToNextNode: angle = 0.0478028 desiredAngle = 1.57087 impulse = 0.320723
56:604 PhysicsSystem::moveForward: QPointF(0.998858,-0.0477846)
56:605 AiSystem::steerToNextNode: angle = 0.0615907 desiredAngle = 1.57092 impulse = 0.320723
56:608 PhysicsSystem::moveForward: QPointF(0.998104,-0.0615518)
56:611 AiSystem::steerToNextNode: angle = 0.0765009 desiredAngle = 1.57099 impulse = 0.320723
56:611 PhysicsSystem::moveForward: QPointF(0.997075,-0.0764263)
56:613 AiSystem::steerToNextNode: angle = 0.0923586 desiredAngle = 1.5711 impulse = 0.320723
56:613 PhysicsSystem::moveForward: QPointF(0.995738,-0.0922273)
56:615 AiSystem::steerToNextNode: angle = 0.109002 desiredAngle = 1.57124 impulse = 0.320723
56:617 PhysicsSystem::moveForward: QPointF(0.994065,-0.108786)
56:618 AiSystem::steerToNextNode: angle = 0.126281 desiredAngle = 1.57142 impulse = 0.320723
56:619 PhysicsSystem::moveForward: QPointF(0.992037,-0.125946)
56:621 AiSystem::steerToNextNode: angle = 0.14406 desiredAngle = 1.57164 impulse = 0.320723
56:622 PhysicsSystem::moveForward: QPointF(0.989641,-0.143562)
56:624 AiSystem::steerToNextNode: angle = 0.162212 desiredAngle = 1.57192 impulse = 0.320723
56:625 PhysicsSystem::moveForward: QPointF(0.986873,-0.161501)
56:626 AiSystem::steerToNextNode: angle = 0.180624 desiredAngle = 1.57225 impulse = 0.320723
56:628 PhysicsSystem::moveForward: QPointF(0.983732,-0.179643)
56:630 AiSystem::steerToNextNode: angle = 0.199194 desiredAngle = 1.57265 impulse = 0.320723
56:630 PhysicsSystem::moveForward: QPointF(0.980226,-0.197879)
56:632 AiSystem::steerToNextNode: angle = 0.21783 desiredAngle = 1.57312 impulse = 0.320723
56:634 PhysicsSystem::moveForward: QPointF(0.976369,-0.216112)
56:634 AiSystem::steerToNextNode: angle = 0.236451 desiredAngle = 1.57367 impulse = 0.320723
56:636 PhysicsSystem::moveForward: QPointF(0.972175,-0.234254)
56:638 AiSystem::steerToNextNode: angle = 0.254986 desiredAngle = 1.5743 impulse = 0.320723
56:638 PhysicsSystem::moveForward: QPointF(0.967667,-0.252231)
56:640 AiSystem::steerToNextNode: angle = 0.27337 desiredAngle = 1.57502 impulse = 0.320723
56:642 PhysicsSystem::moveForward: QPointF(0.962867,-0.269978)
56:642 AiSystem::steerToNextNode: angle = 0.291551 desiredAngle = 1.57583 impulse = 0.320723
56:644 PhysicsSystem::moveForward: QPointF(0.957799,-0.287438)
56:646 AiSystem::steerToNextNode: angle = 0.309481 desiredAngle = 1.57674 impulse = 0.320723
56:646 PhysicsSystem::moveForward: QPointF(0.952492,-0.304564)
56:648 AiSystem::steerToNextNode: angle = 0.327121 desiredAngle = 1.57775 impulse = 0.320723
56:650 PhysicsSystem::moveForward: QPointF(0.946971,-0.321318)
56:650 AiSystem::steerToNextNode: angle = 0.344439 desiredAngle = 1.57888 impulse = 0.320723
56:652 PhysicsSystem::moveForward: QPointF(0.941265,-0.337669)
56:654 AiSystem::steerToNextNode: angle = 0.361409 desiredAngle = 1.58012 impulse = 0.320723
56:654 PhysicsSystem::moveForward: QPointF(0.9354,-0.353592)
56:656 AiSystem::steerToNextNode: angle = 0.378008 desiredAngle = 1.58148 impulse = 0.320723
56:658 PhysicsSystem::moveForward: QPointF(0.929402,-0.36907)
56:677 AiSystem::steerToNextNode: angle = 0.394222 desiredAngle = 1.58296 impulse = 0.320723
56:677 PhysicsSystem::moveForward: QPointF(0.923296,-0.38409)
56:677 AiSystem::steerToNextNode: angle = 0.410038 desiredAngle = 1.58458 impulse = 0.320723
56:679 PhysicsSystem::moveForward: QPointF(0.917106,-0.398644)
56:681 AiSystem::steerToNextNode: angle = 0.425449 desiredAngle = 1.58633 impulse = 0.320723
56:683 PhysicsSystem::moveForward: QPointF(0.910853,-0.41273)
56:685 AiSystem::steerToNextNode: angle = 0.44045 desiredAngle = 1.58821 impulse = 0.320723
56:687 PhysicsSystem::moveForward: QPointF(0.90456,-0.426347)
56:689 AiSystem::steerToNextNode: angle = 0.455041 desiredAngle = 1.59024 impulse = 0.320723
56:690 PhysicsSystem::moveForward: QPointF(0.898243,-0.439499)
56:693 AiSystem::steerToNextNode: angle = 0.469222 desiredAngle = 1.59242 impulse = 0.320723
56:694 PhysicsSystem::moveForward: QPointF(0.89192,-0.452193)
56:696 AiSystem::steerToNextNode: angle = 0.482998 desiredAngle = 1.59475 impulse = 0.320723
56:698 PhysicsSystem::moveForward: QPointF(0.885606,-0.464436)
56:700 AiSystem::steerToNextNode: angle = 0.496374 desiredAngle = 1.59724 impulse = 0.320723
56:702 PhysicsSystem::moveForward: QPointF(0.879315,-0.476241)
56:704 AiSystem::steerToNextNode: angle = 0.509358 desiredAngle = 1.59988 impulse = 0.320723
56:706 PhysicsSystem::moveForward: QPointF(0.873058,-0.487617)
56:729 AiSystem::steerToNextNode: angle = 0.521959 desiredAngle = 1.60268 impulse = 0.320723
56:729 PhysicsSystem::moveForward: QPointF(0.866844,-0.498579)
56:730 AiSystem::steerToNextNode: angle = 0.534186 desiredAngle = 1.60566 impulse = 0.320723
56:732 PhysicsSystem::moveForward: QPointF(0.860684,-0.50914)
56:734 AiSystem::steerToNextNode: angle = 0.54605 desiredAngle = 1.6088 impulse = 0.320723
56:736 PhysicsSystem::moveForward: QPointF(0.854583,-0.519316)
56:738 AiSystem::steerToNextNode: angle = 0.557563 desiredAngle = 1.61211 impulse = 0.320723
56:739 PhysicsSystem::moveForward: QPointF(0.848547,-0.52912)
56:741 AiSystem::steerToNextNode: angle = 0.568738 desiredAngle = 1.61561 impulse = 0.320723
56:742 PhysicsSystem::moveForward: QPointF(0.842582,-0.538569)
56:755 AiSystem::steerToNextNode: angle = 0.579586 desiredAngle = 1.61928 impulse = 0.320723
56:755 PhysicsSystem::moveForward: QPointF(0.83669,-0.547677)
56:755 AiSystem::steerToNextNode: angle = 0.59012 desiredAngle = 1.62313 impulse = 0.320723
56:757 PhysicsSystem::moveForward: QPointF(0.830874,-0.556461)
56:759 AiSystem::steerToNextNode: angle = 0.600354 desiredAngle = 1.62717 impulse = 0.320723
56:761 PhysicsSystem::moveForward: QPointF(0.825136,-0.564935)
56:776 AiSystem::steerToNextNode: angle = 0.6103 desiredAngle = 1.6314 impulse = 0.320723
56:776 PhysicsSystem::moveForward: QPointF(0.819476,-0.573114)
56:777 AiSystem::steerToNextNode: angle = 0.619972 desiredAngle = 1.63582 impulse = 0.320723
56:778 PhysicsSystem::moveForward: QPointF(0.813895,-0.581012)
56:793 AiSystem::steerToNextNode: angle = 0.629382 desiredAngle = 1.64044 impulse = 0.320723
56:793 PhysicsSystem::moveForward: QPointF(0.808392,-0.588645)
56:794 AiSystem::steerToNextNode: angle = 0.638542 desiredAngle = 1.64526 impulse = 0.320723
56:796 PhysicsSystem::moveForward: QPointF(0.802966,-0.596025)
56:803 AiSystem::steerToNextNode: angle = 0.647466 desiredAngle = 1.65028 impulse = 0.320723
56:803 PhysicsSystem::moveForward: QPointF(0.797615,-0.603167)
56:813 AiSystem::steerToNextNode: angle = 0.656165 desiredAngle = 1.6555 impulse = 0.320723
56:813 PhysicsSystem::moveForward: QPointF(0.792338,-0.610082)
56:828 AiSystem::steerToNextNode: angle = 0.664651 desiredAngle = 1.66093 impulse = 0.320723
56:828 PhysicsSystem::moveForward: QPointF(0.787132,-0.616784)
56:841 AiSystem::steerToNextNode: angle = 0.672936 desiredAngle = 1.66656 impulse = 0.320723
56:841 PhysicsSystem::moveForward: QPointF(0.781995,-0.623284)
56:848 AiSystem::steerToNextNode: angle = 0.68103 desiredAngle = 1.67241 impulse = 0.320723
56:848 PhysicsSystem::moveForward: QPointF(0.776925,-0.629594)
56:858 AiSystem::steerToNextNode: angle = 0.688945 desiredAngle = 1.67848 impulse = 0.320723
56:858 PhysicsSystem::moveForward: QPointF(0.771917,-0.635723)
56:873 AiSystem::steerToNextNode: angle = 0.696691 desiredAngle = 1.68476 impulse = 0.320723
56:873 PhysicsSystem::moveForward: QPointF(0.766969,-0.641684)
56:883 AiSystem::steerToNextNode: angle = 0.704279 desiredAngle = 1.69127 impulse = 0.320723
56:883 PhysicsSystem::moveForward: QPointF(0.762079,-0.647484)
56:893 AiSystem::steerToNextNode: angle = 0.711716 desiredAngle = 1.69799 impulse = 0.320723
56:893 PhysicsSystem::moveForward: QPointF(0.757242,-0.653134)
56:908 AiSystem::steerToNextNode: angle = 0.719014 desiredAngle = 1.70494 impulse = 0.320723
56:909 PhysicsSystem::moveForward: QPointF(0.752455,-0.658643)
56:913 AiSystem::steerToNextNode: angle = 0.726181 desiredAngle = 1.71212 impulse = 0.320723
56:913 PhysicsSystem::moveForward: QPointF(0.747715,-0.664019)
56:925 AiSystem::steerToNextNode: angle = 0.733226 desiredAngle = 1.71953 impulse = 0.320723
56:925 PhysicsSystem::moveForward: QPointF(0.743019,-0.66927)
56:942 AiSystem::steerToNextNode: angle = 0.740156 desiredAngle = 1.72717 impulse = 0.320723
56:942 PhysicsSystem::moveForward: QPointF(0.738363,-0.674403)
56:959 AiSystem::steerToNextNode: angle = 0.74698 desiredAngle = 1.73504 impulse = 0.320723
56:959 PhysicsSystem::moveForward: QPointF(0.733744,-0.679426)
56:959 AiSystem::steerToNextNode: angle = 0.753706 desiredAngle = 1.74315 impulse = 0.320723
56:961 PhysicsSystem::moveForward: QPointF(0.729158,-0.684345)
56:975 AiSystem::steerToNextNode: angle = 0.760339 desiredAngle = 1.7515 impulse = 0.320723
56:975 PhysicsSystem::moveForward: QPointF(0.724602,-0.689167)
56:976 AiSystem::steerToNextNode: angle = 0.766888 desiredAngle = 1.76008 impulse = 0.320723
56:978 PhysicsSystem::moveForward: QPointF(0.720073,-0.693898)
56:992 AiSystem::steerToNextNode: angle = 0.773359 desiredAngle = 1.76891 impulse = 0.320723
56:992 PhysicsSystem::moveForward: QPointF(0.715568,-0.698543)
57:009 AiSystem::steerToNextNode: angle = 0.779759 desiredAngle = 1.77797 impulse = 0.320723
57:009 PhysicsSystem::moveForward: QPointF(0.711083,-0.703108)
57:009 AiSystem::steerToNextNode: angle = 0.786093 desiredAngle = 1.78728 impulse = 0.320723
57:011 PhysicsSystem::moveForward: QPointF(0.706616,-0.707598)
57:025 AiSystem::steerToNextNode: angle = 0.792367 desiredAngle = 1.79684 impulse = 0.320723
57:025 PhysicsSystem::moveForward: QPointF(0.702162,-0.712017)
57:028 AiSystem::steerToNextNode: angle = 0.798587 desiredAngle = 1.80664 impulse = 0.320723
57:028 PhysicsSystem::moveForward: QPointF(0.69772,-0.716371)
57:042 AiSystem::steerToNextNode: angle = 0.804758 desiredAngle = 1.81668 impulse = 0.320723
57:042 PhysicsSystem::moveForward: QPointF(0.693286,-0.720663)
57:059 AiSystem::steerToNextNode: angle = 0.810886 desiredAngle = 1.82697 impulse = 0.320723
57:059 PhysicsSystem::moveForward: QPointF(0.688857,-0.724898)
57:075 AiSystem::steerToNextNode: angle = 0.816975 desiredAngle = 1.8375 impulse = 0.320723
57:075 PhysicsSystem::moveForward: QPointF(0.68443,-0.729079)
57:076 AiSystem::steerToNextNode: angle = 0.82303 desiredAngle = 1.84828 impulse = 0.320723
57:078 PhysicsSystem::moveForward: QPointF(0.680002,-0.73321)
57:092 AiSystem::steerToNextNode: angle = 0.829057 desiredAngle = 1.8593 impulse = 0.320723
57:092 PhysicsSystem::moveForward: QPointF(0.675572,-0.737294)
57:093 AiSystem::steerToNextNode: angle = 0.835058 desiredAngle = 1.87056 impulse = 0.320723
57:095 PhysicsSystem::moveForward: QPointF(0.671134,-0.741336)
57:108 AiSystem::steerToNextNode: angle = 0.84104 desiredAngle = 1.88207 impulse = 0.320723
57:109 PhysicsSystem::moveForward: QPointF(0.666688,-0.745337)
57:113 AiSystem::steerToNextNode: angle = 0.847005 desiredAngle = 1.89381 impulse = 0.320723
57:113 PhysicsSystem::moveForward: QPointF(0.66223,-0.7493)
57:125 AiSystem::steerToNextNode: angle = 0.852958 desiredAngle = 1.90579 impulse = 0.320723
57:125 PhysicsSystem::moveForward: QPointF(0.657758,-0.753229)
57:142 AiSystem::steerToNextNode: angle = 0.858903 desiredAngle = 1.918 impulse = 0.320723
57:142 PhysicsSystem::moveForward: QPointF(0.653269,-0.757126)
57:158 AiSystem::steerToNextNode: angle = 0.864843 desiredAngle = 1.93044 impulse = 0.320723
57:159 PhysicsSystem::moveForward: QPointF(0.648759,-0.760994)
57:159 AiSystem::steerToNextNode: angle = 0.870783 desiredAngle = 1.94311 impulse = 0.320723

• You any good with trigonometry? – user59493 Aug 31 '15 at 11:21
• No, I'm terrible, unfortunately. – Mitch Aug 31 '15 at 11:26
• I'm horrible at explaining. For the angles, make the player face the Inverse Tangent of the difference in the Y over the difference in the X. This should be similar to something like angle = Math.atan(yDifference / xDifference); This hasn't been tested yet. Get back to me if you understand or not. :) – user59493 Aug 31 '15 at 11:59
• What are xDifference and yDifference in my code? – Mitch Aug 31 '15 at 17:07
• Alright, you need to create xDifference and yDifference. Difference is the points X and Y, minus the players X and Y. xDif = point.x - player.x; yDif = point.y - player.y; – user59493 Aug 31 '15 at 23:05

It looks to me like the original rotation towards the end of the black line was working. It's just a bit slow.

What's weird is the movement. It looks like the force in the first one is in the wrong direction (accelerating backwards), and there's a weird wobble, too, like the force may be alternating forward and back between frames. I would start by trying reversing DirectionVector. It might (also?) be a rads to degrees problem, as Hedede suggested - that could cause random-looking wobble like that (i.e. if you are passing in degrees when it thinks you mean rads, that will mean instead of a few degrees you get a nearly random direction applied to the momentum).

The second one may be turning a really slow 1 degree per frame, which doesn't do much, and of course for some reason he has momentum down and to the right.

Even if you get forward force going the right direction in the original case, though, I think it's going to be quite weird because you have him turning and accelerating at the same time, even when he's facing mostly away from his target, and he doesn't turn very fast, and with the inertia he has, he's going to look like a newbie Asteroids player spiraling around out of control. People tend not to go sideways a lot, and they tend to stop and turn to face roughly where they're going before going forward. So if you want it to look good, you probably want at least two or three states with different behavior, such as:

(Don't run sideways or backwards): If your sideways component of velocity relative to your facing is greater than your forward velocity, slow down quickly. If your backwards velocity is higher than about 1/2 maximum running speed, slow down. (To slow down, you can just multiply momentum by a fraction less than 1 - start with .5 and adjust to taste.)

(If you're not facing the target, turn and slow down): If abs(angle to target off forward) is greater than about 30 degrees, turn towards target and slow down.

(If you are facing the target, speed up): If the above cases are not true, accelerate towards the target, not to exceed the desired max speed.

Edit: In comments and chat, we found that there were several issues to sort out:

1) As Hedede thought, the direction to target was passing degrees where rads were expected, resulting in unpredictable jerky motion.

2) The sprite image was 90 degrees off from intended.

3) The calculation of the direction to target was wrong - it needed -1 * on the Y component before passing into arctan2().

4) It looks like we finally got it working for the AI, but now the resulting turn is slow in effect sometimes (right after reaching the first waypoint), even though the "impulse" from the AI is a constant full left turn.

That is, we got it to do this: animated GIF showing final motion

• Reversing the direction vector (I'm assuming that you meant directionVector = QPointF(directionVector.y(), directionVector.x());) almost works, but he's going the wrong way: i.imgur.com/w4JzGOY.gif. I understand what you mean about the movement not being realistic, however, I do think that 10 degrees per time step results in a pretty fast turn. I think that at the speed he's turning, he should be able to reach the target without doing the "newbie Asteroids player spiraling around out of control" thing, haha! :p – Mitch Aug 31 '15 at 18:39
• @Mitch Do you mean you swapped x and y? No, I meant reverse the direction of the vector, (e.g. add 180 degrees to the direction) right before applying the force. The current GIF looks like you either have x and y switched (which you shouldn't), or maybe it's just needs -90 degrees. So if you switched x and y, switch them back. Then try +180 degrees to the force you apply. (If that's not what you meant, then try -90 degrees to the force you apply.) – Dronz Aug 31 '15 at 18:45
• Hmm, I switched it back and then added 180 degrees to the rotation before converting it to radians, but he goes off in another direction: i.imgur.com/2PELL6N.gif. Subtracting 90 degrees results in the same GIF that that I posted in my last comment. – Mitch Aug 31 '15 at 18:51
• @Mitch Getting closer. Now he's turning to one direction and moving sideways. Try disabling the part that has him move at all, so you can just confirm that he rotates towards the target and then stops turning and faces it. Possibly the math is right but your image shows 90 degrees off the way you expect? Once that seems right, try adding a very slow constant movement (x + 0.1 per frame or something), and see if he drifts but keeps facing towards the target, or not. That is, it's odd in the last two GIFs that he moves away but facing stays. Maybe the target direction isn't updated each frame? – Dronz Aug 31 '15 at 19:05
• I just realised that the desiredAngle is 1.5708... should that be -1.5708? directionTo() looks like this: paste.kde.org/p3fviwuzv. I've been staring at this for too long. Also, if I disable the movement, he just stares to the west and vibrates a lot. :) – Mitch Aug 31 '15 at 19:23

Your NPC seems to be turning towards the desired angle as it supposed to do, but slowly. Try increasing rotation speed.

Judging by the movement pattern, I think that you are passing degrees to a function which takes radians, or vice versa.

I think the problem is here:

    float rotation = physicsComponent->body()->rotation();
QPointF directionVector = Geometry::directionVector(rotation);


I might be wrong about the cause, but I think the problem is with incorrectly applied force.

• Thanks, I've updated my question. Unfortunately the problem still persists. I've included the direction the force is applied in in my question. – Mitch Aug 31 '15 at 18:27
• I can't comment in the other thread, so I'll comment here. Your clampAngle function clamps the angle between (0; 360), but in steerToNextNode you clamp it to (-180; 180). You should correct either one of those. – Hedede Aug 31 '15 at 20:26
• @Hedede I moved the comments to chat ( chat.stackexchange.com/rooms/27616/… ), so we can all work this out. The clamp in SteerToNextNode is about getting which relative direction to turn, not the bearing, so I don't think they're incompatible. However it might help to simplify that part so that we can eliminate it as a possible problem. If the direction is dubious, then it doesn't help to wonder if the angular momentum part is off too. – Dronz Aug 31 '15 at 20:37