Browse Source

Added C# code to Part 1 of the FPS tutorial (#2385)

* Added C# code to Part 1 of the FPS tutorial

* Update code for FPS Tutorial Part 1

Added _ to private properties. Also removed code in the first code sample that is only added later in the tutorial.
Louis-Jacques Bourdages 6 years ago
parent
commit
e4c5a12916
1 changed files with 214 additions and 8 deletions
  1. 214 8
      tutorials/3d/fps_tutorial/part_one.rst

+ 214 - 8
tutorials/3d/fps_tutorial/part_one.rst

@@ -138,7 +138,8 @@ Attach a new script to the ``Player`` node and call it ``Player.gd``.
 Let's program our player by adding the ability to move around, look around with the mouse, and jump.
 Let's program our player by adding the ability to move around, look around with the mouse, and jump.
 Add the following code to ``Player.gd``:
 Add the following code to ``Player.gd``:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     extends KinematicBody
     extends KinematicBody
 
 
@@ -240,6 +241,135 @@ Add the following code to ``Player.gd``:
             camera_rot.x = clamp(camera_rot.x, -70, 70)
             camera_rot.x = clamp(camera_rot.x, -70, 70)
             rotation_helper.rotation_degrees = camera_rot
             rotation_helper.rotation_degrees = camera_rot
 
 
+ .. code-tab:: csharp
+
+    using Godot;
+    using System;
+
+    public class Player : KinematicBody
+    {
+        [Export]
+        public float Gravity = -24.8f;
+        [Export]
+        public float MaxSpeed = 20.0f;
+        [Export]
+        public float JumpSpeed = 18.0f;
+        [Export]
+        public float Accel = 4.5f;
+        [Export]
+        public float Deaccel = 16.0f;
+        [Export]
+        public float MaxSlopeAngle = 40.0f;
+        [Export]
+        public float MouseSensitivity = 0.05f;
+
+        private Vector3 _vel = new Vector3();
+        private Vector3 _dir = new Vector3();
+
+        private Camera _camera;
+        private Spatial _rotationHelper;
+
+        // Called when the node enters the scene tree for the first time.
+        public override void _Ready()
+        {
+            _camera = GetNode<Camera>("Rotation_Helper/Camera");
+            _rotationHelper = GetNode<Spatial>("Rotation_Helper");
+
+            Input.SetMouseMode(Input.MouseMode.Captured);
+        }
+
+        public override void _PhysicsProcess(float delta)
+        {
+            ProcessInput(delta);
+            ProcessMovement(delta);
+        }
+
+        private void ProcessInput(float delta)
+        {
+            //  -------------------------------------------------------------------
+            //  Walking
+            _dir = new Vector3();
+            Transform camXform = _camera.GetGlobalTransform();
+
+            Vector2 inputMovementVector = new Vector2();
+
+            if (Input.IsActionPressed("movement_forward"))
+                inputMovementVector.y += 1;
+            if (Input.IsActionPressed("movement_backward"))
+                inputMovementVector.y -= 1;
+            if (Input.IsActionPressed("movement_left"))
+                inputMovementVector.x -= 1;
+            if (Input.IsActionPressed("movement_right"))
+                inputMovementVector.x += 1;
+
+            inputMovementVector = inputMovementVector.Normalized();
+
+            _dir += -camXform.basis.z.Normalized() * inputMovementVector.y;
+            _dir += camXform.basis.x.Normalized() * inputMovementVector.x;
+            //  -------------------------------------------------------------------
+
+            //  -------------------------------------------------------------------
+            //  Jumping
+            if (IsOnFloor())
+            {
+                if (Input.IsActionJustPressed("movement_jump"))
+                    _vel.y = JumpSpeed;
+            }
+            //  -------------------------------------------------------------------
+
+            //  -------------------------------------------------------------------
+            //  Capturing/Freeing the cursor
+            if (Input.IsActionJustPressed("ui_cancel"))
+            {
+                if (Input.GetMouseMode() == Input.MouseMode.Visible)
+                    Input.SetMouseMode(Input.MouseMode.Captured);
+                else
+                    Input.SetMouseMode(Input.MouseMode.Visible);
+            }
+            //  -------------------------------------------------------------------
+        }
+
+        private void ProcessMovement(float delta)
+        {
+            _dir.y = 0;
+            _dir = _dir.Normalized();
+
+            _vel.y += delta * Gravity;
+
+            Vector3 hvel = _vel;
+            hvel.y = 0;
+
+            Vector3 target = _dir;
+
+            target *= MaxSpeed;
+
+            float accel;
+            if (_dir.Dot(hvel) > 0)
+                accel = Accel;
+            else
+                accel = Deaccel;
+
+            hvel = hvel.LinearInterpolate(target, accel * delta);
+            _vel.x = hvel.x;
+            _vel.z = hvel.z;
+            _vel = MoveAndSlide(_vel, new Vector3(0, 1, 0), false, 4, Mathf.Deg2Rad(MaxSlopeAngle));
+        }
+
+        public override void _Input(InputEvent @event)
+        {
+            if (@event is InputEventMouseMotion && Input.GetMouseMode() == Input.MouseMode.Captured)
+            {
+                InputEventMouseMotion mouseEvent = @event as InputEventMouseMotion;
+                _rotationHelper.RotateX(Mathf.Deg2Rad(mouseEvent.Relative.y * MouseSensitivity));
+                RotateY(Mathf.Deg2Rad(-mouseEvent.Relative.x * MouseSensitivity));
+
+                Vector3 cameraRot = _rotationHelper.RotationDegrees;
+                cameraRot.x = Mathf.Clamp(cameraRot.x, -70, 70);
+                _rotationHelper.RotationDegrees = cameraRot;
+            }
+        }
+    }
+
 This is a lot of code, so let's break it down function by function:
 This is a lot of code, so let's break it down function by function:
 
 
 .. tip:: While copy and pasting code is ill advised, as you can learn a lot from manually typing the code in, you can
 .. tip:: While copy and pasting code is ill advised, as you can learn a lot from manually typing the code in, you can
