mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-03 05:48:42 +03:00
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:
committed by
Max Hilbrunner
parent
736a34ff0c
commit
e4c5a12916
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user