Browse Source

Added C# examples to the UI Lifebar Tutorial (#1365)

* Added documentation changes for lifebar tutorial

* Added C# examples to zip (as a subfolder)

* Added a note regarding pascal case c# examples
Lamonte 7 years ago
parent
commit
25d1eaff79

BIN
getting_started/step_by_step/files/ui_code_life_bar.zip


+ 152 - 13
getting_started/step_by_step/ui_code_a_life_bar.rst

@@ -78,12 +78,30 @@ The GUI scene encapsulates all of the Game User Interface. It comes with
 a barebones script where we get the path to nodes that exist inside the
 a barebones script where we get the path to nodes that exist inside the
 scene:
 scene:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     onready var number_label = $Bars/LifeBar/Count/Background/Number
     onready var number_label = $Bars/LifeBar/Count/Background/Number
     onready var bar = $Bars/LifeBar/TextureProgress
     onready var bar = $Bars/LifeBar/TextureProgress
     onready var tween = $Tween
     onready var tween = $Tween
 
 
+ .. code-tab:: csharp
+
+    public class Gui : MarginContainer
+    {
+        private Tween _tween;
+        private Label _numberLabel;
+        private TextureProgress _bar;
+
+        public override void _Ready()
+        {
+            // C# doesn't have an onready feature, this works just the same
+            _bar = (TextureProgress) GetNode("Bars/LifeBar/TextureProgress");
+            _tween = (Tween) GetNode("Tween");
+            _numberLabel = (Label) GetNode("Bars/LifeBar/Count/Background/Number");
+        }
+    }
+
 -  ``number_label`` displays a life count as a number. It's a ``Label``
 -  ``number_label`` displays a life count as a number. It's a ``Label``
    node
    node
 -  ``bar`` is the life bar itself. It's a ``TextureProgress`` node
 -  ``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
 ``Player``'s ``max_health`` in a new variable and use it to set the
 ``Player``'s ``max_health`` in a new variable and use it to set the
 ``bar``'s ``max_value``:
 ``bar``'s ``max_value``:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func _ready():
     func _ready():
         var player_max_health = $"../Characters/Player".max_health
         var player_max_health = $"../Characters/Player".max_health
         bar.max_value = player_max_health
         bar.max_value = player_max_health
 
 
+ .. code-tab:: csharp
+
+    public override void _Ready()
+    {
+        // add this below _bar, _tween, and _numberLabel
+        var player = (Player) GetNode("../Characters/Player");
+        _bar.MaxValue = player.MaxHealth;
+    }
+
 Let's break it down. ``$"../Characters/Player"`` is a shorthand that
 Let's break it down. ``$"../Characters/Player"`` is a shorthand that
 goes one node up in the scene tree, and retrieves the
 goes one node up in the scene tree, and retrieves the
 ``Characters/Player`` node from there. It gives us access to the node.
 ``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``
 argument. When the player emits the ``health_changed`` signal it will send
 argument. When the player emits the ``health_changed`` signal it will send
 its current ``health`` alongside it. Your code should look like:
 its current ``health`` alongside it. Your code should look like:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func _on_Player_health_changed(player_health):
     func _on_Player_health_changed(player_health):
         pass
         pass
 
 
+ .. code-tab:: csharp
+
+    public void OnPlayerHealthChanged(int playerHealth)
+    {
+    }
+
+.. note::
+    
+    The engine does not convert PascalCase to snake_case, for C# examples we'll be using
+    PascalCase for method names & camelCase for method parameters which follows the official `C#
+    naming conventions. <https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions>`_ 
+
+
 .. figure:: img/lifebar_tutorial_player_gd_emits_health_changed_code.png
 .. figure:: img/lifebar_tutorial_player_gd_emits_health_changed_code.png
 
 
    In Player.gd, when the Player emits the health\_changed signal, it also
    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
 Create a new ``update_health`` method below ``_on_Player_health_changed``.
 Create a new ``update_health`` method below ``_on_Player_health_changed``.
 It takes a new\_value as its only argument:
 It takes a new\_value as its only argument:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func update_health(new_value):
     func update_health(new_value):
 
 
