# Using versors for movement

The context

I was thinking of using a versor + velocity field to implement the "moving" part of a 2D game object. For example, if the player should move right I just set the versor to be: [1, 0] and the velocity to be some variable. Then when the player movement needs to be updated we just multiply the versor to the variable and we get the vector to be summed to the current vector position.

For example if the position p is [12, 45] in the 2D space, the versor vs is [1, 0] and the velocity v is 4 we can easily apply the algorithm above:

new position = p + (vs * v)


new position = [12, 45] + ([1, 0] * 4)
new position = [12, 45] + [4, 0]
new position = [16, 45]


The velocity/speed is a separate field because a versor (of length always = 1) better explain diagonal cases, like we see below.

When the player position is handled by the pressing of WASD keys I'd like to be able to code something like this:

on press W -> add versor [0, +1] to current versor and normalize
on press S -> add versor [0, -1] to current versor and normalize
on press A -> add versor [-1, 0] to current versor and normalize
on press D -> add versor [+1, 0] to current versor and normalize

on release W -> remove versor [0, +1]
on release S -> remove versor [0, -1]
on release A -> remove versor [-1, 0]
on release D -> remove versor [+1, 0]


The cool thing about this is that when both W and D are pressed the player moves diagonally to the top right because we first add the W versor and normalize:

vs = [0, 0]
vs += [0, +1] // W versor
// vs is now [0, +1] which is already normalized


and then we add the D versor:

// vs is now [0, +1]
vs += [+1, 0] // D versor
// vs is now [1, 1] which is not normalized
vs /= magnitude(vs)
// vs is now [0.71, 0.71]


Substracting versors (the problem)

Now the problem is when the user later release the W key for example. We currently have the W and D key pressed (which means the player is moving of [0.71, 0.71] (towards the top right corner) at every update. But if we remove the W versor, the calculus goes as:

// vs is now [0.71, 0.71]
vs -= [0, +1]
// vs is now [0.71, -0.29]
vs /= magnitude(vs)
// vs is now [0.9258, -0.3781]


The versor should be the remaining D versor, instead, ([1, 0]). I understand that this problem is related to the fact that we are normalizing at every operation, otherwise we would have:

vs = [0, 0]
vs += [0, +1] // W versor
vs += [+1, 0] // D versor
// vs is now [+1, +1]
vs -= [+1, 0] // D versor
// vs is now [0, +1]


but if we don't normalize and for some reason two D events are sent, we end up with:

vs = [0, 0]
vs += [0, +1] // W versor
vs += [+1, 0] // D versor
vs += [+1, 0] // D versor
// vs is now [+1, +2]
vs -= [+1, 0] // D versor
// vs is now [+1, +1]


which is not what we want. How can I correctly calculate the player position with versors then?

• What do versors plus speed (you've mislabeled it velocity in your example; velocity includes direction, speed does not) actually offer you? Looks like extra math (less efficiency) and complication over just using a velocity vector for no gain. – Sean Middleditch Oct 12 '13 at 17:25
• @SeanMiddleditch, You are right, I meant speed. I need to be able to modify the speed at every update if I need to (and I need it to simulate friction). With vectors I would always have to calculate the length/magnitude of the vector and adjust it to be of the length of the speed I want (which seems less efficient if you ask me). Either way if you have a cleaner solution with a single vector (without an external component) I'm fine with it. – Shoe Oct 12 '13 at 17:30
• In the end it doesn't change a thing. Normalizing to 1 or normalizing to the length/speed you want doesn't change anything of the problem above. – Shoe Oct 12 '13 at 17:31
• So... your underlying question has nothing to do with versors at all but with the application of movement controls? – Sean Middleditch Oct 12 '13 at 17:34
• @SeanMiddleditch, the problem I'm facing is with versors. The problem lies on the fact that the versor is normalized by definition and I can't apply and unapply "forces" to it like shown above (at least I don't know why), which is what I need for controls. – Shoe Oct 12 '13 at 17:40