mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 13:30:07 +01:00
121 lines
3.9 KiB
C#
121 lines
3.9 KiB
C#
using Godot;
|
|
|
|
public partial class Player : CharacterBody3D
|
|
{
|
|
// Emitted when the player was hit by a mob.
|
|
[Signal]
|
|
public delegate void HitEventHandler();
|
|
|
|
// How fast the player moves in meters per second.
|
|
[Export]
|
|
public int Speed { get; set; } = 14;
|
|
// The downward acceleration when in the air, in meters per second squared.
|
|
[Export]
|
|
public int FallAcceleration { get; set; } = 75;
|
|
// Vertical impulse applied to the character upon jumping in meters per second.
|
|
[Export]
|
|
public int JumpImpulse { get; set; } = 20;
|
|
// Vertical impulse applied to the character upon bouncing over a mob in meters per second.
|
|
[Export]
|
|
public int BounceImpulse { get; set; } = 16;
|
|
|
|
private Vector3 _targetVelocity = Vector3.Zero;
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
// We create a local variable to store the input direction.
|
|
Vector3 direction = Vector3.Zero;
|
|
|
|
// We check for each move input and update the direction accordingly.
|
|
if (Input.IsActionPressed("move_right"))
|
|
{
|
|
direction.X += 1.0f;
|
|
}
|
|
if (Input.IsActionPressed("move_left"))
|
|
{
|
|
direction.X -= 1.0f;
|
|
}
|
|
if (Input.IsActionPressed("move_back"))
|
|
{
|
|
// Notice how we are working with the vector's X and Z axes.
|
|
// In 3D, the XZ plane is the ground plane.
|
|
direction.Z += 1.0f;
|
|
}
|
|
if (Input.IsActionPressed("move_forward"))
|
|
{
|
|
direction.Z -= 1.0f;
|
|
}
|
|
|
|
// Prevent diagonal movement being very fast.
|
|
if (direction != Vector3.Zero)
|
|
{
|
|
direction = direction.Normalized();
|
|
// Setting the basis property will affect the rotation of the node.
|
|
GetNode<Node3D>("Pivot").Basis = Basis.LookingAt(direction);
|
|
GetNode<AnimationPlayer>("AnimationPlayer").SpeedScale = 4;
|
|
}
|
|
else
|
|
{
|
|
GetNode<AnimationPlayer>("AnimationPlayer").SpeedScale = 1;
|
|
}
|
|
|
|
// Ground velocity
|
|
_targetVelocity.X = direction.X * Speed;
|
|
_targetVelocity.Z = direction.Z * Speed;
|
|
|
|
// Vertical velocity
|
|
if (!IsOnFloor())
|
|
{
|
|
_targetVelocity.Y -= FallAcceleration * (float)delta;
|
|
}
|
|
|
|
// Jumping.
|
|
if (IsOnFloor() && Input.IsActionJustPressed("jump"))
|
|
{
|
|
_targetVelocity.Y = JumpImpulse;
|
|
}
|
|
|
|
// Iterate through all collisions that occurred this frame.
|
|
for (int index = 0; index < GetSlideCollisionCount(); index++)
|
|
{
|
|
// We get one of the collisions with the player.
|
|
KinematicCollision3D collision = GetSlideCollision(index);
|
|
|
|
// If the collision is with a mob.
|
|
// With C# we leverage typing and pattern-matching
|
|
// instead of checking for the group we created.
|
|
if (collision.GetCollider() is Mob mob)
|
|
{
|
|
// We check that we are hitting it from above.
|
|
if (Vector3.Up.Dot(collision.GetNormal()) > 0.1f)
|
|
{
|
|
// If so, we squash it and bounce.
|
|
mob.Squash();
|
|
_targetVelocity.Y = BounceImpulse;
|
|
// Prevent further duplicate calls.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Moving the character
|
|
Velocity = _targetVelocity;
|
|
MoveAndSlide();
|
|
|
|
Node3D pivot = GetNode<Node3D>("Pivot");
|
|
pivot.Rotation = new Vector3(Mathf.Pi / 6.0f * Velocity.Y / JumpImpulse, pivot.Rotation.Y, pivot.Rotation.Z);
|
|
}
|
|
|
|
private void Die()
|
|
{
|
|
EmitSignal(SignalName.Hit);
|
|
QueueFree();
|
|
}
|
|
|
|
// We also specified this function name in PascalCase in the editor's connection window
|
|
private void OnMobDetectorBodyEntered(Node3D body)
|
|
{
|
|
Die();
|
|
}
|
|
}
|