Multiplayer Basis

This commit is contained in:
LittleSheep 2024-08-05 16:30:50 +08:00
parent fc6678f58b
commit c5387d7784
8 changed files with 235 additions and 4 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -6,8 +6,9 @@
[sub_resource type="CircleShape2D" id="CircleShape2D_68yf8"] [sub_resource type="CircleShape2D" id="CircleShape2D_68yf8"]
radius = 26.0768 radius = 26.0768
[node name="Player" type="CharacterBody2D"] [node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("PlayerDashCountdown")]
script = ExtResource("1_0btyt") script = ExtResource("1_0btyt")
PlayerDashCountdown = NodePath("DashCountdown")
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(2.08165e-12, 2.08165e-12) position = Vector2(2.08165e-12, 2.08165e-12)
@ -16,3 +17,6 @@ texture = ExtResource("1_cqpqa")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_68yf8") shape = SubResource("CircleShape2D_68yf8")
[node name="DashCountdown" type="Timer" parent="."]
one_shot = true

View File

@ -1,14 +1,26 @@
[gd_scene load_steps=2 format=3 uid="uid://bjhmjrldq4lkt"] [gd_scene load_steps=4 format=3 uid="uid://bjhmjrldq4lkt"]
[ext_resource type="Script" path="res://Scripts/Multiplayer.cs" id="1_fym13"]
[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/MultiplayerUI.tscn" id="2_7o53i"]
[node name="Node" type="Node"] [node name="Node" type="Node"]
[node name="Camera2D" type="Camera2D" parent="."] [node name="MultiplayerNode" type="Node" parent="." node_paths=PackedStringArray("Playground")]
script = ExtResource("1_fym13")
Playground = NodePath("../Playground")
[node name="MultiplayerUi" parent="." node_paths=PackedStringArray("MultiplayerController") instance=ExtResource("2_7o53i")]
MultiplayerController = NodePath("../MultiplayerNode")
[node name="Playground" type="Node2D" parent="."]
[node name="Camera2D" type="Camera2D" parent="Playground"]
enabled = false
process_callback = 0 process_callback = 0
position_smoothing_enabled = true position_smoothing_enabled = true
rotation_smoothing_enabled = true rotation_smoothing_enabled = true
[node name="Player" parent="." node_paths=PackedStringArray("PlayerCamera") instance=ExtResource("1_vby0g")] [node name="Player" parent="Playground" node_paths=PackedStringArray("PlayerCamera") instance=ExtResource("1_vby0g")]
position = Vector2(0, 2) position = Vector2(0, 2)
PlayerCamera = NodePath("../Camera2D") PlayerCamera = NodePath("../Camera2D")

View File

@ -0,0 +1,49 @@
[gd_scene load_steps=2 format=3 uid="uid://bvll23f5ibd4v"]
[ext_resource type="Script" path="res://Scripts/UI/MultiplayerUi.cs" id="1_fm6j5"]
[node name="MultiplayerUi" type="Control" node_paths=PackedStringArray("ServerPortInput", "ServerAddrInput", "StartAsServerButton", "StartAsClientButton")]
process_mode = 3
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_fm6j5")
ServerPortInput = NodePath("CenterContainer/VBoxContainer/PortEdit")
ServerAddrInput = NodePath("CenterContainer/VBoxContainer/AddrEdit")
StartAsServerButton = NodePath("CenterContainer/VBoxContainer/HBoxContainer/HostButton")
StartAsClientButton = NodePath("CenterContainer/VBoxContainer/HBoxContainer/ConnectButton")
[node name="CenterContainer" type="CenterContainer" parent="."]
layout_mode = 0
offset_right = 1152.0
offset_bottom = 648.0
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
text = "Mutiplayer"
horizontal_alignment = 1
[node name="PortEdit" type="LineEdit" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
placeholder_text = "Server port"
[node name="AddrEdit" type="LineEdit" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
placeholder_text = "Server address"
[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
[node name="HostButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Host a Game"
[node name="ConnectButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Connect a Game"

71
Scripts/Multiplayer.cs Normal file
View File

@ -0,0 +1,71 @@
using System;
using Godot;
namespace CodingLand.Scripts;
public partial class Multiplayer : Node
{
[Export] public Node2D Playground;
private void GameFreeze()
{
Playground.Hide();
GetTree().Paused = true;
}
private void GameUnfreeze()
{
Playground.Show();
Playground.GetNode<Camera2D>("Camera2D").Enabled = true;
GetTree().Paused = false;
}
public override void _Ready()
{
GameFreeze();
if (DisplayServer.GetName() == "headless")
{
GD.Print("Starting server in headless mode...");
StartAsServer(4343);
}
}
public bool StartAsServer(int port)
{
var peer = new ENetMultiplayerPeer();
peer.CreateServer(port);
if (peer.GetConnectionStatus() == MultiplayerPeer.ConnectionStatus.Disconnected)
{
GD.PrintErr("Failed to start multiplayer server...");
OS.Alert("Failed to start multiplayer server...");
return false;
}
Multiplayer.MultiplayerPeer = peer;
GameUnfreeze();
return true;
}
public bool StartAsClient(string addr, int port)
{
if (string.IsNullOrEmpty(addr)) return false;
var peer = new ENetMultiplayerPeer();
peer.CreateClient(addr, port);
if (peer.GetConnectionStatus() == MultiplayerPeer.ConnectionStatus.Disconnected)
{
var info = $"Unable to connect multiplayer server {addr}:{port}";
GD.PrintErr(info);
OS.Alert(info);
return false;
}
Multiplayer.MultiplayerPeer = peer;
GameUnfreeze();
return true;
}
}

View File

@ -1,3 +1,4 @@
using System;
using Godot; using Godot;
namespace CodingLand.Scripts; namespace CodingLand.Scripts;
@ -13,6 +14,9 @@ public partial class Player : CharacterBody2D
[Export] public Camera2D PlayerCamera; [Export] public Camera2D PlayerCamera;
[Export] public Timer PlayerDashCountdown;
[Export] public float PlayerDashAcceleration = 2f;
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
var input = Vector2.Zero; var input = Vector2.Zero;
@ -40,6 +44,12 @@ public partial class Player : CharacterBody2D
Velocity = Velocity.MoveToward(Vector2.Zero, Deceleration * (float)delta); Velocity = Velocity.MoveToward(Vector2.Zero, Deceleration * (float)delta);
} }
if (Input.IsActionJustPressed("move_dash") && PlayerDashCountdown.IsStopped())
{
Velocity *= PlayerDashAcceleration;
PlayerDashCountdown.Start();
}
Position += Velocity * (float)delta; Position += Velocity * (float)delta;
MoveAndSlide(); MoveAndSlide();

View File

@ -0,0 +1,74 @@
using Godot;
namespace CodingLand.Scripts.UI;
public partial class MultiplayerUi : Control
{
[Export] public int DefaultServerPort = 4343;
[Export] public string DefaultServerAddr = "127.0.0.1";
[Export] public Multiplayer MultiplayerController;
[Export] public LineEdit ServerPortInput;
[Export] public LineEdit ServerAddrInput;
[Export] public Button StartAsServerButton;
[Export] public Button StartAsClientButton;
private void ApplySize()
{
var screenSize = GetViewportRect().Size;
Position = new Vector2(0, 0);
Size = screenSize;
GetNode<CenterContainer>("CenterContainer").Size = screenSize;
}
private bool DoValidation()
{
var addr = ServerAddrInput.Text;
var port = ServerPortInput.Text;
if (string.IsNullOrEmpty(addr)) return false;
if (string.IsNullOrEmpty(port) || !int.TryParse(port, out _)) return false;
return true;
}
public override void _Ready()
{
ApplySize();
ServerPortInput.Text = DefaultServerPort.ToString();
ServerAddrInput.Text = DefaultServerAddr;
StartAsServerButton.Pressed += () =>
{
if (!DoValidation())
{
OS.Alert("Invalid multiplayer configuration.");
return;
}
var port = ServerPortInput.Text;
var result = MultiplayerController.StartAsServer(int.Parse(port));
if (result)
Hide();
};
StartAsServerButton.Pressed += () =>
{
if (!DoValidation())
{
OS.Alert("Invalid multiplayer configuration.");
return;
}
var addr = ServerAddrInput.Text;
var port = ServerPortInput.Text;
var result = MultiplayerController.StartAsClient(addr, int.Parse(port));
if (result)
Hide();
};
}
}

View File

@ -41,6 +41,11 @@ move_right={
"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":68,"key_label":0,"unicode":100,"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":68,"key_label":0,"unicode":100,"echo":false,"script":null)
] ]
} }
move_dash={
"deadzone": 0.5,
"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)
]
}
[rendering] [rendering]