Hi there.
I have this simple code for a bullet scene. I’m trying to find a way to change the Vector2.direction via my direction key presses for my character.
I’m calling the instance of the bullet scene in the character script via a fire button press. I’m trying to avoid huge amounts of if statements.
I can’t find a way to change the Vector2 direction when moving up, down , left, right.
I’m just learning and I’m really struggling trying to find how to make one script talk to another. Any help highly appreciated.
It would be helpful to see your player code that you are “calling” the bullet scene with.
What do you mean by “calling” are you loading and instantiating it?
If you are instantiating a bullet scene you could use that code to pass your characters vector to a variable on the bullet. Then use that variable rather than Vector2.RIGHT.
Player → add_child(bullet)
bullet.dir = player_dir
Bullet → global_position += dir * BULLETSPEED * delta
This is just a possibility, but I don’t know how you have the player and bullet coupled.
Hi regnarok!
Yes that makes much more sense. Sorry I wasn’t using the correct terminology. Yes, I’m instantiating a bullet scene in the player script but I should be controlling the direction of the bullet scene I’m instantiating from the player script and at the moment it’s kind of hard coded into the bullet script. Your code suggestion looks like the correct way to go about. I wasn’t thinking straight trying to do all this in the bullet script, doh!
Thank you so much man, really appreciate your help again!
I had to break it down again because when I try to move the instantiated bullet scene it doesn’t move. It shows up on screen but then just moves when I press direction keys.
can you move and instantiated scene like this? I’m just using Vector2.RIGHT for now while I test to get it going.
bullet_ins.global_position += Vector2.RIGHT * BULLET_SPEED * delta
Okay, so I think you ended up moving your bullet script to your plaayer body?
I would say if your bullet is a fire and forget don’t “control” it from player script.
Instantiate it like you did before, but add an extra variable to the bullet script var fire_dir:Vector2.
In your player script add a var player_dir:Vector2. Now when you instantiate bullet, after add_child(bullet), add bullet.fire_dir = player_dir. Under your var direction in player script write player_dir = direction.
Return your bullet move script back to bullet script and change the Vector2.RIGHT that you had with the new variable fire_dir.
The problem you have right now is you have an input check as a condition for your bullet movement, so it will only move if you are pressi g the input.
Sorry on my phone it is hard to write out the code. If you still havent gotten it working by the time I’m next at my computer I’ll wrire up a code example.
Ok I had a problem with the way I got the movement left and right set up with get_axis
So far it’s working like this following code. Not sure its the most efficient way to write it out but it works. The bullet doesn’t come from the player position yet but so far its working
extends CharacterBody2D
const SPEED : int = 600
const BULLET_SPEED : int = 2000
var bullet_ready : bool = true
var bullet_tscn = preload("res://bullet.tscn")
var player_dir : Vector2
@onready var player_body = $Sprite2D/Marker2D
func _physics_process(delta: float) -> void:
velocity += Vector2() * delta
if Input.is_action_just_pressed("shoot") and bullet_ready: #shoot is W
var bullet_ins = bullet_tscn.instantiate()
add_child(bullet_ins)
bullet_ins.fire_dir = player_dir
bullet_ready = false
$Bullet_Timer.start()
if Input.is_action_pressed("move_player_right"):
player_dir = Vector2.RIGHT
velocity.x = SPEED
elif Input.is_action_pressed("move_player_left"):
player_dir = Vector2.LEFT
velocity.x = -SPEED
else:
velocity.x = move_toward(velocity.x, 0, 30)
if Input.is_action_pressed("move_player_up"):
player_dir = Vector2.UP
velocity.y = -SPEED
elif Input.is_action_pressed("move_player_down"):
player_dir = Vector2.DOWN
velocity.y = SPEED
else:
velocity.y = 0
move_and_slide()
func _on_bullet_timer_timeout() -> void:
bullet_ready = true
In a little while when my son takes his nap I will try and write up some actual code to demonstrate what I am saying. Then ill post it here.
If you don’t need to control something from llayer it is better not to. Also, if you end up with multiple instances of bullet you will potentially run into an issue with that as well.
If bullet needs to move it is best to do so from bullet script, and just give it the var it needs to know when you instantiate it.
Okay, so I took your code and replicated and made it function. Not sure if it is exactly what you want.
What it does → You have a character that has 8 directional movement, and he can shoot a bullet that will go in the direction that he is moving when he fires.
Node Structure
Main
Player
BulletHolder # Protects the bullets from following players relative position
Player Code
extends CharacterBody2D
const SPEED : int = 200
var bullet_ready : bool = true
var bullet_tscn = preload("res://bullet.tscn")
var player_dir : Vector2 = Vector2.RIGHT
# This allows you to keep the bullets from following the player around,
# if they are a child of player they will keep a relative position to player
# as he moves.
@onready var bullet_holder = $"../BulletHolder"
func _physics_process(delta: float) -> void:
var direction = Input.get_vector("west","east","north","south")
# This gives you smooth movement in any direction
if direction:
player_dir = direction
velocity = SPEED * direction
else:
velocity = Vector2.ZERO
move_and_slide()
# This is by mouse click, but that isn't important
if Input.is_action_just_pressed("interact") and bullet_ready:
var bullet_ins = bullet_tscn.instantiate()
bullet_holder.add_child(bullet_ins)
bullet_ins.set_start_pos(global_position)
bullet_ins.fire_dir = player_dir
Bullet Code
extends Sprite2D
const BULLET_SPEED: int = 400
# Gets fire direction from player
var fire_dir: Vector2
# Sets position to be at the players position
func set_start_pos(pos:Vector2) -> void:
global_position = pos
# Moves the bullet in direction of player
func _physics_process(delta: float) -> void:
global_position += fire_dir * BULLET_SPEED * delta
This gives you a baseline to work from, obviously for ease of management and to address your primary question I removed the bullet timer aspect, and any queue_free calls in order to just get your primary issue solved. I also made the bullet only a Sprite2D because I was lazy and didn’t feel like making it an Area2D haha.
If this isn’t what you are looking for, let me know exactly what you would like to accomplish.
This is great, thanks so much. I have to play around with this now. There are definitely some things in there that I had no idea about. get_vector for example. This solves the whole if statement mess on the player movement. I have to understand how the BulletHolder is working but I’m gonna learn a lot from this.
I’m just doing kind of mini projects in Godot to master the code for different types of player and enemy movements and things like that before I jump and try to do anything more ambitious. :0)
Honestly I just added to bullet holder to get it to work how I wanted it to. Another way would be making the bullets a child of main. It is just a node that doesn’t move and has no code.
If you attach the bullets as children of player, when your player moves they move with the player.
So, BulletHolder gives you a fixed locatio to use to spawn bullets.
I am sure there are other ways to do that, that was just my quick solution to get it working. If I were to make a game with those mechanics I might explore other ways.
I figured out you could use a Marker2d like @onready var bullet_spawn = $Player/Marker2d
and then
bullet_ins.global_position = bullet_spawn.global_position
something like that but your way looks more slick.