✨ Bullet, shooting & camera shake
This commit is contained in:
31
Scripts/Bullet.cs
Normal file
31
Scripts/Bullet.cs
Normal 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;
|
||||
}
|
||||
}
|
58
Scripts/Effects/CameraShake.cs
Normal file
58
Scripts/Effects/CameraShake.cs
Normal 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);
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user