Bullets move with the player

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By KlonAnon

I’m programing my first own godot project and want to implement some bullets. I chose a KinematicBody2D for the bullets (not sure if this is the best way to do this), the only problem is that the bullets move with the player, and I dont know how to avoid that.

The scene structure looks like this:
Scene
|Player (child of Scene)
|Weapon (Child of Player)
|bullet (Child of Weapon)

The code of the player:

extends KinematicBody2D


export (int) var speed = 200
export (int) var lifepoints = 100
var velocity = Vector2()


func get_input():
    velocity = Vector2()
    if Input.is_action_pressed("ui_up"):
	    velocity.y -= 1
    if Input.is_action_pressed("ui_down"):
	    velocity.y += 1
    if Input.is_action_pressed("ui_left"):
	    velocity.x -= 1
    if Input.is_action_pressed("ui_right"):
	    velocity.x += 1

    if Input.is_action_just_pressed("left_clicked"):
	    $BaseWeapon.fire()


func _physics_process(delta):
    get_input()

    if velocity.length() > 0:
	    velocity = velocity.normalized() * speed
	    $AnimatedSprite.play()
    else:
	    $AnimatedSprite.stop()
	    $AnimatedSprite.frame = 0
	
    velocity *= delta

    if velocity.x < 0:
	    $AnimatedSprite.flip_h = true
    elif velocity.x > 0:
	    $AnimatedSprite.flip_h = false

    velocity = move_and_collide(velocity)

The code of the weapon:

extends Node2D

export (int) var damage
export (int) var reloadtime
export (int) var firerate = 1 #shots per sec
export (int) var capacity 
export (PackedScene) var Bullet #bullet type


func fire():
    var bullet = Bullet.instance()
    add_child(bullet)
    bullet.shoot(position, 0)

The code of the bullet:

extends KinematicBody2D


export (int) var bullet_speed = 750 #pixels/sec
var velocity = Vector2()


func shoot(pos, dir):
    position = pos
    rotation = dir
    velocity = Vector2(bullet_speed, 0).rotated(rotation)


func _physics_process(delta):
    var collision = move_and_collide(velocity * delta)
:bust_in_silhouette: Reply From: Zylann

In Godot, node positions are always relative to their parent.
You placed your bullets as child of the weapon. And your weapon is child of the player. So… your weapon will move with the player, and so will your bullets.

If you want bullets to be relative to the level root instead, you should spawn them under it, as siblings of the player.
Given your weapon creates the bullets, that should make it work:

func fire():
    var bullet = Bullet.instance()

    # Going up once gets the player handing the weapon,
    # And a second time to get the parent of the player,
    # which I suppose is the root of your level
    var level_root = get_parent().get_parent()

    level_root.add_child(bullet)
    bullet.shoot(position, 0)

Just use get_tree().get_root() so the code won’t break if you change player’s path

A112Studio | 2020-05-11 19:26

Depends. Spawning bullets under “the same parent as the player” or “under the root of the scene tree” are two ideas that can work well.
In fact get_root() would be useful if the weapon can be used without a user (i.e directly in the level, not child of a game object).

Zylann | 2020-05-11 19:47