+ .. code-tab:: csharp
+
+    public void UpdateHealth(int health)
+    {
+    }
+
 This method needs to:
 This method needs to:
 
 
 -  set the ``Number`` node's ``text`` to ``new_value`` converted to a
 -  set the ``Number`` node's ``text`` to ``new_value`` converted to a
    string
    string
 -  set the ``TextureProgress``'s ``value`` to ``new_value``
 -  set the ``TextureProgress``'s ``value`` to ``new_value``
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func update_health(new_value):
     func update_health(new_value):
         number_label.text = str(new_value)
         number_label.text = str(new_value)
         bar.value = new_value
         bar.value = new_value
 
 
+ .. code-tab:: csharp
+
+    public void UpdateHealth(int health)
+    {
+        _numberLabel.Text = health.ToString();
+        _bar.Value = health;
+    }
+
 .. tip::
 .. tip::
 
 
     ``str`` is a built-in function that converts about any value to
     ``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
 clear its content. Let's animate the ``animated_health`` value. Call the
 clear its content. Let's animate the ``animated_health`` value. Call the
 ``Tween`` node's ``interpolate_property`` method:
 ``Tween`` node's ``interpolate_property`` method:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func update_health(new_value):
     func update_health(new_value):
         tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
         tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
 
 
+ .. code-tab:: csharp
+
+    // add this to the top of your class
+    private int _animatedHealth = 0;
+
+    public void UpdateHealth(int health)
+    {
+        _tween.InterpolateProperty(this, "_animatedHealth", _animatedHealth, health, 0.6f, Tween.TransitionType.Linear,
+            Tween.EaseType.In);
+    }
+
 Let's break down the call:
 Let's break down the call:
 
 
 ::
 ::
@@ -380,11 +450,19 @@ The animation will not play until we activated the ``Tween`` node with
 ``tween.start()``. We only have to do this once if the node is not
 ``tween.start()``. We only have to do this once if the node is not
 active. Add this code after the last line:
 active. Add this code after the last line:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
         if not tween.is_active():
         if not tween.is_active():
             tween.start()
             tween.start()
 
 
+ .. code-tab:: csharp
+
+        if (!_tween.IsActive())
+        {
+            _tween.Start();
+        }
+
 .. note::
 .. note::
 
 
     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`.
     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.
 
 
 So far, the update\_health method looks like this:
 So far, the update\_health method looks like this:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func update_health(new_value):
     func update_health(new_value):
         tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
         tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
         if not tween.is_active():
         if not tween.is_active():
             tween.start()
             tween.start()
 
 
+ .. code-tab:: csharp
+
+    public void UpdateHealth(int health)
+    {
+        _tween.InterpolateProperty(this, "_animatedHealth", _animatedHealth, health, 0.6f, Tween.TransitionType.Linear,
+            Tween.EaseType.In);
+
+        if(!_tween.IsActive())
+        {
+            _tween.Start();
+        }
+    }
+
+
 In this specific case, because ``number_label`` takes text, we need to
 In this specific case, because ``number_label`` takes text, we need to
 use the ``_process`` method to animate it. Let's now update the
 use the ``_process`` method to animate it. Let's now update the
 ``Number`` and ``TextureProgress`` nodes like before, inside of
 ``Number`` and ``TextureProgress`` nodes like before, inside of
 ``_process``:
 ``_process``:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func _process(delta):
     func _process(delta):
         number_label.text = str(animated_health)
         number_label.text = str(animated_health)
         bar.value = animated_health
         bar.value = animated_health
 
 
+ .. code-tab:: csharp
+
+    public override void _Process(float delta)
+    {
+        _numberLabel.Text = _animatedHealth.ToString();
+        _bar.Value = _animatedHealth;
+    }
+
 .. note::
 .. note::
 
 
     `number_label` and `bar` are variables that store references to the `Number` and `TextureProgress` nodes.
     `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
 ``animated_health``. Then assign it to ``number_label.text`` and
 ``animated_health``. Then assign it to ``number_label.text`` and
 ``bar.value``:
 ``bar.value``:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func _process(delta):
     func _process(delta):
         var round_value = round(animated_health)
         var round_value = round(animated_health)
         number_label.text = str(round_value)
         number_label.text = str(round_value)
         bar.value = round_value
         bar.value = round_value
 
 
