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.
This commit is contained in:
Louis-Jacques Bourdages
2019-04-22 06:32:20 -04:00
committed by Max Hilbrunner
parent 736a34ff0c
commit e4c5a12916

View File

@@ -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.
Add the following code to ``Player.gd``:
::
.. tabs::
.. code-tab:: gdscript GDScript
extends KinematicBody
@@ -240,6 +241,135 @@ Add the following code to ``Player.gd``:
camera_rot.x = clamp(camera_rot.x, -70, 70)
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:
.. 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:
::
.. tabs::
.. code-tab:: gdscript GDScript
if Input.is_action_pressed("movement_forward"):
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))
if Input.is_action_pressed("movement_right"):
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.
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:
::
.. tabs::
.. code-tab:: gdscript GDScript
if Input.is_action_pressed("movement_forward"):
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())
if Input.is_action_pressed("movement_right"):
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:
@@ -539,7 +693,8 @@ so let's do that!
First we need a few more class variables in our player script:
::
.. tabs::
.. code-tab:: gdscript GDScript
const MAX_SPRINT_SPEED = 30
const SPRINT_ACCEL = 18
@@ -547,6 +702,16 @@ First we need a few more class variables in our player script:
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
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``:
::
.. tabs::
.. code-tab:: gdscript GDScript
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.
_________
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
@@ -584,6 +755,26 @@ Now we need to change some of the code in ``process_input``. Add the following s
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:
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:
::
.. tabs::
.. code-tab:: gdscript GDScript
if is_sprinting:
target *= MAX_SPRINT_SPEED
else:
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.
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:
::
.. tabs::
.. code-tab:: gdscript GDScript
if is_sprinting:
accel = SPRINT_ACCEL
else:
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.