Rotating bullet objects


#1

So currently, I’m trying to create arrows that fire off of the character and have a curved/falling trajectory. The issue that I’m running across is that the arrow does not rotate along with the trajectory, making it stay flat until it bounces off something.

Any way to rotate it so that it rotates at the angle that it falls?


#2

All you need to do is keep track of the previous position the arrow was on the previous frame. Then you can do an angle between two points between the previous position and current position to get a rotation to apply to the arrow.


#3

Owo what a magnificent solution :smiley:


#4

My newest issue is that though calculating angle and applying rotation works, however, it appears that I can’t apply that rotation to the object itself, since it is a dynamic object. Is there a workaround to this?

My current code:

self.arrowpos1=go.get_position()
self.direction=self.arrowpos0-self.arrowpos1
self.angle=math.atan2(self.direction.y,self.direction.x)
self.rotation=vmath.quat(vmath.quat_rotation_z(self.angle))
self.arrowpos0=go.get_position()

This is in the update script of the arrows


#5

First disable rotation on the main GO.
Add a sub-GO to your arrow GO and put the arrow sprite on that. Then rotate the sub-GO instead of the main GO.
I think that should work.
If you can’t disable rotation on the main GO because of how you have your collision object then you might need to just have a second GO that has the arrow sprite and always set to its position and with the right rotation. So when you spawn an arrow let it also create the display GO and control it.

If you make templates with collections (then use collection factories instead of regular factories) this is possible and cleaner than plain GOs by the way.


#6

That worked! Also adding a collision with the display also helps with correcting collisions so they match with the rotation of the location go. It’s a bit laggy than I would like, but I think I can optimize it from here

For any one else who has this issue in the future, my code looks like this for the arrow:

function init(self)
	self.arrowpos0=go.get_position()
	self.idc=0
	self.id=0
	self.start_tracking=false
end

function update(self, dt)
	if self.start_tracking==true then
		go.set_position(go.get_position(self.idc))
		self.arrowpos1=go.get_position()
		self.direction=self.arrowpos0-self.arrowpos1
		self.angle=math.atan2(self.direction.y,self.direction.x)
		self.rotation=vmath.quat(vmath.quat_rotation_z(self.angle))
		go.set_rotation(self.rotation, self.id)
		self.arrowpos0=go.get_position()
	end
end

function on_message(self, message_id, message, sender)
	self.idc=message["ida"]
	self.id=message["idb"]
	self.start_tracking=true
end

For the player (the person spawning the arrow)

self.arrow_spawn = collectionfactory.create("Charac#Arrow", go.get_position())
msg.post(self.arrow_spawn[hash("/Arrow")], "apply_force", {force = vmath.vector3(self.charge_bow*300*self.last_horiz, self.charge_bow+action.y*5, 0), position = go.get_world_position()})
msg.post(self.arrow_spawn[hash("/arrow")], "id", {ida=self.arrow_spawn[hash("/Arrow")],idb=self.arrow_spawn[hash("/arrow")]})

and the outline for the arrow’s spawn collection


#7

If you’re using a dynamic body, you can use go.get("#collisionobject", "linear_velocity") instead of getting the difference in position between frames.