Hi everyone, I'm new to Godot and gamedev in general. Been lurking for a while and I've had many problems all of which I've been able to solve with determination (and searching the forums!) but I've hit upon the first problem I seemingly can't solve.

I have a cannon firing a ball.

The cannon is an Area2D as the main parent Node.
I have a CollisionShape2D, Sprite, Position2D (Muzzle) and Label all as separate children beneath.

Dragging with the RMB pressed rotates the cannon:

rotation_degrees += (event.relative.y / zoom)

if event.is_action_pressed("ui_accept"):
		var new_ball = Ball.instance()
		new_ball.position = $Muzzle.position
		#generic velocity for now
		new_ball.linear_velocity = Vector2(600,-800)
		add_child(new_ball)

This works absolutely fine.

However the label (used to show the angle) rotates also.
If I make the Position2D a child of the sprite and change the code to rotate the sprite instead of the Area2D, when the Ball is fired it just stays in the same initial place the muzzle has before rotation.

$Sprite.rotation_degrees += (event.relative.y / zoom)

if event.is_action_pressed("ui_accept"):
		var new_ball = Ball.instance()
		new_ball.position = $Sprite/Muzzle.position
		#generic velocity for now
		new_ball.linear_velocity = Vector2(600,-800)
		add_child(new_ball)

I thought it might be global_position instead but that spawns the ball somewhere off the bottom of the screen.

No idea what is going on. Any help would be great.

  • I'm sorry, I misread the question. Ignore my other comment. Properties such as position or rotation are local (relative to the direct parent). If you need another coordinate space, then you need to convert from the local to another local space (not global, global can have other problems if you're not careful).

    var new_position = sprite.transform.xform(muzzle.position)

    That would move it to the sprites transform. But if you need two levels up, then you'd need to do it twice.

    var new_position = transform.xform(sprite.transform.xform(muzzle.position))

That looks correct. Position2D does not have a rotation, so the changing the rotation should not change anything. You should just use the first method, but set the rotation of the label to the negative of the cannon on process.

    cybereality Hi cybereality, thanks for taking the time to reply. I thought Position2Ds were meant to stay relative with their child though? If I rotate the sprite in editor, the Position2D rotates perfectly along with the sprite, staying exactly at the end of the barrel at all times.

      I'm sorry, I misread the question. Ignore my other comment. Properties such as position or rotation are local (relative to the direct parent). If you need another coordinate space, then you need to convert from the local to another local space (not global, global can have other problems if you're not careful).

      var new_position = sprite.transform.xform(muzzle.position)

      That would move it to the sprites transform. But if you need two levels up, then you'd need to do it twice.

      var new_position = transform.xform(sprite.transform.xform(muzzle.position))

        cybereality it's cool 😊 thanks cybereality. I'll try that out later and report back.