Skip to content

Commit 25d1eaf

Browse files
extsmhilbrunner
authored andcommitted
Added C# examples to the UI Lifebar Tutorial (godotengine#1365)
* Added documentation changes for lifebar tutorial * Added C# examples to zip (as a subfolder) * Added a note regarding pascal case c# examples
1 parent 546c923 commit 25d1eaf

File tree

2 files changed

+152
-13
lines changed

2 files changed

+152
-13
lines changed
Binary file not shown.

getting_started/step_by_step/ui_code_a_life_bar.rst

Lines changed: 152 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,30 @@ The GUI scene encapsulates all of the Game User Interface. It comes with
7878
a barebones script where we get the path to nodes that exist inside the
7979
scene:
8080

81-
::
81+
.. tabs::
82+
.. code-tab:: gdscript GDScript
8283

8384
onready var number_label = $Bars/LifeBar/Count/Background/Number
8485
onready var bar = $Bars/LifeBar/TextureProgress
8586
onready var tween = $Tween
8687

88+
.. code-tab:: csharp
89+
90+
public class Gui : MarginContainer
91+
{
92+
private Tween _tween;
93+
private Label _numberLabel;
94+
private TextureProgress _bar;
95+
96+
public override void _Ready()
97+
{
98+
// C# doesn't have an onready feature, this works just the same
99+
_bar = (TextureProgress) GetNode("Bars/LifeBar/TextureProgress");
100+
_tween = (Tween) GetNode("Tween");
101+
_numberLabel = (Label) GetNode("Bars/LifeBar/Count/Background/Number");
102+
}
103+
}
104+
87105
- ``number_label`` displays a life count as a number. It's a ``Label``
88106
node
89107
- ``bar`` is the life bar itself. It's a ``TextureProgress`` node
@@ -127,12 +145,22 @@ open its script. In the ``_ready`` function, we're going to store the
127145
``Player``'s ``max_health`` in a new variable and use it to set the
128146
``bar``'s ``max_value``:
129147

130-
::
148+
.. tabs::
149+
.. code-tab:: gdscript GDScript
131150

132151
func _ready():
133152
var player_max_health = $"../Characters/Player".max_health
134153
bar.max_value = player_max_health
135154

155+
.. code-tab:: csharp
156+
157+
public override void _Ready()
158+
{
159+
// add this below _bar, _tween, and _numberLabel
160+
var player = (Player) GetNode("../Characters/Player");
161+
_bar.MaxValue = player.MaxHealth;
162+
}
163+
136164
Let's break it down. ``$"../Characters/Player"`` is a shorthand that
137165
goes one node up in the scene tree, and retrieves the
138166
``Characters/Player`` node from there. It gives us access to the node.
@@ -247,11 +275,25 @@ Inside the parens after the function name, add a ``player_health``
247275
argument. When the player emits the ``health_changed`` signal it will send
248276
its current ``health`` alongside it. Your code should look like:
249277

250-
::
278+
.. tabs::
279+
.. code-tab:: gdscript GDScript
251280

252281
func _on_Player_health_changed(player_health):
253282
pass
254283

284+
.. code-tab:: csharp
285+
286+
public void OnPlayerHealthChanged(int playerHealth)
287+
{
288+
}
289+
290+
.. note::
291+
292+
The engine does not convert PascalCase to snake_case, for C# examples we'll be using
293+
PascalCase for method names & camelCase for method parameters which follows the official `C#
294+
naming conventions. <https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions>`_
295+
296+
255297
.. figure:: img/lifebar_tutorial_player_gd_emits_health_changed_code.png
256298

257299
In Player.gd, when the Player emits the health\_changed signal, it also
@@ -270,22 +312,38 @@ Inside ``_on_Player_health_changed`` let's call a second function called
270312
Create a new ``update_health`` method below ``_on_Player_health_changed``.
271313
It takes a new\_value as its only argument:
272314

