Bullet, shooting & camera shake

This commit is contained in:
2024-08-08 12:13:53 +08:00
parent 6fa2c8411f
commit 0f9192a5f8
10 changed files with 216 additions and 20 deletions

31
Scripts/Bullet.cs Normal file
View File

@ -0,0 +1,31 @@
using Godot;
namespace AceField.Scripts;
public partial class Bullet : Area2D
{
[Export] public int PlayerId = 1;
[Export] public float Speed = 1500;
[Export] public double Damage = 8;
[Export] public Timer FreeTimer;
public override void _Ready()
{
FreeTimer.Timeout += QueueFree;
BodyEntered += body =>
{
if (body is Player player && player.PlayerId != PlayerId)
{
player.TakeDamage(Damage);
}
};
}
public override void _PhysicsProcess(double delta)
{
Position += -Transform.Y * Speed * (float)delta;
}
}

View File

@ -0,0 +1,58 @@
using System;
using Godot;
namespace AceField.Scripts.Effects;
public partial class CameraShake : Camera2D
{
[Export] public float Decay = 0.8f;
[Export] public Vector2 MaxOffset = new(100, 75);
[Export] public float MaxRoll = 0.0f;
[Export] public FastNoiseLite Noise;
private float _noiseY = 0.0f;
private float _trauma = 0.0f;
private int _traumaExponent = 3;
public override void _Ready()
{
GD.Randomize();
Noise.Seed = (int)GD.Randi();
}
public override void _Process(double delta)
{
if (_trauma > 0)
{
_trauma = Mathf.Max(_trauma - Decay * (float)delta, 0);
Shake();
}
else if (Offset.X != 0 || Offset.Y != 0 || Rotation != 0)
{
Mathf.Lerp(Offset.X, 0.0f, 1);
Mathf.Lerp(Offset.Y, 0.0f, 1);
Mathf.Lerp(Rotation, 0.0f, 1);
}
}
private void Shake()
{
var amount = Mathf.Pow(_trauma, _traumaExponent);
_noiseY++;
Rotation = MaxRoll * amount * Noise.GetNoise2D(0, _noiseY);
Offset = new Vector2(
MaxOffset.X * amount * Noise.GetNoise2D(2000, _noiseY),
MaxOffset.Y * amount * Noise.GetNoise2D(3000, _noiseY)
);
}
public void AddTrauma(float amount)
{
_trauma = Mathf.Min(_trauma + amount, 1.0f);
}
public void SetTrauma(float amount)
{
_trauma = Mathf.Min(amount, 1.0f);
}
}

View File

@ -5,6 +5,7 @@ namespace AceField.Scripts.Logic;
public partial class PlayerInput : MultiplayerSynchronizer
{
[Export] public bool IsDashing;
[Export] public bool IsShooting;
[Export] public Vector2 MovementDirection;
@ -21,12 +22,18 @@ public partial class PlayerInput : MultiplayerSynchronizer
private void Dash()
=> IsDashing = true;
[Rpc(CallLocal = true)]
private void Shoot()
=> IsShooting = true;
public override void _Process(double delta)
{
MovementDirection = Input.GetVector("move_left", "move_right", "move_up", "move_down");
if (Input.IsActionJustPressed("move_dash"))
Rpc(nameof(Dash));
if (Input.IsActionJustPressed("shoot"))
Rpc(nameof(Shoot));
}
public override void _Input(InputEvent evt)

View File

@ -1,3 +1,4 @@
using AceField.Scripts.Effects;
using AceField.Scripts.Logic;
using Godot;
@ -14,12 +15,18 @@ public partial class Player : CharacterBody2D
[Export] public int Reach = 5;
[Export] public Camera2D PlayerCamera;
[Export] public double Health = 100;
[Export] public double MaxHealth = 100;
[Export] public double ActionPoints = 20;
[Export] public double MaxActionPoints = 20;
[Export] public Camera2D PlayerCamera;
[Export] public PlayerInput PlayerInput;
[Export] public float PlayerDashAcceleration = 2f;
[Export] public PackedScene BulletScene;
[Export]
public int PlayerId
{
@ -39,12 +46,20 @@ public partial class Player : CharacterBody2D
public override void _Ready()
{
Health = MaxHealth;
ActionPoints = MaxActionPoints;
if (PlayerId == Multiplayer.GetUniqueId())
PlayerCamera.Enabled = true;
}
public override void _Process(double delta)
{
if (PlayerInput.IsShooting)
{
Rpc(nameof(Shoot));
PlayerInput.IsShooting = false;
}
}
public override void _PhysicsProcess(double delta)
@ -75,4 +90,29 @@ public partial class Player : CharacterBody2D
Position += Velocity * (float)delta;
MoveAndSlide();
}
public void TakeDamage(double damage)
{
Rpc(nameof(GotDamage), damage);
}
[Rpc(MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)]
private void GotDamage(double damage)
{
Health -= damage;
var shakableCamera = GetNode<CameraShake>("Camera2D");
shakableCamera.AddTrauma(0.5f);
}
[Rpc(MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)]
private void Shoot()
{
var marker = GetNode<Marker2D>("Muzzle");
var projectile = BulletScene.Instantiate<Bullet>();
projectile.Transform = marker.GlobalTransform;
projectile.PlayerId = PlayerId;
GetParent().AddChild(projectile);
}
}