Godot Engine v4.2.2.stable.official.15073afe3
Question
Pretty much what the title says. Here are the two scripts, each attached to the root notes of their respective scenes.
joker.gd/joker.tscn (this is the character)
extends CharacterBody2D
var direction: = Vector2.ZERO
var speed = 100
var can_flip = true
var stepping = false
var is_actionable = true
var target_velocity = Vector2.ZERO
var smoothing = 7.5
var has_card = false
signal select_suit(current_suit: String)
@onready var sprite = $Sprite2D
@onready var anim_player = $AnimationPlayer
enum State { IDLE, RUNNING, JUMPING }
var state: State = State.IDLE
func _ready():
#Engine.time_scale = 0.2
pass
func _process(delta):
if state in [State.IDLE, State.RUNNING]:
is_actionable = true
else:
is_actionable = false
func _physics_process(delta):
movement()
jump()
attackA()
if is_actionable:
velocity = direction * speed
move_and_slide()
elif state == State.JUMPING:
velocity = velocity.lerp(target_velocity, smoothing * delta)
move_and_slide()
func movement():
if stepping:
speed = 100
else:
speed = 0
if is_actionable:
can_flip = true
direction = Input.get_vector("p1left", "p1right", "p1up", "p1down").normalized()
if direction.length() > 0:
state = State.RUNNING
anim_player.play("jokerRun")
else:
state = State.IDLE
stepping = false
anim_player.play("jokerIdle")
if can_flip == true:
if direction.x < 0:
sprite.flip_h = true
$CollisionShape2D.position = Vector2(0.5, 0)
elif direction.x > 0:
sprite.flip_h = false
$CollisionShape2D.position = Vector2(-0.5, 0)
func step():
stepping = !stepping
if state == State.JUMPING:
can_flip = !can_flip
$CollisionShape2D.disabled = !$CollisionShape2D.disabled
if $CollisionShape2D.disabled:
sprite.z_index = 2
func jump():
if Input.is_action_just_pressed("p1roll") and is_actionable:
print("boing")
state = State.JUMPING
stepping = false
can_flip = false
anim_player.play("jokerJump")
await anim_player.animation_finished
state = State.IDLE
sprite.z_index = 1
if state == State.JUMPING:
direction = Input.get_vector("p1left", "p1right", "p1up", "p1down").normalized()
target_velocity = direction * speed
func attackA():
if Input.is_action_just_pressed("p1attackA") and not has_card:
var suit = ["spade", "club", "heart", "diamond", "ace", "joker"]
var rng = RandomNumberGenerator.new()
rng.randomize()
var index = rng.randi_range(0, 5)
var current_suit = suit[index]
has_card = true
print("you got ",current_suit, "!")
select_suit.emit(current_suit)
keep track of when signal “select_suit” is declared, and how it is used
jokerSuit.gd/jokerSuit.tscn (supporting scene)
extends Node2D
@onready var anim_player = $AnimationPlayer
@onready var joker = preload("res://scenes/joker.tscn").instantiate()
func _ready():
add_child(joker)
joker.select_suit.connect(selectSuit)
func _process(delta):
pass
func selectSuit(current_suit):
print("the selected suit is: ", current_suit)
Why does the final print message not get printed? Also, am I using my signals right/cleanly (do I have spaghetti code)?
Can you show your scene tree? If the joker
node is already present in your scene tree when the game starts, the issue might be that you’re not connecting the signal to that instance. In your current code, you’re instantiating a new joker
node in jokerSuit.gd
, which is different from the one already in the scene. This would explain why the signal isn’t working as expected.
How are you getting to this function:?
func attackA()
Does this get printed:?
print("you got ",current_suit, "!")
If the joker character is already placed in the scene, then in joker_suit.gd, you would need to reference the existing node in the tree. Right now, the line:
@onready var joker = preload(“res://scenes/joker.tscn”).instantiate()
creates a new joker, which would not be the one in the scene tree already which would cause your signal to never fire.
If joker already exists in the scene, suggested options could be the two listed below:
Use @onready var to get the existing node:
@onready var joker = get_node(“PathToJoker”)
Or use an exported variable to assign the node from the editor:
@export var joker: CharacterBody2D
If the goal is for joker_suit to spawn and manage its own joker instance, then that changes what the issue could be. If that is the case, can you share a screenshot of your scene tree showing where joker_suit is within the scene tree?
attackA() is constantly checked for in _physics_process(delta):
func _physics_process(delta):
movement()
jump()
attackA()
when the character does not have a card (he gains a card from attackA()) and inputs “p1attackA,” the function is triggered
func attackA():
if Input.is_action_just_pressed("p1attackA") and not has_card:
var suit = ["spade", "club", "heart", "diamond", "ace", "joker"]
var rng = RandomNumberGenerator.new()
rng.randomize()
var index = rng.randi_range(0, 5)
var current_suit = suit[index]
has_card = true
print("you got ",current_suit, "!")
select_suit.emit(current_suit)
the message does get printed.
Ok, I’ll fully explain what I am trying to achieve.
This the scene for joker.tscn
. It is a CharacterBody2D
and is what is controlled.
^^^ in the game, joker is moving
When I input p1attackA
, the character selects a card [spade, club, heart, diamond, ace, joker]
. What I want is, alongside selecting the card, a signal carrying with it information on WHAT card is selected (current_suit
) to be transmitted to the SEPARATE SCENE jokerSuit.tscn
.
This scene will serve as a an icon that follows around the character, showing what card has been selected. However, this comes later, right know I just want to make sure that the correct information is transmitted by printing a message letting me know what the current_suit
is.
I want to use signals instead of preloading because the latter will likely cause a circular dependency within my code.
Try this:
extends Node2D
@onready var anim_player = $AnimationPlayer
@onready var joker = preload("res://scenes/joker.tscn").instantiate()
func _ready():
add_child(joker)
await get_tree().process_frame
joker.select_suit.connect(selectSuit)
func _process(delta):
pass
func selectSuit(current_suit):
print("the selected suit is: ", current_suit)
I added this line: await get_tree().process_frame
which waits one frame before executing the next line. If it doesn’t work, try separating the spawn logic from the signal connection logic.
This doesn’t do anything.
Try this one. Remove the joker.select_suit.connect(selectSuit)
from the jokerSuit.gd
and add this on the joker.gd
instead:
func _ready():
if get_parent().has_method("selectSuit"):
select_suit.connect(get_parent().selectSuit)
I don’t know if this works, but it makes sure the scene is loaded and the parent (which is jokerSuit) is ready before connecting the signal.