✨ Multiplayer Basis
This commit is contained in:
		
							
								
								
									
										6
									
								
								.idea/.idea.CodingLand/.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/.idea.CodingLand/.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
 | 
					    <mapping directory="" vcs="Git" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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")
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								Scenes/UI/MultiplayerUI.tscn
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								Scenes/UI/MultiplayerUI.tscn
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										71
									
								
								Scripts/Multiplayer.cs
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										74
									
								
								Scripts/UI/MultiplayerUi.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Scripts/UI/MultiplayerUi.cs
									
									
									
									
									
										Normal 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();
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user