Reload & HUD

This commit is contained in:
LittleSheep 2024-08-08 17:10:48 +08:00
parent 91662a1c9f
commit e5be2bdc7c
12 changed files with 189 additions and 21 deletions

View File

@ -5,15 +5,18 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="c7bd02c7-bbb4-431f-81ca-d2f8b7b09b37" name="Changes" comment=""> <list default="true" id="c7bd02c7-bbb4-431f-81ca-d2f8b7b09b37" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/Scenes/UI/LaunchScreen.tscn" afterDir="false" /> <change afterPath="$PROJECT_DIR$/Scenes/UI/HUD.tscn" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Scripts/UI/HUD.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.CodingLand/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.CodingLand/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/.idea.CodingLand/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.CodingLand/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scenes/Player.tscn" beforeDir="false" afterPath="$PROJECT_DIR$/Scenes/Player.tscn" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Scenes/Player.tscn" beforeDir="false" afterPath="$PROJECT_DIR$/Scenes/Player.tscn" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scenes/Root.tscn" beforeDir="false" afterPath="$PROJECT_DIR$/Scenes/Root.tscn" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Scenes/Root.tscn" beforeDir="false" afterPath="$PROJECT_DIR$/Scenes/Root.tscn" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scenes/UI/StartScreen.tscn" beforeDir="false" /> <change beforePath="$PROJECT_DIR$/Scenes/UI/LaunchScreen.tscn" beforeDir="false" afterPath="$PROJECT_DIR$/Scenes/UI/LaunchScreen.tscn" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scripts/Bullet.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Bullet.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scripts/Launcher.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Launcher.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Scripts/Launcher.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Launcher.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scripts/Logic/PlayerInput.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Logic/PlayerInput.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scripts/Logic/World.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Logic/World.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Scripts/Logic/World.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Logic/World.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scripts/Player.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Player.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Scripts/Player.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/Player.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Scripts/UI/StartScreen.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Scripts/UI/LaunchScreen.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/project.godot" beforeDir="false" afterPath="$PROJECT_DIR$/project.godot" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -116,7 +119,7 @@
<workItem from="1722846222698" duration="9239000" /> <workItem from="1722846222698" duration="9239000" />
<workItem from="1722855558149" duration="11578000" /> <workItem from="1722855558149" duration="11578000" />
<workItem from="1723040712804" duration="74000" /> <workItem from="1723040712804" duration="74000" />
<workItem from="1723040934916" duration="11438000" /> <workItem from="1723040934916" duration="16092000" />
</task> </task>
<task id="LOCAL-00001" summary=":sparkles: Usable multiplayer"> <task id="LOCAL-00001" summary=":sparkles: Usable multiplayer">
<option name="closed" value="true" /> <option name="closed" value="true" />

View File

@ -101,6 +101,10 @@ rotation_smoothing_enabled = true
script = ExtResource("4_fwngj") script = ExtResource("4_fwngj")
Noise = SubResource("FastNoiseLite_cfnx7") Noise = SubResource("FastNoiseLite_cfnx7")
[node name="ReloadTimer" type="Timer" parent="."]
wait_time = 6.0
one_shot = true
[node name="DashCountdown" type="Timer" parent="."] [node name="DashCountdown" type="Timer" parent="."]
one_shot = true one_shot = true

View File

