Godot Top-Down Shooter, getting a bullet to fire from a rotated gun?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By genfy
:warning: Old Version Published before Godot 3 was released.

Okay, so I’m currently creating a top-down shooter with weapon switching, I’ve come across a problem.

First up, this is the layout of my player:
Project Layout
This is what I came up with, sprite is rotated to “look_at” the mouse position, then the gun is a child of the mouse so it’s rotation is changed too.

Now I want to fire a bullet from a gun, so I came up with this:
Picture of what I want to happen
Basically I want to find a point on a circle.

So I used the following equations:

x = centreX + radius * cos(rotation)
y = centreY + radius * sin(rotation)

In this line of code:

var posOnCircle = Vector2(pos.x + radius * cos(rotation), pos.y + radius * sin(rotation))

pos - centre of player
radius - pre-defined radius
rotation - rotation in radians

And this doesn’t work for me. Maybe I’m overcomplicating things, I’d be satisfied with a better solution to the problem rather than just a fix, but this is what I came up with.

:bust_in_silhouette: Reply From: Nophlock

Well this should work quite nice for your needs, I hope:

var rotation  = self.get_rot()
var direction = Vector2(sin(rotation), cos(rotation))
var distance_from_me = 100 #need to best adjusted by you
var spawn_point      = self.get_global_pos() + direction * distance_from_me
var bullet = bullet_scene.instance()
var wolrd  = self.get_node("../world") #of wherever you're bullet should spawn, but don't spawn it as a player child

world.add_child(bullet)
bullet.set_global_pos(spawn_point)

You can then also pass the direction vector to the bullet, to use that as the movement for it in the _process(dt) function.
Note: Maybe you need to add PI/2 or something like that to the rotation variable if the bullet spawns in the wrong angle of your player if for example your sprite has any base rotation applied to it.

Hope that helps :slight_smile:

I don’t know anything about cos and sin but i used Vector2(cos(rotation), sin(rotation)) and it works but your doesn’t works

Chisk3n0 | 2019-01-01 00:08

Thx Chisk3n0. I figured it out the same and then saw you comment (confirming this).

Naxos84 | 2020-04-19 23:17

:bust_in_silhouette: Reply From: rgrams

I just use a Node2D “shotpoint” as both the spawn point for the bullet, and as a target position to calculate the shot’s direction vector. Assuming you want to fire your bullet on a vector straight from the origin of this node, you do:

var shotscene = preload("res://bullet.tscn")
var shotspeed = 1000.0

func fire():
     var shot = shotscene.instance()
     var shotvect = (get_node("shotpoint").get_global_pos() - get_global_pos()).normalized()
     get_parent.add_child(shot)
     shot.set_global_pos(get_node("shotpoint").get_global_pos())
     shot.set_linear_velocity(shotvect * shotspeed) # if your shot is a rigidbody

     # If your shot is not a rigidbody and handles movement itself, set a velocity var 
     # on the shot before you add it to the scene so its ready() function fires after it is set. 

If you want to make a shotgun or any weapon that shoots multiple bullets in different directions, I’ve done it two ways:

A. Just move the “shotpoint” node (probably by rotating its parent) and call fire() again.

B. Iterate through multiple “shotpoint” nodes. Name them “shotpoint 0”, “shotpoint 1”, etc. Adjust the fire() function as follows:

var shotcount = 5 # as many as you want, as long as you have enough shotpoint nodes. 

func fire():
     for i in range(shotcount):
          var pos = get_node( "shotpoint " + str(i) ).get_global_pos()
          var shotvect = (pos - get_global_pos()).normalized()
          var shot = shotscene.instance()
          shot.velocity = shotvect * shotspeed
          get_parent().add_child(shot)
          shot.set_global_pos(pos)

rgrams | 2016-09-08 11:28

:bust_in_silhouette: Reply From: YeOldeDM

I have found a slightly more elegant solution to this than the ‘shotpoint’ method described above.

This is assuming your turret is facing “down” while at 0 rotation (from the orientation of Mr Godot in your screenshot that seems to be the case)

var barrel_length = 32   # Adjust as needed
var trans = get_global_transform()
var bullet_pos = trans.basis_xform( Vector2( 0, barrel_length ) )

Bullet_pos could also then be normalized, and re-used as the directional vector the bullet travels along.