273-
::
315+
.. tabs::
316+
.. code-tab:: gdscript GDScript
274317

275318
func update_health(new_value):
276319

320+
.. code-tab:: csharp
321+
322+
public void UpdateHealth(int health)
323+
{
324+
}
325+
277326
This method needs to:
278327

279328
- set the ``Number`` node's ``text`` to ``new_value`` converted to a
280329
string
281330
- set the ``TextureProgress``'s ``value`` to ``new_value``
282331

283-
::
332+
.. tabs::
333+
.. code-tab:: gdscript GDScript
284334

285335
func update_health(new_value):
286336
number_label.text = str(new_value)
287337
bar.value = new_value
288338

339+
.. code-tab:: csharp
340+
341+
public void UpdateHealth(int health)
342+
{
343+
_numberLabel.Text = health.ToString();
344+
_bar.Value = health;
345+
}
346+
289347
.. tip::
290348

291349
``str`` is a built-in function that converts about any value to
@@ -342,11 +400,23 @@ At the top of the script, define a new variable, name it
342400
clear its content. Let's animate the ``animated_health`` value. Call the
343401
``Tween`` node's ``interpolate_property`` method:
344402

345-
::
403+
.. tabs::
404+
.. code-tab:: gdscript GDScript
346405

347406
func update_health(new_value):
348407
tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
349408

409+
.. code-tab:: csharp
410+
411+
// add this to the top of your class
412+
private int _animatedHealth = 0;
413+
414+
public void UpdateHealth(int health)
415+
{
416+
_tween.InterpolateProperty(this, "_animatedHealth", _animatedHealth, health, 0.6f, Tween.TransitionType.Linear,
417+
Tween.EaseType.In);
418+
}
419+
350420
Let's break down the call:
351421

352422
::
@@ -380,11 +450,19 @@ The animation will not play until we activated the ``Tween`` node with
380450
``tween.start()``. We only have to do this once if the node is not
381451
active. Add this code after the last line:
382452

383-
::
453+
.. tabs::
454+
.. code-tab:: gdscript GDScript
384455

385456
if not tween.is_active():
386457
tween.start()
387458

459+
.. code-tab:: csharp
460+
461+
if (!_tween.IsActive())
462+
{
463+
_tween.Start();
464+
}
465+
388466
.. note::
389467

390468
Although we could animate the `health` property on the `Player`, we really shouldn't. Characters should lose life instantly when they get hit. It makes it a lot easier to manage their state, like to know when one died. You always want to store animations in a separate data container or node. The `tween` node is perfect for code-controlled animations. For hand-made animations, check out `AnimationPlayer`.
@@ -397,24 +475,48 @@ actual ``Bar`` and ``Number`` nodes anymore. Let's fix this.
397475

398476
So far, the update\_health method looks like this:
399477

400-
::
478+
.. tabs::
479+
.. code-tab:: gdscript GDScript
401480

402481
func update_health(new_value):
403482
tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
404483
if not tween.is_active():
405484
tween.start()
406485

486+
.. code-tab:: csharp
487+
488+
public void UpdateHealth(int health)
489+
{
490+
_tween.InterpolateProperty(this, "_animatedHealth", _animatedHealth, health, 0.6f, Tween.TransitionType.Linear,
491+
Tween.EaseType.In);
492+
493+
if(!_tween.IsActive())
494+
{
495+
_tween.Start();
496+
}
497+
}
498+
499+
407500
In this specific case, because ``number_label`` takes text, we need to
408501
use the ``_process`` method to animate it. Let's now update the
409502
``Number`` and ``TextureProgress`` nodes like before, inside of
410503
``_process``:
411504

412-
::
505+
.. tabs::
506+
.. code-tab:: gdscript GDScript
413507

414508
func _process(delta):
415509
number_label.text = str(animated_health)
416510
bar.value = animated_health
417511