@@ -339,7 +469,8 @@ In Godot, the origin is at position ``(0, 0, 0)`` with a rotation of ``(0, 0, 0)
 
 
 If you want to move using the world space directional vectors, you'd do something like this:
 If you want to move using the world space directional vectors, you'd do something like this:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     if Input.is_action_pressed("movement_forward"):
     if Input.is_action_pressed("movement_forward"):
         node.translate(Vector3(0, 0, 1))
         node.translate(Vector3(0, 0, 1))
@@ -349,6 +480,17 @@ If you want to move using the world space directional vectors, you'd do somethin
         node.translate(Vector3(1, 0, 0))
         node.translate(Vector3(1, 0, 0))
     if Input.is_action_pressed("movement_right"):
     if Input.is_action_pressed("movement_right"):
         node.translate(Vector3(-1, 0, 0))
         node.translate(Vector3(-1, 0, 0))
+        
+ .. code-tab:: csharp
+ 
+    if (Input.IsActionPressed("movement_forward"))
+        node.Translate(new Vector3(0, 0, 1));
+    if (Input.IsActionPressed("movement_backward"))
+        node.Translate(new Vector3(0, 0, -1));
+    if (Input.IsActionPressed("movement_left"))
+        node.Translate(new Vector3(1, 0, 0));
+    if (Input.IsActionPressed("movement_right"))
+        node.Translate(new Vector3(-1, 0, 0));
 
 
 .. note:: Notice how we do not need to do any calculations to get world space directional vectors.
 .. note:: Notice how we do not need to do any calculations to get world space directional vectors.
           We can define a few :ref:`Vector3 <class_Vector3>` variables and input the values pointing in each direction.
           We can define a few :ref:`Vector3 <class_Vector3>` variables and input the values pointing in each direction.
@@ -387,7 +529,8 @@ Each of those vectors point towards each of the local space vectors coming from
 
 
 To use the :ref:`Spatial <class_Spatial>` node's local directional vectors, we use this code:
 To use the :ref:`Spatial <class_Spatial>` node's local directional vectors, we use this code:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     if Input.is_action_pressed("movement_forward"):
     if Input.is_action_pressed("movement_forward"):
         node.translate(node.global_transform.basis.z.normalized())
         node.translate(node.global_transform.basis.z.normalized())
@@ -397,6 +540,17 @@ To use the :ref:`Spatial <class_Spatial>` node's local directional vectors, we u
         node.translate(node.global_transform.basis.x.normalized())
         node.translate(node.global_transform.basis.x.normalized())
     if Input.is_action_pressed("movement_right"):
     if Input.is_action_pressed("movement_right"):
         node.translate(-node.global_transform.basis.x.normalized())
         node.translate(-node.global_transform.basis.x.normalized())
+        
+ .. code-tab:: csharp
+        
+    if (Input.IsActionPressed("movement_forward"))
+        node.Translate(node.GlobalTransform.basis.z.Normalized());
+    if (Input.IsActionPressed("movement_backward"))
+        node.Translate(-node.GlobalTransform.basis.z.Normalized());
+    if (Input.IsActionPressed("movement_left"))
+        node.Translate(node.GlobalTransform.basis.x.Normalized());
+    if (Input.IsActionPressed("movement_right"))
+        node.Translate(-node.GlobalTransform.basis.x.Normalized());
 
 
 Here is what local space looks like in 2D:
 Here is what local space looks like in 2D:
 
 
@@ -539,7 +693,8 @@ so let's do that!
 
 
 First we need a few more class variables in our player script:
 First we need a few more class variables in our player script:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     const MAX_SPRINT_SPEED = 30
     const MAX_SPRINT_SPEED = 30
     const SPRINT_ACCEL = 18
     const SPRINT_ACCEL = 18