+ .. code-tab:: csharp
+
+    public override void _Process(float delta)
+    {
+        var roundValue = Mathf.Round(_animatedHealth);
+        _numberLabel.Text = roundValue.ToString();
+        _bar.Value = roundValue;
+    }
+
 Try the game again to see a nice blocky animation.
 Try the game again to see a nice blocky animation.
 
 
 .. figure:: img/lifebar_tutorial_number_animation_working.gif
 .. figure:: img/lifebar_tutorial_number_animation_working.gif
@@ -506,12 +618,21 @@ the top of the ``_on_Player_died`` method and name them ``start_color``
 and ``end_color``. Use the ``Color()`` constructor to build two
 and ``end_color``. Use the ``Color()`` constructor to build two
 ``Color`` values.
 ``Color`` values.
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func _on_Player_died():
     func _on_Player_died():
         var start_color = Color(1.0, 1.0, 1.0, 1.0)
         var start_color = Color(1.0, 1.0, 1.0, 1.0)
         var end_color = Color(1.0, 1.0, 1.0, 0.0)
         var end_color = Color(1.0, 1.0, 1.0, 0.0)
 
 
+ .. code-tab:: csharp
+
+    public void OnPlayerDied()
+    {
+        var startColor = new Color(1.0f, 1.0f, 1.0f);
+        var endColor = new Color(1.0f, 1.0f, 1.0f, 0.0f);
+    }
+
 ``Color(1.0, 1.0, 1.0)`` corresponds to white. The fourth argument,
 ``Color(1.0, 1.0, 1.0)`` corresponds to white. The fourth argument,
 respectively ``1.0`` and ``0.0`` in ``start_color`` and ``end_color``,
 respectively ``1.0`` and ``0.0`` in ``start_color`` and ``end_color``,
 is the alpha channel.
 is the alpha channel.
@@ -519,23 +640,41 @@ is the alpha channel.
 We then have to call the ``interpolate_property`` method of the
 We then have to call the ``interpolate_property`` method of the
 ``Tween`` node again:
 ``Tween`` node again:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     tween.interpolate_property(self, "modulate", start_color, end_color, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN)
     tween.interpolate_property(self, "modulate", start_color, end_color, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN)
 
 
+ .. code-tab:: csharp
+
+    _tween.InterpolateProperty(this, "modulate", startColor, endColor, 1.0f, Tween.TransitionType.Linear,
+      Tween.EaseType.In);
+
 This time we change the ``modulate`` property and have it animate from
 This time we change the ``modulate`` property and have it animate from
 ``start_color`` to the ``end_color``. The duration is of one second,
 ``start_color`` to the ``end_color``. The duration is of one second,
 with a linear transition. Here again, because the transition is linear,
 with a linear transition. Here again, because the transition is linear,
 the easing does not matter. Here's the complete ``_on_Player_died``
 the easing does not matter. Here's the complete ``_on_Player_died``
 method:
 method:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     func _on_Player_died():
     func _on_Player_died():
         var start_color = Color(1.0, 1.0, 1.0, 1.0)
         var start_color = Color(1.0, 1.0, 1.0, 1.0)
         var end_color = Color(1.0, 1.0, 1.0, 0.0)
         var end_color = Color(1.0, 1.0, 1.0, 0.0)
         tween.interpolate_property(self, "modulate", start_color, end_color, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN)
         tween.interpolate_property(self, "modulate", start_color, end_color, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN)
 
 
+ .. code-tab:: csharp
+
+    public void OnPlayerDied()
+    {
+        var startColor = new Color(1.0f, 1.0f, 1.0f);
+        var endColor = new Color(1.0f, 1.0f, 1.0f, 0.0f);
+        
+        _tween.InterpolateProperty(this, "modulate", startColor, endColor, 1.0f, Tween.TransitionType.Linear,
+            Tween.EaseType.In);
+    }
+
 And that is it. You may now play the game to see the final result!
 And that is it. You may now play the game to see the final result!
 
 
 .. figure:: img/lifebar_tutorial_final_result.gif
 .. figure:: img/lifebar_tutorial_final_result.gif