✨ Reload & HUD
This commit is contained in:
parent
91662a1c9f
commit
e5be2bdc7c
@ -5,15 +5,18 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<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$/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/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/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/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>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@ -116,7 +119,7 @@
|
||||
<workItem from="1722846222698" duration="9239000" />
|
||||
<workItem from="1722855558149" duration="11578000" />
|
||||
<workItem from="1723040712804" duration="74000" />
|
||||
<workItem from="1723040934916" duration="11438000" />
|
||||
<workItem from="1723040934916" duration="16092000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary=":sparkles: Usable multiplayer">
|
||||
<option name="closed" value="true" />
|
||||
|
@ -101,6 +101,10 @@ rotation_smoothing_enabled = true
|
||||
script = ExtResource("4_fwngj")
|
||||
Noise = SubResource("FastNoiseLite_cfnx7")
|
||||
|
||||
[node name="ReloadTimer" type="Timer" parent="."]
|
||||
wait_time = 6.0
|
||||
one_shot = true
|
||||
|
||||
[node name="DashCountdown" type="Timer" parent="."]
|
||||
one_shot = true
|
||||
|
||||
|
@ -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://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/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="LaunchScreen" parent="." node_paths=PackedStringArray("Launcher") instance=ExtResource("2_7o53i")]
|
||||
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")
|
||||
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="."]
|
||||
script = ExtResource("3_xwguj")
|
||||
|
74
Scenes/UI/HUD.tscn
Normal file
74
Scenes/UI/HUD.tscn
Normal 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
|
@ -25,11 +25,17 @@ offset_bottom = 648.0
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
|
||||
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"]
|
||||
layout_mode = 2
|
||||
placeholder_text = "Player name"
|
||||
|
||||
[node name="MultiplayerTitle" type="Label" parent="CenterContainer/VBoxContainer"]
|
||||
[node name="PlayTitle" type="Label" parent="CenterContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Play the Game"
|
||||
horizontal_alignment = 1
|
||||
|
@ -17,10 +17,9 @@ public partial class Bullet : Area2D
|
||||
|
||||
BodyEntered += body =>
|
||||
{
|
||||
if (body is Player player && player.PlayerId != PlayerId)
|
||||
{
|
||||
if (body is not Player player || player.PlayerId == PlayerId) return;
|
||||
player.TakeDamage(Damage);
|
||||
}
|
||||
QueueFree();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,17 +6,20 @@ namespace AceField.Scripts;
|
||||
public partial class Launcher : Node
|
||||
{
|
||||
[Export] public World World;
|
||||
[Export] public CanvasLayer Overlay;
|
||||
|
||||
private void GameFreeze()
|
||||
{
|
||||
GetTree().Paused = true;
|
||||
World.Hide();
|
||||
Overlay.Hide();
|
||||
}
|
||||
|
||||
private void GameUnfreeze()
|
||||
{
|
||||
GetTree().Paused = false;
|
||||
World.Show();
|
||||
Overlay.Show();
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
|
@ -6,6 +6,7 @@ public partial class PlayerInput : MultiplayerSynchronizer
|
||||
{
|
||||
[Export] public bool IsDashing;
|
||||
[Export] public bool IsShooting;
|
||||
[Export] public bool IsReloading;
|
||||
|
||||
[Export] public Vector2 MovementDirection;
|
||||
|
||||
@ -26,14 +27,20 @@ public partial class PlayerInput : MultiplayerSynchronizer
|
||||
private void Shoot()
|
||||
=> IsShooting = true;
|
||||
|
||||
[Rpc(CallLocal = true)]
|
||||
private void Reload()
|
||||
=> IsReloading = 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"))
|
||||
if (Input.IsActionJustPressed("weapon_shoot"))
|
||||
Rpc(nameof(Shoot));
|
||||
if (Input.IsActionJustPressed("weapon_reload"))
|
||||
Rpc(nameof(Reload));
|
||||
}
|
||||
|
||||
public override void _Input(InputEvent evt)
|
||||
|
@ -33,10 +33,8 @@ public partial class World : Node2D
|
||||
Multiplayer.PeerConnected -= AddPlayer_Adaptor;
|
||||
}
|
||||
|
||||
private string BuildPlayerName(int id)
|
||||
{
|
||||
return $"Player#{id}";
|
||||
}
|
||||
private static string BuildPlayerName(int id)
|
||||
=> $"Player#{id}";
|
||||
|
||||
private void AddPlayer_Adaptor(long id)
|
||||
=> AddPlayer((int)id);
|
||||
|
@ -44,6 +44,12 @@ public partial class Player : CharacterBody2D
|
||||
|
||||
public bool IsCurrentPlayer => _currentPlayerId == Multiplayer.GetUniqueId();
|
||||
|
||||
public bool IsReloading
|
||||
=> !GetNode<Timer>("ReloadTimer").IsStopped();
|
||||
|
||||
public double TimeRemainingOfReload
|
||||
=> GetNode<Timer>("ReloadTimer").TimeLeft;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Health = MaxHealth;
|
||||
@ -56,14 +62,27 @@ public partial class Player : CharacterBody2D
|
||||
GetNode<Label>("Overlay/NameTag").Text = PlayerName;
|
||||
|
||||
GetNode<ProgressBar>("Overlay/HealthBar").Value = Health / MaxHealth * 100;
|
||||
|
||||
GetNode<Timer>("ReloadTimer").Timeout += () =>
|
||||
{
|
||||
AmmoAmount = MaxAmmoAmount;
|
||||
PlayerInput.IsReloading = false;
|
||||
};
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (PlayerInput.IsShooting)
|
||||
{
|
||||
Rpc(nameof(Shoot));
|
||||
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");
|
||||
if (PlayerInput.IsDashing && dashCountdown.IsStopped())
|
||||
if (PlayerInput.IsDashing && dashCountdown.IsStopped() && ActionPoints > 0)
|
||||
{
|
||||
PlayerInput.IsDashing = false;
|
||||
Velocity *= PlayerDashAcceleration;
|
||||
ActionPoints--;
|
||||
dashCountdown.Start();
|
||||
}
|
||||
|
||||
@ -122,14 +142,16 @@ public partial class Player : CharacterBody2D
|
||||
shakableCamera.AddTrauma(0.5f);
|
||||
}
|
||||
|
||||
[Rpc(MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)]
|
||||
private void Shoot()
|
||||
{
|
||||
if (AmmoAmount <= 0) return;
|
||||
|
||||
var marker = GetNode<Marker2D>("RotationCentre/Muzzle");
|
||||
var projectile = BulletScene.Instantiate<Bullet>();
|
||||
projectile.Transform = marker.GlobalTransform;
|
||||
projectile.PlayerId = PlayerId;
|
||||
|
||||
GetParent().AddChild(projectile);
|
||||
AmmoAmount--;
|
||||
}
|
||||
}
|
||||
|
40
Scripts/UI/HUD.cs
Normal file
40
Scripts/UI/HUD.cs
Normal 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}";
|
||||
}
|
||||
}
|
@ -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)
|
||||
]
|
||||
}
|
||||
shoot={
|
||||
weapon_shoot={
|
||||
"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)
|
||||
]
|
||||
}
|
||||
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]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user