@@ -547,6 +702,16 @@ First we need a few more class variables in our player script:
 
 
     var flashlight
     var flashlight
 
 
+ .. code-tab:: csharp
+
+    [Export]
+    public float MaxSprintSpeed = 30.0f;
+    [Export]
+    public float SprintAccel = 18.0f;
+    private bool _isSprinting = false;
+    
+    private SpotLight _flashlight;
+
 All the sprinting variables work exactly the same as the non sprinting variables with
 All the sprinting variables work exactly the same as the non sprinting variables with
 similar names.
 similar names.
 
 
@@ -555,17 +720,23 @@ we will be using to hold the player's flash light node.
 
 
 Now we need to add a few lines of code, starting in ``_ready``. Add the following to ``_ready``:
 Now we need to add a few lines of code, starting in ``_ready``. Add the following to ``_ready``:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     flashlight = $Rotation_Helper/Flashlight
     flashlight = $Rotation_Helper/Flashlight
 
 
+ .. code-tab:: csharp
+ 
+    _flashlight = GetNode<SpotLight>("Rotation_Helper/Flashlight");
+
 This gets the ``Flashlight`` node and assigns it to the ``flashlight`` variable.
 This gets the ``Flashlight`` node and assigns it to the ``flashlight`` variable.
 
 
 _________
 _________
 
 
 Now we need to change some of the code in ``process_input``. Add the following somewhere in ``process_input``:
 Now we need to change some of the code in ``process_input``. Add the following somewhere in ``process_input``:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     # ----------------------------------
     # ----------------------------------
     # Sprinting
     # Sprinting
@@ -584,6 +755,26 @@ Now we need to change some of the code in ``process_input``. Add the following s
             flashlight.show()
             flashlight.show()
     # ----------------------------------
     # ----------------------------------
 
 
+ .. code-tab:: csharp
+ 
+    //  -------------------------------------------------------------------
+    //  Sprinting
+    if (Input.IsActionPressed("movement_sprint"))
+        _isSprinting = true;
+    else
+        _isSprinting = false;
+    //  -------------------------------------------------------------------
+
+    //  -------------------------------------------------------------------
+    //  Turning the flashlight on/off
+    if (Input.IsActionJustPressed("flashlight"))
+    {
+        if (_flashlight.IsVisibleInTree())
+            _flashlight.Hide();
+        else
+            _flashlight.Show();
+    }
+
 Let's go over the additions:
 Let's go over the additions:
 
 
 We set ``is_sprinting`` to true when the player is holding down the ``movement_sprint`` action, and false
 We set ``is_sprinting`` to true when the player is holding down the ``movement_sprint`` action, and false
@@ -597,25 +788,40 @@ _________
 
 
 Now we need to change a couple things in ``process_movement``. First, replace ``target *= MAX_SPEED`` with the following:
 Now we need to change a couple things in ``process_movement``. First, replace ``target *= MAX_SPEED`` with the following:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     if is_sprinting:
     if is_sprinting:
         target *= MAX_SPRINT_SPEED
         target *= MAX_SPRINT_SPEED
     else:
     else:
         target *= MAX_SPEED
         target *= MAX_SPEED
 
 
+ .. code-tab:: csharp
+ 
+    if (_isSprinting)
+        target *= MaxSprintSpeed;    
+    else
+        target *= MaxSpeed;
+            
 Now instead of always multiplying ``target`` by ``MAX_SPEED``, we first check to see if the player is sprinting or not.
 Now instead of always multiplying ``target`` by ``MAX_SPEED``, we first check to see if the player is sprinting or not.
 If the player is sprinting, we instead multiply ``target`` by ``MAX_SPRINT_SPEED``.
 If the player is sprinting, we instead multiply ``target`` by ``MAX_SPRINT_SPEED``.
 
 
 Now all that's left is to change the acceleration when sprinting. Change ``accel = ACCEL`` to the following:
 Now all that's left is to change the acceleration when sprinting. Change ``accel = ACCEL`` to the following:
 
 
-::
+.. tabs::
+ .. code-tab:: gdscript GDScript
 
 
     if is_sprinting:
     if is_sprinting:
         accel = SPRINT_ACCEL
         accel = SPRINT_ACCEL
     else:
     else:
         accel = ACCEL
         accel = ACCEL
 
 
+ .. code-tab:: csharp
+ 
+    if (_isSprinting)
+        accel = SprintAccel;
+    else
+        accel = Accel;
 
 
 Now, when the player is sprinting, we'll use ``SPRINT_ACCEL`` instead of ``ACCEL``, which will accelerate the player faster.
 Now, when the player is sprinting, we'll use ``SPRINT_ACCEL`` instead of ``ACCEL``, which will accelerate the player faster.