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
 scene:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     onready var number_label = $Bars/LifeBar/Count/Background/Number
     onready var bar = $Bars/LifeBar/TextureProgress
     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``
    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
 ``bar``'s ``max_value``:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _ready():
         var player_max_health = $"../Characters/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
 goes one node up in the scene tree, and retrieves the
 ``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
 its current ``health`` alongside it. Your code should look like:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _on_Player_health_changed(player_health):
         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
 
    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``.
 It takes a new\_value as its only argument:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func update_health(new_value):
 
+ .. code-tab:: csharp
+
+    public void UpdateHealth(int health)
+    {
+    }
+
 This method needs to:
 
 -  set the ``Number`` node's ``text`` to ``new_value`` converted to a
    string
 -  set the ``TextureProgress``'s ``value`` to ``new_value``
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func update_health(new_value):
         number_label.text = str(new_value)
         bar.value = new_value
 
+ .. code-tab:: csharp
+
+    public void UpdateHealth(int health)
+    {
+        _numberLabel.Text = health.ToString();
+        _bar.Value = health;
+    }
+
 .. tip::
 
     ``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
 ``Tween`` node's ``interpolate_property`` method:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func update_health(new_value):
         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:
 
 ::
@@ -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
 active. Add this code after the last line:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
         if not tween.is_active():
             tween.start()
 
+ .. code-tab:: csharp
+
+        if (!_tween.IsActive())
+        {
+            _tween.Start();
+        }
+
 .. 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`.
@@ -397,24 +475,48 @@ actual ``Bar`` and ``Number`` nodes anymore. Let's fix this.
 
 So far, the update\_health method looks like this:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func update_health(new_value):
         tween.interpolate_property(self, "animated_health", animated_health, new_value, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN)
         if not tween.is_active():
             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
 use the ``_process`` method to animate it. Let's now update the
 ``Number`` and ``TextureProgress`` nodes like before, inside of
 ``_process``:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _process(delta):
         number_label.text = str(animated_health)
         bar.value = animated_health
 
+ .. code-tab:: csharp
+
+    public override void _Process(float delta)
+    {
+        _numberLabel.Text = _animatedHealth.ToString();
+        _bar.Value = _animatedHealth;
+    }
+
 .. note::
 
     `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
 ``bar.value``:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _process(delta):
         var round_value = round(animated_health)
         number_label.text = str(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.
 
 .. 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
 ``Color`` values.
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _on_Player_died():
         var start_color = Color(1.0, 1.0, 1.0, 1.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,
 respectively ``1.0`` and ``0.0`` in ``start_color`` and ``end_color``,
 is the alpha channel.
@@ -519,23 +640,41 @@ is the alpha channel.
 We then have to call the ``interpolate_property`` method of the
 ``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)
 
+ .. 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
 ``start_color`` to the ``end_color``. The duration is of one second,
 with a linear transition. Here again, because the transition is linear,
 the easing does not matter. Here's the complete ``_on_Player_died``
 method:
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
     func _on_Player_died():
         var start_color = Color(1.0, 1.0, 1.0, 1.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)
 
+ .. 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!
 
 .. figure:: img/lifebar_tutorial_final_result.gif