mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-05 22:09:56 +03:00
Added C# examples & info for the Your First Game example (#1297)
* Added C# examples & information for the your first game example
This commit is contained in:
@@ -140,6 +140,9 @@ node, so we'll add a script. Click the ``Player`` node and click the
|
||||
In the script settings window, you can leave the default settings alone. Just
|
||||
click "Create":
|
||||
|
||||
.. note:: If you're creating a C# script or other languages, select the
|
||||
language from the `language` drop down menu before hitting create.
|
||||
|
||||
.. image:: img/attach_node_window.png
|
||||
|
||||
.. note:: If this is your first time encountering GDScript, please read
|
||||
@@ -147,28 +150,51 @@ click "Create":
|
||||
|
||||
Start by declaring the member variables this object will need:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends Area2D
|
||||
|
||||
export (int) var SPEED # how fast the player will move (pixels/sec)
|
||||
var screensize # size of the game window
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public class Player : Area2D
|
||||
{
|
||||
[Export]
|
||||
public int Speed = 0;
|
||||
|
||||
private Vector2 _screenSize;
|
||||
}
|
||||
|
||||
|
||||
Using the ``export`` keyword on the first variable ``SPEED`` allows us to
|
||||
set its value in the Inspector. This can be very handy for values that you
|
||||
want to be able to adjust just like a node's built-in properties. Click on
|
||||
the ``Player`` node and set the speed property to ``400``.
|
||||
|
||||
.. warning:: If you're using C#, you need to restart godot editor temporarily to see
|
||||
exported variables in the editor until it's fixed.
|
||||
|
||||
.. image:: img/export_variable.png
|
||||
|
||||
The ``_ready()`` function is called when a node enters the scene tree,
|
||||
which is a good time to find the size of the game window:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _ready():
|
||||
screensize = get_viewport_rect().size
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_screenSize = GetViewport().GetSize();
|
||||
}
|
||||
|
||||
Now we can use the ``_process()`` function to define what the player will do.
|
||||
``_process()`` is called every frame, so we'll use it to update
|
||||
elements of our game which we expect will change often. Here we'll make it:
|
||||
@@ -188,7 +214,8 @@ You can detect whether a key is pressed using
|
||||
``Input.is_action_pressed()``, which returns ``true`` if it is pressed
|
||||
or ``false`` if it isn't.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _process(delta):
|
||||
var velocity = Vector2() # the player's movement vector
|
||||
@@ -206,6 +233,36 @@ or ``false`` if it isn't.
|
||||
else:
|
||||
$AnimatedSprite.stop()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Process(float delta)
|
||||
{
|
||||
var velocity = new Vector2();
|
||||
if (Input.IsActionPressed("ui_right")) {
|
||||
velocity.x += 1;
|
||||
}
|
||||
|
||||
if (Input.IsActionPressed("ui_left")) {
|
||||
velocity.x -= 1;
|
||||
}
|
||||
|
||||
if (Input.IsActionPressed("ui_down")) {
|
||||
velocity.y += 1;
|
||||
}
|
||||
|
||||
if (Input.IsActionPressed("ui_up")) {
|
||||
velocity.y -= 1;
|
||||
}
|
||||
|
||||
var animatedSprite = (AnimatedSprite) GetNode("AnimatedSprite");
|
||||
if (velocity.Length() > 0) {
|
||||
velocity = velocity.Normalized() * Speed;
|
||||
animatedSprite.Play();
|
||||
} else {
|
||||
animatedSprite.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
We check each input and add/subtract from the ``velocity`` to obtain a
|
||||
total direction. For example, if you hold ``right`` and ``down`` at
|
||||
the same time, the resulting ``velocity`` vector will be ``(1, 1)``. In
|
||||
@@ -230,14 +287,24 @@ AnimatedSprite animation.
|
||||
So in the code above, ``$AnimatedSprite.play()`` is the same as ``get_node("AnimatedSprite").play()``.
|
||||
|
||||
Now that we have a movement direction, we can update ``Player``'s position
|
||||
and use ``clamp()`` to prevent it from leaving the screen:
|
||||
and use ``clamp()`` to prevent it from leaving the screen by adding the following
|
||||
to the bottom of the ``_process`` function:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
position += velocity * delta
|
||||
position.x = clamp(position.x, 0, screensize.x)
|
||||
position.y = clamp(position.y, 0, screensize.y)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
Position += velocity * delta;
|
||||
Position = new Vector2(
|
||||
Mathf.Clamp(Position.x, 0, _screenSize.x),
|
||||
Mathf.Clamp(Position.y, 0, _screenSize.y)
|
||||
);
|
||||
|
||||
|
||||
.. tip:: *Clamping* a value means restricting it to a given range.
|
||||
|
||||
@@ -258,7 +325,8 @@ property for left movement, and an "up" animation, which should be
|
||||
flipped vertically with ``flip_v`` for downward movement.
|
||||
Let's place this code at the end of our ``_process()`` function:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
if velocity.x != 0:
|
||||
$AnimatedSprite.animation = "right"
|
||||
@@ -267,16 +335,32 @@ Let's place this code at the end of our ``_process()`` function:
|
||||
elif velocity.y != 0:
|
||||
$AnimatedSprite.animation = "up"
|
||||
$AnimatedSprite.flip_v = velocity.y > 0
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
if (velocity.x != 0) {
|
||||
animatedSprite.Animation = "right";
|
||||
animatedSprite.FlipH = velocity.x < 0;
|
||||
animatedSprite.FlipV = false;
|
||||
} else if(velocity.y != 0) {
|
||||
animatedSprite.Animation = "up";
|
||||
animatedSprite.FlipV = velocity.y > 0;
|
||||
}
|
||||
|
||||
Play the scene again and check that the animations are correct in each
|
||||
of the directions. When you're sure the movement is working correctly,
|
||||
add this line to ``_ready()`` so the player will be hidden when the game
|
||||
starts:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
hide()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
Hide();
|
||||
|
||||
Preparing for Collisions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -286,10 +370,16 @@ made any enemies yet! That's OK, because we're going to use Godot's
|
||||
|
||||
Add the following at the top of the script, after ``extends Area2d``:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
signal hit
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
[Signal]
|
||||
public delegate void Hit();
|
||||
|
||||
This defines a custom signal called "hit" that we will have our player
|
||||
emit (send out) when it collides with an enemy. We will use ``Area2D`` to
|
||||
detect the collision. Select the ``Player`` node and click the "Node" tab
|
||||
@@ -311,13 +401,27 @@ settings - Godot will automatically create a function called
|
||||
|
||||
Add this code to the function:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _on_Player_body_entered( body ):
|
||||
hide() # Player disappears after being hit
|
||||
emit_signal("hit")
|
||||
$CollisionShape2D.disabled = true
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void OnPlayerBodyEntered(Godot.Object body)
|
||||
{
|
||||
Hide();
|
||||
EmitSignal("Hit");
|
||||
|
||||
// for the sake of this example, but it's better to create a class var
|
||||
// then assign the variable inside _Ready()
|
||||
var collisionShape2D = (CollisionShape2D) GetNode("CollisionShape2D");
|
||||
collisionShape2D.Disabled = true;
|
||||
}
|
||||
|
||||
.. Note:: Disabling the area's collision shape means
|
||||
it won't detect collisions. By turning it off, we make
|
||||
sure we don't trigger the ``hit`` signal more than once.
|
||||
@@ -326,13 +430,25 @@ Add this code to the function:
|
||||
The last piece for our player is to add a function we can call to reset
|
||||
the player when starting a new game.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func start(pos):
|
||||
position = pos
|
||||
show()
|
||||
$CollisionShape2D.disabled = false
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void Start(Vector2 pos)
|
||||
{
|
||||
Position = pos;
|
||||
Show();
|
||||
|
||||
var collisionShape2D = (CollisionShape2D) GetNode("CollisionShape2D");
|
||||
collisionShape2D.Disabled = false;
|
||||
}
|
||||
|
||||
Enemy Scene
|
||||
-----------
|
||||
|
||||
@@ -388,7 +504,8 @@ Enemy Script
|
||||
|
||||
Add a script to the ``Mob`` and add the following member variables:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends RigidBody2D
|
||||
|
||||
@@ -396,6 +513,19 @@ Add a script to the ``Mob`` and add the following member variables:
|
||||
export (int) var MAX_SPEED # maximum speed range
|
||||
var mob_types = ["walk", "swim", "fly"]
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public class Mob : RigidBody2D
|
||||
{
|
||||
[Export]
|
||||
public int MinSpeed = 150;
|
||||
|
||||
[Export]
|
||||
public int MaxSpeed = 250;
|
||||
|
||||
private String[] _mobTypes = {"walk", "swim", "fly"};
|
||||
}
|
||||
|
||||
We'll pick a random value between ``MIN_SPEED`` and ``MAX_SPEED`` for
|
||||
how fast each mob will move (it would be boring if they were all moving
|
||||
at the same speed). Set them to ``150`` and ``250`` in the Inspector. We
|
||||
@@ -405,11 +535,27 @@ we'll use to select a random one.
|
||||
Now let's look at the rest of the script. In ``_ready()`` we randomly
|
||||
choose one of the three animation types:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _ready():
|
||||
$AnimatedSprite.animation = mob_types[randi() % mob_types.size()]
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
var animatedSprite = (AnimatedSprite) GetNode("AnimatedSprite");
|
||||
|
||||
// C# doesn't implement gdscript's random methods, so we use Random
|
||||
// as an alternative.
|
||||
//
|
||||
// Note: Never define random multiple times in real projects. Create a
|
||||
// class memory and reuse it to get true random numbers.
|
||||
var randomMob = new Random();
|
||||
animatedSprite.Animation = _mobTypes[randomMob.Next(0, _mobTypes.Length)];
|
||||
}
|
||||
|
||||
.. note:: You must use ``randomize()`` if you want
|
||||
your sequence of "random" numbers to be different every time you run
|
||||
the scene. We're going to use ``randomize()`` in our ``Main`` scene,
|
||||
@@ -420,11 +566,19 @@ The last piece is to make the mobs delete themselves when they leave the
|
||||
screen. Connect the ``screen_exited()`` signal of the ``Visibility``
|
||||
node and add this code:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _on_Visibility_screen_exited():
|
||||
queue_free()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void onVisibilityScreenExited()
|
||||
{
|
||||
QueueFree();
|
||||
}
|
||||
|
||||
This completes the `Mob` scene.
|
||||
|
||||
Main Scene
|
||||
@@ -492,7 +646,8 @@ Add a script to ``Main``. At the top of the script we use
|
||||
``export (PackedScene)`` to allow us to choose the Mob scene we want to
|
||||
instance.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends Node
|
||||
|
||||
@@ -502,6 +657,30 @@ instance.
|
||||
func _ready():
|
||||
randomize()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public class Main : Node
|
||||
{
|
||||
[Export]
|
||||
public PackedScene Mob;
|
||||
|
||||
public int Score = 0;
|
||||
|
||||
// note: we're going to use this many times, so instantiating it
|
||||
// allows our numbers to consistently be random
|
||||
private Random rand = new Random();
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
}
|
||||
|
||||
// we'll use this later because c# doesn't support gdscript's randi()
|
||||
private float RandRand(float min, float max)
|
||||
{
|
||||
return (float) (rand.NextDouble() * (max - min) + min);
|
||||
}
|
||||
}
|
||||
|
||||
Drag ``Mob.tscn`` from the "FileSystem" panel and drop it in the
|
||||
``Mob`` property under the Script Variables of the ``Main`` node.
|
||||
|
||||
@@ -511,7 +690,8 @@ game ends. Type "game_over" in the "Method In Node" box at the bottom of the
|
||||
"Connecting Signal" window. Add the following code, as well as a ``new_game``
|
||||
function to set everything up for a new game:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func game_over():
|
||||
$ScoreTimer.stop()
|
||||
@@ -522,12 +702,36 @@ function to set everything up for a new game:
|
||||
$Player.start($StartPosition.position)
|
||||
$StartTimer.start()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void GameOver()
|
||||
{
|
||||
//timers
|
||||
var mobTimer = (Timer) GetNode("MobTimer");
|
||||
var scoreTimer = (Timer) GetNode("ScoreTimer");
|
||||
|
||||
scoreTimer.Stop();
|
||||
mobTimer.Stop();
|
||||
}
|
||||
|
||||
public void NewGame()
|
||||
{
|
||||
Score = 0;
|
||||
|
||||
var player = (Player) GetNode("Player");
|
||||
var startTimer = (Timer) GetNode("StartTimer");
|
||||
var startPosition = (Position2D) GetNode("StartPosition");
|
||||
|
||||
player.Start(startPosition.Position);
|
||||
startTimer.Start();
|
||||
}
|
||||
|
||||
Now connect the ``timeout()`` signal of each of the Timer nodes.
|
||||
``StartTimer`` will start the other two timers. ``ScoreTimer`` will
|
||||
increment the score by 1.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _on_StartTimer_timeout():
|
||||
$MobTimer.start()
|
||||
@@ -536,6 +740,23 @@ increment the score by 1.
|
||||
func _on_ScoreTimer_timeout():
|
||||
score += 1
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void OnStartTimerTimeout()
|
||||
{
|
||||
//timers
|
||||
var mobTimer = (Timer) GetNode("MobTimer");
|
||||
var scoreTimer = (Timer) GetNode("ScoreTimer");
|
||||
|
||||
mobTimer.Start();
|
||||
scoreTimer.Start();
|
||||
}
|
||||
|
||||
public void OnScoreTimerTimeout()
|
||||
{
|
||||
Score += 1;
|
||||
}
|
||||
|
||||
In ``_on_MobTimer_timeout()`` we will create a mob instance, pick a
|
||||
random starting location along the ``Path2D``, and set the mob in
|
||||
motion. The ``PathFollow2D`` node will automatically rotate as it
|
||||
@@ -545,7 +766,8 @@ well as its position.
|
||||
Note that a new instance must be added to the scene using
|
||||
``add_child()``.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _on_MobTimer_timeout():
|
||||
# choose a random location on Path2D
|
||||
@@ -563,6 +785,27 @@ Note that a new instance must be added to the scene using
|
||||
# choose the velocity
|
||||
mob.set_linear_velocity(Vector2(rand_range(mob.MIN_SPEED, mob.MAX_SPEED), 0).rotated(direction))
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void OnMobTimerTimeout()
|
||||
{
|
||||
//choose random location on path2d
|
||||
var mobSpawnLocation = (PathFollow2D) GetNode("MobPath/MobSpawnLocation");
|
||||
mobSpawnLocation.SetOffset(rand.Next());
|
||||
|
||||
//set direction
|
||||
var direction = mobSpawnLocation.Rotation + Mathf.PI/2;
|
||||
direction += RandRand(-Mathf.PI/4, Mathf.PI/4);
|
||||
|
||||
//create mob instance and add it to scene
|
||||
var mobInstance = (RigidBody2D) Mob.Instance();
|
||||
mobInstance.Position = mobSpawnLocation.Position;
|
||||
mobInstance.Rotation = direction;
|
||||
mobInstance.SetLinearVelocity(new Vector2(RandRand(150f, 250f), 0).Rotated(direction));
|
||||
|
||||
AddChild(mobInstance);
|
||||
}
|
||||
|
||||
.. important:: In functions requiring angles, GDScript uses *radians*,
|
||||
not degrees. If you're more comfortable working with
|
||||
degrees, you'll need to use the ``deg2rad()`` and
|
||||
@@ -669,27 +912,50 @@ the three ``Control`` nodes:
|
||||
|
||||
Now add this script to ``HUD``:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends CanvasLayer
|
||||
|
||||
signal start_game
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public class HUD : CanvasLayer
|
||||
{
|
||||
[Signal]
|
||||
public delegate void StartGame();
|
||||
}
|
||||
|
||||
The ``start_game`` signal tells the ``Main`` node that the button
|
||||
has been pressed.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func show_message(text):
|
||||
$MessageLabel.text = text
|
||||
$MessageLabel.show()
|
||||
$MessageTimer.start()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void ShowMessage(string text)
|
||||
{
|
||||
var messageTimer = (Timer) GetNode("MessageTimer");
|
||||
var messageLabel = (Label) GetNode("MessageLabel");
|
||||
|
||||
messageLabel.Text = text;
|
||||
messageLabel.Show();
|
||||
messageTimer.Start();
|
||||
}
|
||||
|
||||
This function is called when we want to display a message
|
||||
temporarily, such as "Get Ready". On the ``MessageTimer``, set the
|
||||
``Wait Time`` to ``2`` and set the ``One Shot`` property to "On".
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func show_game_over():
|
||||
show_message("Game Over")
|
||||
@@ -698,21 +964,48 @@ temporarily, such as "Get Ready". On the ``MessageTimer``, set the
|
||||
$MessageLabel.text = "Dodge the\nCreeps!"
|
||||
$MessageLabel.show()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
async public void ShowGameOver()
|
||||
{
|
||||
ShowMessage("Game Over");
|
||||
|
||||
var startButton = (Button) GetNode("StartButton");
|
||||
var messageTimer = (Timer) GetNode("MessageTimer");
|
||||
var messageLabel = (Label) GetNode("MessageLabel");
|
||||
|
||||
//work around for gdscript's yield
|
||||
await Task.Delay((int) messageTimer.WaitTime * 1000);
|
||||
messageLabel.Text = "Dodge the\nCreeps!";
|
||||
messageLabel.Show();
|
||||
startButton.Show();
|
||||
}
|
||||
|
||||
This function is called when the player loses. It will show "Game
|
||||
Over" for 2 seconds, then return to the title screen and show the
|
||||
"Start" button.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func update_score(score):
|
||||
$ScoreLabel.text = str(score)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void UpdateScore(int score)
|
||||
{
|
||||
var scoreLabel = (Label) GetNode("ScoreLabel");
|
||||
scoreLabel.Text = score.ToString();
|
||||
}
|
||||
|
||||
This function is called in ``Main`` whenever the score changes.
|
||||
|
||||
Connect the ``timeout()`` signal of ``MessageTimer`` and the
|
||||
``pressed()`` signal of ``StartButton``.
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _on_StartButton_pressed():
|
||||
$StartButton.hide()
|
||||
@@ -721,6 +1014,22 @@ Connect the ``timeout()`` signal of ``MessageTimer`` and the
|
||||
func _on_MessageTimer_timeout():
|
||||
$MessageLabel.hide()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void OnStartButtonPressed()
|
||||
{
|
||||
var startButton = (Button) GetNode("StartButton");
|
||||
startButton.Hide();
|
||||
|
||||
EmitSignal("StartGame");
|
||||
}
|
||||
|
||||
public void OnMessageTimerTimeout()
|
||||
{
|
||||
var messageLabel = (Label) GetNode("MessageLabel");
|
||||
messageLabel.Hide();
|
||||
}
|
||||
|
||||
Connecting HUD to Main
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -740,24 +1049,43 @@ In the Node tab, connect the HUD's ``start_game`` signal to the
|
||||
In ``new_game()``, update the score display and show the "Get Ready"
|
||||
message:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
$HUD.update_score(score)
|
||||
$HUD.show_message("Get Ready")
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var hud = (HUD) GetNode("HUD");
|
||||
hud.UpdateScore(Score);
|
||||
hud.ShowMessage("Get Ready!");
|
||||
|
||||
In ``game_over()`` we need to call the corresponding ``HUD`` function:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
$HUD.show_game_over()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var hud = (HUD) GetNode("HUD");
|
||||
hud.ShowGameOver();
|
||||
|
||||
Finally, add this to ``_on_ScoreTimer_timeout()`` to keep the display in
|
||||
sync with the changing score:
|
||||
|
||||
::
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
$HUD.update_score(score)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var hud = (HUD) GetNode("HUD");
|
||||
hud.UpdateScore(Score);
|
||||
|
||||
Now you're ready to play! Click the "Play the Project" button. You will
|
||||
be asked to select a main scene, so choose ``Main.tscn``.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user