# Rotation and direction problem

Hello, i’m actually working on a kind of “puzzle-adventure” game, in the second part of my game, the player can lunch a projectile. My problem is that the direction of the projectile doesn’t match the direction the player is facing when he’s rotation in radian is between pie/2 and pie.

here’s the code of my projectile:

``````function init(self)
self.t = 2 --temps de vie
self.explode = 0 --exploser ou pas
self.enter = 0 --contact
self.velocity = vmath.vector3(0, 0, 0)
end

function update(self, dt)
self.t = self.t - dt
self.rot = go.get_rotation() --enregistrer l'angle de rotation en quaternion
self.rad = 2 * math.acos(self.rot.z) -- convertir l'angle en radian afin de pouvoir appliquer la trigo pour mettre le mouvement en correspondance avec l'angle

if self.t < -(8/12) then --animation explosion finis, suppression
go.delete()
elseif self.t <= 0 and self.explode == 0 then --distance max atteinte ou contact, animation explosion
msg.post("#sprite", "play_animation", {id = hash("explosion4")})
self.explode = 1
elseif self.t < 2-(8/12) and self.explode == 0 then --animation de charge finis, boule de feu lancer
go.set_position(go.get_position() + self.velocity)
self.velocity.y = math.cos(self.rad) * 10 --calculer le module du vecteur y de l'angle
self.velocity.x = math.sin(self.rad) * 10 --calcule le module du vecteur x de l'angle
end
end

function on_message(self, message_id, message, sender)
if message_id == hash ("contact_point_response") then
if message.group == hash("wall") or message.group == hash("enemie") or message.group == hash("player2") then
if self.enter == 0 then
self.t = 0.1 --contact, declenche explosion prématuré
self.enter = 1
end
end
end
end
``````

and here’s the update function for the code of the player :

``````function update(self, dt)
self.wall_contact = false
self.correction = vmath.vector3()

--mouvement / rotation
if self.moving then
self.pos = go.get_position()
self.pos = self.pos + self.dir * self.speed * dt
go.set_position(self.pos)
else
msg.post("#sprite", "play_animation", {id = hash("player1_1")})
end
self.rot = math.atan2(self.dir.y, self.dir.x) + math.pi/2 --calculer l'angle en fonction de la direction du mouvement
go.set_rotation(vmath.quat_rotation_z(self.rot)) --affecter l'angle à la rotation du joueur

self.input.x = 0
self.input.y = 0
self.moving = false

--power
if self.shoot == 1 then
if self.shooted == 0 then
factory.create("#power", go.get_position(), go.get_rotation())
self.moving = false
self.t = 1
self.shooted = 1
elseif self.shooted == 1 then --une boule tirer donc attendre 1s
if self.t < 0 then
self.shooted = 0 --1s ecoule donc possibilité de retirer une boule
self.shoot = 0
else
self.t = self.t - dt
end
end
end
end
``````

Thanks !

I think you should be able to replace this code:

``````    elseif self.t < 2-(8/12) and self.explode == 0 then --animation de charge finis, boule de feu lancer
go.set_position(go.get_position() + self.velocity)
self.velocity.y = math.cos(self.rad) * 10 --calculer le module du vecteur y de l'angle
self.velocity.x = math.sin(self.rad) * 10 --calcule le module du vecteur x de l'angle
end
``````

with something like this:

``````    elseif self.t < 2-(8/12) and self.explode == 0 then --animation de charge finis, boule de feu lancer
self.velocity = vmath.rotate(go.get_rotation(), vmath.vector3(10,0,0))
go.set_position(go.get_position() + self.velocity)
end
``````

(I haven’t had time to test it myself, let me know how it goes!)

4 Likes

I think this line is the root of the confusion:

``````self.rad = 2 * math.acos(self.rot.z)
``````

A quaternion is represented by a vector part (x,y,z) and an angle part (w). The vector part may be zero (the unit quaternion is (0,0,0,1)). And the sum of all elements squared is 1.

Simply taking the vector part’s z component and using it as an angle doesn’t work. Using the “w” part should give better results, since in this example we’re rotating around Z, but I would go with @sven’s suggestion since it is easier to read and understand.

Here’s an excellent introductory presentation about quaternions.

8 Likes

Yeah but when i first tried i used math.acos(self.rot.w) but it didn’t worked at all (i had probably done other mistake) so i tried to change and with “z” instead of “w” it worked better (exept for the issue i had here). Thanks for the link it will help me a lot !

I’ve replaced my code with the one @sven send me and it work without any problem. I didn’t know there was a vmath.rotate function that do this that’s why i tried with some trigo, now that i know that, it will be a lot easier for me !

2 Likes