@ -1,18 +1,25 @@
[gd_scene load_steps=5 format=3 uid="uid://bjhmjrldq4lkt"] [gd_scene load_steps=6 format=3 uid="uid://bjhmjrldq4lkt"]
[ext_resource type="PackedScene" uid="uid://b3gx0bl43lku3" path="res://Scenes/Player.tscn" id="1_vby0g"] [ext_resource type="PackedScene" uid="uid://b3gx0bl43lku3" path="res://Scenes/Player.tscn" id="1_vby0g"]
[ext_resource type="PackedScene" uid="uid://bvll23f5ibd4v" path="res://Scenes/UI/LaunchScreen.tscn" id="2_7o53i"] [ext_resource type="PackedScene" uid="uid://bvll23f5ibd4v" path="res://Scenes/UI/LaunchScreen.tscn" id="2_7o53i"]
[ext_resource type="Script" path="res://Scripts/Launcher.cs" id="2_u5cms"] [ext_resource type="Script" path="res://Scripts/Launcher.cs" id="2_u5cms"]
[ext_resource type="Script" path="res://Scripts/Logic/World.cs" id="3_xwguj"] [ext_resource type="Script" path="res://Scripts/Logic/World.cs" id="3_xwguj"]
[ext_resource type="PackedScene" uid="uid://c7w5sgq0bshk0" path="res://Scenes/UI/HUD.tscn" id="5_qvun1"]
[node name="Node" type="Node"] [node name="Node" type="Node"]
[node name="LaunchScreen" parent="." node_paths=PackedStringArray("Launcher") instance=ExtResource("2_7o53i")] [node name="LaunchScreen" parent="." node_paths=PackedStringArray("Launcher") instance=ExtResource("2_7o53i")]
Launcher = NodePath("../LauncherNode") Launcher = NodePath("../LauncherNode")
[node name="LauncherNode" type="Node" parent="." node_paths=PackedStringArray("World")] [node name="LauncherNode" type="Node" parent="." node_paths=PackedStringArray("World", "Overlay")]
script = ExtResource("2_u5cms") script = ExtResource("2_u5cms")
World = NodePath("../World") World = NodePath("../World")
Overlay = NodePath("../OverlayLayer")
[node name="OverlayLayer" type="CanvasLayer" parent="."]
[node name="Hud" parent="OverlayLayer" node_paths=PackedStringArray("World") instance=ExtResource("5_qvun1")]
World = NodePath("../../World")
[node name="World" type="Node2D" parent="."] [node name="World" type="Node2D" parent="."]
script = ExtResource("3_xwguj") script = ExtResource("3_xwguj")

74
Scenes/UI/HUD.tscn Normal file
View File

