getting_started/first_2d_game/06.heads_up_display #69
Replies: 43 comments 74 replies
-
In the last part about "removing old creeps" the newest version of Godot now supports global and scene groups. |
Beta Was this translation helpful? Give feedback.
-
C# users must change the connections under the Node tab to C# nomenclature, not the default it provides you. Change these: _on_start_button_pressed to: OnStartButtonPressed or, if you've already created the script as guided, you can select the Pick button to the right of the text field when editing the connection, and then select the appropriate method. |
Beta Was this translation helpful? Give feedback.
-
why am i not able to connect start_game signal of HUD node to new_game() function of Main node? |
Beta Was this translation helpful? Give feedback.
-
when i am trying to connect start_game signal of HUD node to new_game() function of Main node , I can't find the function new_game() in the options in the pop? |
Beta Was this translation helpful? Give feedback.
-
When I create a new group named "mobs" and use the code to clear all mobs, the Player and the HUD are also cleared. I assume the problem is that they are being included the in mobs group, but I have no idea how this group is supposed to know what is inside it anyway. How do I make sure the "mobs" group only contains instances of Mob? |
Beta Was this translation helpful? Give feedback.
-
Something breaking down between my _on_start_button_pressed and new_game, not sure what I'm missing. Tried disconnecting and reconnecting, but no change. new_game triggers fine if I have _ready call it. I'm seeing the debug print I added for the start button press. Best I can tell is the signal isn't being emitted. Anyone have an idea what's breaking down? Here's my _on_start_button_pressed: func _on_start_button_pressed():
print("Debug: Start Button pressed")
$StartButton.hide()
start_game.emit Here's my new_game: func new_game():
print("Debug: new_game called")
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
$HUD.update_score(score)
$HUD.show_message("Get Ready") |
Beta Was this translation helpful? Give feedback.
-
I was crashing with an error that it couldn't find "$HUD.update_score(score)" and I had to poke around for the solution. Mine was named #hud and not #HUD. Case matters apparently, because I fixed the case and the game works fine. Hope that makes sense and helps someone. |
Beta Was this translation helpful? Give feedback.
-
So I worked through this over a couple of days and I was a bit confused at the end because I realized that I never added my mob scene to the Main tree. So I was left wondering "how the f is this even connected?" Of course it was a bit simple to solve by simply going backwards. But I wonder if it would be useful to show the mob scene in the tree somehow. Basically to show its being used by Mobpath. Maybe this would be good for a small game like this, and would be problematic in a complicated scene. |
Beta Was this translation helpful? Give feedback.
-
Hi all, I have having an issue after pressing Start button. Error message: Attempt to call function 'start' in base 'null instance' on a null instance. There seems to be an issue with the message timer activation. 3 things were called onto the stack frames and the corresponding code below:
func show_message(text):
$Message.text = text
$Message.show()
$MessageTimer.start()
func new_game():
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
$HUD.update_score(score)
$HUD.show_message("Get Ready")
get_tree().call_group("mobs", "queue_free")
func _on_start_button_pressed():
$StartButton.hide()
start_game.emit() Can anyone share where I went wrong? |
Beta Was this translation helpful? Give feedback.
-
The instructions say to extend HUD from CanvasLayer. But if I do I get this error: script inherits from native type ‘area2d’ so it cannot be instanced in object of type node Changing it to "extends Node" works - I found a similar question posed online too so I was surprised not to see a similar comment here. |
Beta Was this translation helpful? Give feedback.
-
Hello I am having some issues with my scripts breaking at the start_game.emit() portion of the code. I have added signal start_game to the top of the HUD.gd script, under extends CanvasLayer, and linked the start game signal from later in the hud.gd script func _on_start_button_pressed():
$StartButton.hide()
start_game.emit() to the new_game() function in the main.gd script func new_game():
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
$HUD.update_score(score)
$HUD.show_message("Get Ready")
get_tree().call_group("mobs", "queue_free") Despite seemingly following the instructions, when I press the start button the game crashes, and the debugger identifies the line with start_game.emit() as the point where the code breaks. Can anyone tell me what I am doing wrong? |
Beta Was this translation helpful? Give feedback.
-
I also had to start the $ScoreTimer.start()
$MobTimer.start() |
Beta Was this translation helpful? Give feedback.
-
I'm pretty sure I followed all the instructions but for some reason the score wont update. It merely stays at zero |
Beta Was this translation helpful? Give feedback.
-
When trying to make a signal from hud - start_game() to Main - new_game(). In the Connect a Signal to a method window I select Main (root node), but in the Select Method window the new_game() function is not appearing even though the main.tscn file is attached to the Main node. So I cant make the signal work. I have a working Player hit signal so I don't know what the Issue is. See: https://i.imgur.com/suCspm4.jpeg Using Godot Engine v4.3.stable.official [77dcf97d8] |
Beta Was this translation helpful? Give feedback.
-
I had a rather trivial question on the function design here:
In this function, the callee
This approach makes sure that the usage of $MessageTimer only stays inside the |
Beta Was this translation helpful? Give feedback.
-
I'm really new to godot so perhaps it's a stupid question: |
Beta Was this translation helpful? Give feedback.
-
Just a tip, when I encounter bugs (as I did on the last two sections) it helped me to compare my GDscript code to the tutorial code from the Github link they shared. For whatever reason there have been a couple of instances where I totally left out lines of code in a function for some reason, and just comparing my functions to the Github code has been a quick and easy way to tell if I just missed something or mistyped something. |
Beta Was this translation helpful? Give feedback.
-
My God I actually finished it. I have no training or coding skills but still can't shake a fascination with it. But I changed it so player turns in whatever direction they're going, also changed $HUD.show_game_over() to $HUD.show_message("Game Over"), where you can put whatever text you want there. There is one problem: none of the creeps are moving. They spawn randomly along the path, and animate correctly, but don't go anywhere. The "Game Over" works when I run into them, but they're paralyzed. Did this happen with anyone else? Does it have to do with paths? Here's the code I have for that section, I'd appreciate any help: func _on_mob_timer_timeout() -> void:
# create a new instance of the scene
var mob = mob_scene.instantiate()
# Choose a random location on Path2D.
var mob_spawn_location = $MobPath/MobSpawnLocation
mob_spawn_location.progress_ratio = randf()
# Set the mob's direction perpendicular to the path direction.
var direction = mob_spawn_location.rotation + PI / 2
# Set the mob's position to a random location
mob.position = mob_spawn_location.position
# Add some randomness to the direction.
direction += randf_range (-PI / 4, PI / 4)
mob.rotation = direction
# Choose the velocity for the mob
var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
add_child(mob) |
Beta Was this translation helpful? Give feedback.
-
help me i have a problem with the player being invisible in-game and when in title screen the player is visible here is my code # player.gd
extends Area2D
signal hit
@export var speed = 400 # How fast the player will move (pix/sec)
var screen_size # Size of the game window.
func _ready():
screen_size = get_viewport_rect().size
show()
func _process(delta):
var velocity = Vector2.ZERO # The player's movement vector
if Input.is_action_pressed("move_right"):
velocity.x += 1
if Input.is_action_pressed("move_left"):
velocity.x -= 1
if Input.is_action_pressed("move_down"):
velocity.y += 1
if Input.is_action_pressed("move_up"):
velocity.y -= 1
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += velocity * delta
position = position.clamp(Vector2.ZERO, screen_size)
if velocity.x < 0:
$AnimatedSprite2D.flip_h = true
else:
$AnimatedSprite2D.flip_h = false
func _on_body_entered(_body: Node2D) -> void:
pass # Replace with function body.
hide() # Player disappears after being hit
hit.emit()
# Must be deferred as we can't change physics proprierties on a physics callback.
$CollisionShape2D.set_deferred("disabled", true)
func start(pos):
position = pos
show()
$CollisionShape2D.disabled = false # main.gd
extends Node
@export var mob_scene: PackedScene
var score
func game_over():
$ScoreTimer.stop()
$MobTimer.stop()
$HUD.show_game_over()
$Music.stop()
$DeathSound.play()
func new_game():
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
$HUD.update_score(score)
$HUD.show_message("Get ready!")
$Music.play()
get_tree().call_group("mobs", "queue_free")
func _on_score_timer_timeout():
score += 1
$HUD.update_score(score)
func _on_start_timer_timeout():
$MobTimer.start()
$ScoreTimer.start()
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on Path2D.
var mob_spawn_location = $MobPath/MobSpawnLocation
mob_spawn_location.progress_ratio = randf()
# Set the mob's direction perpendicular to the path direction.
var direction = mob_spawn_location.rotation + PI / 2
# Set the mob's position to a random location.
mob.position = mob_spawn_location.position
# Add some randomness to the direction.
direction += randf_range(-PI / 4, PI / 4)
mob.rotation = direction
# Choose the velocity for the mob.
var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
mob.linear_velocity = velocity.rotated(direction)
# Spawn the mob by adding it to the Main scene.
add_child(mob) |
Beta Was this translation helpful? Give feedback.
-
Hi I am having problem with the Start button, It does nothing when I press it. My Main: extends Node
@export var mob_scene: PackedScene
var score
func game_over():
$MobTimer.stop()
$ScoreTimer.stop()
$HUD.show_game_over()
func new_game():
get_tree().call_group("mobs", "queue_free")
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
$HUD.update_score(score)
$HUD.show_message("Get Ready")
func _on_score_timer_timeout():
score += 1
$HUD.update_score(score)
func _on_start_timer_timeout():
$MobTimer.start()
$ScoreTimer.start()
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on Path2D.
var mob_spawn_location = $MobPath/MobSpawnLocation
mob_spawn_location.progress_ratio = randf()
# Set the mob's direction perpendicular to the path direction.
var direction = mob_spawn_location.rotation + PI / 2
# Set the mob's position to a random location.
mob.position = mob_spawn_location.position
# Add some randomness to the direction.
direction += randf_range(-PI / 4, PI / 4)
mob.rotation = direction
# Choose the velocity for the mob.
var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
mob.linear_velocity = velocity.rotated(direction)
# Spawn the mob by adding it to the Main scene.
add_child(mob) my HUD: extends CanvasLayer
# Notifies `Main` node that the button has been pressed
signal start_game
func show_message(text):
$Message.text = text
$Message.show()
$MessageTimer.start()
func show_game_over():
show_message("Game Over")
# Wait until the MessageTimer has counted down.
await $MessageTimer.timeout
$Message.text = "Dodge the Creeps!"
$Message.show()
# Make a one-shot timer and wait for it to finish.
await get_tree().create_timer(1.0).timeout
$StartButton.show()
func update_score(score):
$ScoreLabel.text = str(score)
func _on_start_button_pressed():
$StartButton.hide()
start_game.emit()
func _on_message_timer_timeout():
$Message.hide()
|
Beta Was this translation helpful? Give feedback.
-
I just wanted to state my issue and how I resolved it for anyone who may have been dealing with the same thing. When trying to get the script to delete the old creeps by using the call group function to have them cleared from queue, it was not working for me in the new game function. I remedied by adding the same line of code to the game over function and it works like a charm. |
Beta Was this translation helpful? Give feedback.
-
Mine is saying the identifier "score" is not declared on my HUD.gd script but works fine on my main. any ideas? |
Beta Was this translation helpful? Give feedback.
-
I keep running into the error of A, my message will not go away after the game starts that says get ready, and B: when my player hits an enemy I get this error: Invalid call. Nonexistent function 'set_deffered' in base 'CollisionShape2D'. |
Beta Was this translation helpful? Give feedback.
-
Guys never fear, I will save you a lot of stress and time. I also had the issue connecting my start_game() signal to new_game(). I went through all these comments and used chatGPT for literally 4 or more hours or more before I finally resolved the issue. So go ahead and try all the above suggestions as they might help. But if you are emitting the signal, and you do have all your scripts correctly written than maybe you had the same problem I had. When I dragged the Hud scene into the Main Node it replaced the main nodes script with the HUD script. Anyway, there is no way to tell this without looking at the inspector. Click on your node, go to the bottom of the inspector, make sure the correct script is associated to that node. |
Beta Was this translation helpful? Give feedback.
-
C# question: Is there a way to connect a signal's emission to a method that does I have the following for the "Game Over" method in the Main scene's script, private async void GameOver()
{
GetNode<Timer>("MobTimer").Stop();
GetNode<Timer>("ScoreTimer").Stop();
await GetNode<HUD>("HUD").ShowGameOverAsync();
} The issue is if you declare it as
Here's My "Show Game Over" method in the HUD scene: public async Task ShowGameOverAsync()
{
ShowMessage("Game Over");
Timer messageTimer = GetNode<Timer>("MessageTimer");
await ToSignal(messageTimer, Timer.SignalName.Timeout);
Label message = GetNode<Label>("Message");
message.Text = _defaultMessageText;
message.Show();
await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
GetNode<Button>("StartButton").Show();
} |
Beta Was this translation helpful? Give feedback.
-
"Get ready!" wouldn't disappear for me after pressing the start button. I got it to work by going to the HUD tab at the top (hud.tscn), clicking on MessageTimer, and connecting it to HUD with a timeout() signal. |
Beta Was this translation helpful? Give feedback.
-
If you can't get the score to increase, make sure you're using "score += 1" instead of "score =+ 1" like I did. hud.gd should look like this func update_score(score):
score += 1
$ScoreLabel.text = str(score) And main.gd should look like this func _on_score_timer_timeout():
score += 1
$HUD.update_score(score) |
Beta Was this translation helpful? Give feedback.
-
My score timer briefly pauses and then keeps going up after a game over, as if I was still playing. It does reset back to 0 when I press start again. Any advice? I can provide my code if needed. Here's my main.gd extends Node
@export var mob_scene: PackedScene #selects the mob scene we want to insance
var score
func _ready(): #can use new_game to test out the game
pass
func game_over(): #handles game over
$ScoreTimer.stop()
$MobTimer.stop()
$HUD.show_game_over()
$Music.stop()
$DeathSound.play()
func new_game(): #starts new game
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
$HUD.update_score(score)
$HUD.show_message("Get ready!")
get_tree().call_group("mobs", "queue_free") #calls mob to delete itself
$Music.play()
func _on_mob_timer_timeout():
var mob = mob_scene.instantiate() #creates new instance of mob scene
var mob_spawn_location = $MobPath/MobSpawnLocation #choose random location on Path2D
mob_spawn_location.progress_ratio = randf()
var direction = mob_spawn_location.rotation + PI / 2 #sets mob direction perpendicular to path direction
mob.position = mob_spawn_location.position #sets mob position to random location
direction += randf_range(-PI / 4, PI / 4) #Add randomness to direction
mob.rotation = direction
var velocity = Vector2(randf_range(150.0, 250.0), 0.0) #choose mob velocity
mob.linear_velocity = velocity.rotated(direction)
add_child(mob) #spawn mob by adding it to scene
func _on_score_timer_timeout(): #increases score by 1
score += 1
$HUD.update_score(score)
func _on_start_timer_timeout(): #the start timer will start the other 2 timers
$MobTimer.start()
$ScoreTimer.start() |
Beta Was this translation helpful? Give feedback.
-
I just spent literal hours trying to get to the bottom of this following issue, with no success. Basically, I don't understand why I'm getting this automatically attached signal (the yellow one): Due to this connection I can't disconnect, and due to using the following method, the game would end up in a stack overflow every time I pressed the "Start Game" button:
Renaming the method as follows got rid of the issue:
The yellow connection remains there though, no matter what. In the sample project from the GODOT github it doesn't exist. If anyone has any idea why this might be happening in my case, I'd appreciate the help! |
Beta Was this translation helpful? Give feedback.
-
I am throwing an error that the "Attempt to call function 'update_score' in base 'null instance' on a null instance". The error throws at the
code. ChatGPT hasn't been super helpful. I noticed this first after the "Connecting HUD to Main" section of this part of the tutorial. I have gone back through and I think I instantiated the Child Scene correctly to connect HUD to Main. I am new to all this and maybe made other mistakes along the way (such as not writing this code under the
function. Any advice or fixes would be super helpful! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
getting_started/first_2d_game/06.heads_up_display
The final piece our game needs is a User Interface (UI) to display things like score, a "game over" message, and a restart button. Create a new scene, click the "Other Node" button and add a Canvas...
https://docs.godotengine.org/en/stable/getting_started/first_2d_game/06.heads_up_display.html
Beta Was this translation helpful? Give feedback.
All reactions