Rotating bullet objects

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?

1 Like

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.

6 Likes

Owo what a magnificent solution :smiley:

2 Likes

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

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.

3 Likes

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

4 Likes

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

6 Likes

I know it’s old, but I am doing it today and I am using dynamic objects, so wanted to use this:

but unfortunately go.set_rotation() is not affecting it obviously nor can I rotate just the sprite, so how should I rotate the object?
@Pkeod pointed out of course to make two objects, of which one is rotated - but I am creating the bullet with factory, so should I make it into collectionfactory or make another factory inside to create just a game object with a sprite?

It is very sad, that we can’t rotate (nor move, nor scale) sprite component in runtime, this is just much more intuitive :frowning:

You should use the collectionfactory. Using collections as prefab containers is very efficient and allows relative messaging / easier cleanup. Extra GOs have a very very low runtime cost.

1 Like

Meh… :confused:
It just complicates things, as I am using a generic “missile” game object for all and create them using factory.create(), so another “if” for this case to change api call for collectionfactory.create() :smiley:
Another improvement could be to merge collectionfactory and factory (as they have exact same API!) :wink:

1 Like

I do think early tutorials should encourage people more to use collections as prefabs vs raw GOs. Show why with relative messaging / how much easier it is rather than trying to do complex situations with GOs directly.

1 Like

This might be a good example to show, though I think it’s a bit “hacky” :smiley:

I managed to do this (don’t mind the animations) :wink: :

2 Likes