@ -0,0 +1,74 @@
[gd_scene load_steps=2 format=3 uid="uid://c7w5sgq0bshk0"]
[ext_resource type="Script" path="res://Scripts/UI/HUD.cs" id="1_2iqqk"]
[node name="Hud" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("1_2iqqk")
[node name="TopBox" type="HBoxContainer" parent="."]
layout_mode = 0
offset_left = 16.0
offset_top = 16.0
offset_right = 1136.0
offset_bottom = 32.0
theme_override_constants/separation = 16
[node name="HealthBox" type="VBoxContainer" parent="TopBox"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Label" type="Label" parent="TopBox/HealthBox"]
layout_mode = 2
text = "Health 100/100"
[node name="Bar" type="ProgressBar" parent="TopBox/HealthBox"]
custom_minimum_size = Vector2(2.08165e-12, 16)
layout_mode = 2
size_flags_horizontal = 3
rounded = true
allow_greater = true
allow_lesser = true
show_percentage = false
[node name="ActionPointBox" type="VBoxContainer" parent="TopBox"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Label" type="Label" parent="TopBox/ActionPointBox"]
layout_mode = 2
text = "AP 20/20"
horizontal_alignment = 1
[node name="Bar" type="ProgressBar" parent="TopBox/ActionPointBox"]
custom_minimum_size = Vector2(2.08165e-12, 16)
layout_mode = 2
size_flags_horizontal = 3
rounded = true
allow_greater = true
allow_lesser = true
show_percentage = false
[node name="AmmoBox" type="VBoxContainer" parent="TopBox"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Label" type="Label" parent="TopBox/AmmoBox"]
layout_mode = 2
text = "Ammo 30/30"
horizontal_alignment = 2
[node name="Bar" type="ProgressBar" parent="TopBox/AmmoBox"]
custom_minimum_size = Vector2(2.08165e-12, 16)
layout_mode = 2
size_flags_horizontal = 3
rounded = true
allow_greater = true
allow_lesser = true
show_percentage = false

View File

@ -25,11 +25,17 @@ offset_bottom = 648.0
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"] [node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2 layout_mode = 2
[node name="MainTitle" type="Label" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
text = "AceField
Prototype · Closed test"
horizontal_alignment = 1
[node name="NameEdit" type="LineEdit" parent="CenterContainer/VBoxContainer"] [node name="NameEdit" type="LineEdit" parent="CenterContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
placeholder_text = "Player name" placeholder_text = "Player name"
[node name="MultiplayerTitle" type="Label" parent="CenterContainer/VBoxContainer"] [node name="PlayTitle" type="Label" parent="CenterContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
text = "Play the Game" text = "Play the Game"
horizontal_alignment = 1 horizontal_alignment = 1

View File

@ -17,10 +17,9 @@ public partial class Bullet : Area2D
BodyEntered += body => BodyEntered += body =>
{ {
if (body is Player player && player.PlayerId != PlayerId) if (body is not Player player || player.PlayerId == PlayerId) return;
{ player.TakeDamage(Damage);
player.TakeDamage(Damage); QueueFree();
}
}; };
} }

View File

@ -6,17 +6,20 @@ namespace AceField.Scripts;
public partial class Launcher : Node public partial class Launcher : Node
{ {
[Export] public World World; [Export] public World World;
[Export] public CanvasLayer Overlay;
private void GameFreeze() private void GameFreeze()
{ {
GetTree().Paused = true; GetTree().Paused = true;
World.Hide(); World.Hide();
Overlay.Hide();
} }
private void GameUnfreeze() private void GameUnfreeze()
{ {
GetTree().Paused = false; GetTree().Paused = false;
World.Show(); World.Show();
Overlay.Show();
} }
public override void _Ready() public override void _Ready()

View File

@ -6,6 +6,7 @@ public partial class PlayerInput : MultiplayerSynchronizer
{ {
[Export] public bool IsDashing; [Export] public bool IsDashing;
[Export] public bool IsShooting; [Export] public bool IsShooting;
[Export] public bool IsReloading;
[Export] public Vector2 MovementDirection; [Export] public Vector2 MovementDirection;
@ -25,6 +26,10 @@ public partial class PlayerInput : MultiplayerSynchronizer
[Rpc(CallLocal = true)] [Rpc(CallLocal = true)]
private void Shoot() private void Shoot()
=> IsShooting = true; => IsShooting = true;
[Rpc(CallLocal = true)]
private void Reload()
=> IsReloading = true;
public override void _Process(double delta) public override void _Process(double delta)
{ {
@ -32,8 +37,10 @@ public partial class PlayerInput : MultiplayerSynchronizer
if (Input.IsActionJustPressed("move_dash")) if (Input.IsActionJustPressed("move_dash"))
Rpc(nameof(Dash)); Rpc(nameof(Dash));
if (Input.IsActionJustPressed("shoot")) if (Input.IsActionJustPressed("weapon_shoot"))
Rpc(nameof(Shoot)); Rpc(nameof(Shoot));
if (Input.IsActionJustPressed("weapon_reload"))
Rpc(nameof(Reload));
} }
public override void _Input(InputEvent evt) public override void _Input(InputEvent evt)

View File

@ -33,10 +33,8 @@ public partial class World : Node2D
Multiplayer.PeerConnected -= AddPlayer_Adaptor; Multiplayer.PeerConnected -= AddPlayer_Adaptor;
} }
private string BuildPlayerName(int id) private static string BuildPlayerName(int id)
{ => $"Player#{id}";
return $"Player#{id}";
}
private void AddPlayer_Adaptor(long id) private void AddPlayer_Adaptor(long id)
=> AddPlayer((int)id); => AddPlayer((int)id);

View File

@ -44,6 +44,12 @@ public partial class Player : CharacterBody2D
public bool IsCurrentPlayer => _currentPlayerId == Multiplayer.GetUniqueId(); public bool IsCurrentPlayer => _currentPlayerId == Multiplayer.GetUniqueId();
public bool IsReloading
=> !GetNode<Timer>("ReloadTimer").IsStopped();
public double TimeRemainingOfReload
=> GetNode<Timer>("ReloadTimer").TimeLeft;
public override void _Ready() public override void _Ready()
{ {
Health = MaxHealth; Health = MaxHealth;
@ -52,18 +58,31 @@ public partial class Player : CharacterBody2D
if (PlayerId == Multiplayer.GetUniqueId()) if (PlayerId == Multiplayer.GetUniqueId())
PlayerCamera.Enabled = true; PlayerCamera.Enabled = true;
PlayerName ??= $"Player#{PlayerId}"; PlayerName ??= $"Player#{PlayerId}";
GetNode<Label>("Overlay/NameTag").Text = PlayerName; GetNode<Label>("Overlay/NameTag").Text = PlayerName;
GetNode<ProgressBar>("Overlay/HealthBar").Value = Health / MaxHealth * 100; GetNode<ProgressBar>("Overlay/HealthBar").Value = Health / MaxHealth * 100;
GetNode<Timer>("ReloadTimer").Timeout += () =>
{
AmmoAmount = MaxAmmoAmount;
PlayerInput.IsReloading = false;
};
} }
public override void _Process(double delta) public override void _Process(double delta)
{ {
if (PlayerInput.IsShooting) if (PlayerInput.IsShooting)
{ {
Rpc(nameof(Shoot));
PlayerInput.IsShooting = false; PlayerInput.IsShooting = false;
Shoot();
}
if (PlayerInput.IsReloading)
{
var timer = GetNode<Timer>("ReloadTimer");
if (timer.IsStopped())
timer.Start();
} }
} }
@ -86,10 +105,11 @@ public partial class Player : CharacterBody2D
} }
var dashCountdown = GetNode<Timer>("DashCountdown"); var dashCountdown = GetNode<Timer>("DashCountdown");
if (PlayerInput.IsDashing && dashCountdown.IsStopped()) if (PlayerInput.IsDashing && dashCountdown.IsStopped() && ActionPoints > 0)
{ {
PlayerInput.IsDashing = false; PlayerInput.IsDashing = false;
Velocity *= PlayerDashAcceleration; Velocity *= PlayerDashAcceleration;
ActionPoints--;
dashCountdown.Start(); dashCountdown.Start();
} }
@ -122,14 +142,16 @@ public partial class Player : CharacterBody2D
shakableCamera.AddTrauma(0.5f); shakableCamera.AddTrauma(0.5f);
} }
[Rpc(MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)]
private void Shoot() private void Shoot()
{ {
if (AmmoAmount <= 0) return;
var marker = GetNode<Marker2D>("RotationCentre/Muzzle"); var marker = GetNode<Marker2D>("RotationCentre/Muzzle");
var projectile = BulletScene.Instantiate<Bullet>(); var projectile = BulletScene.Instantiate<Bullet>();
projectile.Transform = marker.GlobalTransform; projectile.Transform = marker.GlobalTransform;
projectile.PlayerId = PlayerId; projectile.PlayerId = PlayerId;
GetParent().AddChild(projectile); GetParent().AddChild(projectile);
AmmoAmount--;
} }
} }

40
Scripts/UI/HUD.cs Normal file
View File

@ -0,0 +1,40 @@
using AceField.Scripts.Logic;
using Godot;
namespace AceField.Scripts.UI;
public partial class HUD : Control
{
[Export] public World World;
private void ApplySize()
{
var screenSize = GetViewportRect().Size;
Position = new Vector2(0, 0);
Size = screenSize;
GetNode<HBoxContainer>("TopBox").Size = new Vector2(screenSize.X-16*2, 16);
}
public override void _Process(double delta)
{
var player = World.GetCurrentPlayer();
if (player == null) return;
var healthBar = GetNode<ProgressBar>("TopBox/HealthBox/Bar");
var healthLabel = GetNode<Label>("TopBox/HealthBox/Label");
healthBar.Value = player.Health / player.MaxHealth * 100;
healthLabel.Text = $"Health {player.Health}/{player.MaxHealth}";
var actionBar = GetNode<ProgressBar>("TopBox/ActionPointBox/Bar");
var actionLabel = GetNode<Label>("TopBox/ActionPointBox/Label");
actionBar.Value = player.ActionPoints / player.MaxActionPoints * 100;
actionLabel.Text = $"AP {player.ActionPoints}/{player.MaxActionPoints}";
var ammoBar = GetNode<ProgressBar>("TopBox/AmmoBox/Bar");
var ammoLabel = GetNode<Label>("TopBox/AmmoBox/Label");
ammoBar.Value = player.AmmoAmount / player.MaxAmmoAmount * 100;
if (player.IsReloading) ammoLabel.Text = $"Reloading... {player.TimeRemainingOfReload:F2}";
else ammoLabel.Text = $"Ammo {player.AmmoAmount}/{player.MaxAmmoAmount}";
}
}

View File

@ -46,11 +46,16 @@ move_dash={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"echo":false,"script":null)
] ]
} }
shoot={ weapon_shoot={
"deadzone": 0.5, "deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"echo":false,"script":null)
] ]
} }
weapon_reload={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"echo":false,"script":null)
]
}
[rendering] [rendering]