512+
.. code-tab:: csharp
513+
514+
public override void _Process(float delta)
515+
{
516+
_numberLabel.Text = _animatedHealth.ToString();
517+
_bar.Value = _animatedHealth;
518+
}
519+
418520
.. note::
419521

420522
`number_label` and `bar` are variables that store references to the `Number` and `TextureProgress` nodes.
@@ -432,13 +534,23 @@ local variable named ``round_value`` to store the rounded
432534
``animated_health``. Then assign it to ``number_label.text`` and
433535
``bar.value``:
434536

435-
::
537+
.. tabs::
538+
.. code-tab:: gdscript GDScript
436539

437540
func _process(delta):
438541
var round_value = round(animated_health)
439542
number_label.text = str(round_value)
440543
bar.value = round_value
441544

545+
.. code-tab:: csharp
546+
547+
public override void _Process(float delta)
548+
{
549+
var roundValue = Mathf.Round(_animatedHealth);
550+
_numberLabel.Text = roundValue.ToString();
551+
_bar.Value = roundValue;
552+
}
553+
442554
Try the game again to see a nice blocky animation.
443555

444556
.. figure:: img/lifebar_tutorial_number_animation_working.gif
@@ -506,36 +618,63 @@ the top of the ``_on_Player_died`` method and name them ``start_color``
506618
and ``end_color``. Use the ``Color()`` constructor to build two
507619
``Color`` values.
508620

509-
::
621+
.. tabs::
622+
.. code-tab:: gdscript GDScript
510623

511624
func _on_Player_died():
512625
var start_color = Color(1.0, 1.0, 1.0, 1.0)
513626
var end_color = Color(1.0, 1.0, 1.0, 0.0)
514627

628+
.. code-tab:: csharp
629+
630+
public void OnPlayerDied()
631+
{
632+
var startColor = new Color(1.0f, 1.0f, 1.0f);
633+
var endColor = new Color(1.0f, 1.0f, 1.0f, 0.0f);
634+
}
635+
515636
``Color(1.0, 1.0, 1.0)`` corresponds to white. The fourth argument,
516637
respectively ``1.0`` and ``0.0`` in ``start_color`` and ``end_color``,
517638
is the alpha channel.
518639

519640
We then have to call the ``interpolate_property`` method of the
520641
``Tween`` node again:
521642

522-
::
643+
.. tabs::
644+
.. code-tab:: gdscript GDScript
523645

524646
tween.interpolate_property(self, "modulate", start_color, end_color, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN)
525647

648+
.. code-tab:: csharp
649+
650+
_tween.InterpolateProperty(this, "modulate", startColor, endColor, 1.0f, Tween.TransitionType.Linear,
651+
Tween.EaseType.In);
652+
526653
This time we change the ``modulate`` property and have it animate from
527654
``start_color`` to the ``end_color``. The duration is of one second,
528655
with a linear transition. Here again, because the transition is linear,
529656
the easing does not matter. Here's the complete ``_on_Player_died``
530657
method:
531658

532-
::
659+
.. tabs::
660+
.. code-tab:: gdscript GDScript
533661

534662
func _on_Player_died():
535663
var start_color = Color(1.0, 1.0, 1.0, 1.0)
536664
var end_color = Color(1.0, 1.0, 1.0, 0.0)
537665
tween.interpolate_property(self, "modulate", start_color, end_color, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN)
538666

667+
.. code-tab:: csharp
668+
669+
public void OnPlayerDied()
670+
{
671+
var startColor = new Color(1.0f, 1.0f, 1.0f);
672+
var endColor = new Color(1.0f, 1.0f, 1.0f, 0.0f);
673+
674+
_tween.InterpolateProperty(this, "modulate", startColor, endColor, 1.0f, Tween.TransitionType.Linear,
675+
Tween.EaseType.In);
676+
}
677+
539678
And that is it. You may now play the game to see the final result!
540679

541680
.. figure:: img/lifebar_tutorial_final_result.gif

0 commit comments

Comments
 (0)