From 09c345785cacf5f6aac9df6bebb349aa98c1f483 Mon Sep 17 00:00:00 2001 From: patrick_pluto Date: Fri, 2 Aug 2024 20:13:42 +0200 Subject: [PATCH] Added Multiplayer Support --- maps/base_map.tscn | 9 ++--- menus/create.tscn | 60 ++++++++++++++++++++++++++++++ menus/join.tscn | 49 +++++++++++++++++++++++++ menus/main_menu.tscn | 65 +++++++++++++++++++++++++++++++++ project.godot | 8 ++-- scripts/create.gd | 10 +++++ scripts/game.gd | 5 ++- scripts/join.gd | 14 +++++++ scripts/main_menu.gd | 20 ++++++++++ scripts/movement.gd | 87 ++++++++++++++++++++++++++------------------ scripts/server.gd | 57 +++++++++++++++++++++++++++++ 11 files changed, 338 insertions(+), 46 deletions(-) create mode 100644 menus/create.tscn create mode 100644 menus/join.tscn create mode 100644 menus/main_menu.tscn create mode 100644 scripts/create.gd create mode 100644 scripts/join.gd create mode 100644 scripts/main_menu.gd create mode 100644 scripts/server.gd diff --git a/maps/base_map.tscn b/maps/base_map.tscn index f5c212d..4610c77 100644 --- a/maps/base_map.tscn +++ b/maps/base_map.tscn @@ -1,12 +1,12 @@ -[gd_scene load_steps=4 format=3 uid="uid://2qsccmko8yl8"] +[gd_scene load_steps=3 format=3 uid="uid://2qsccmko8yl8"] -[ext_resource type="PackedScene" uid="uid://b440i2oidk5sp" path="res://objects/player.tscn" id="1_e1efq"] [ext_resource type="PackedScene" uid="uid://4mhcwvn365ki" path="res://objects/computer.tscn" id="2_28qhl"] [sub_resource type="BoxShape3D" id="BoxShape3D_34oyu"] size = Vector3(50, 1, 50) -[node name="Node3D" type="Node3D"] +[node name="map" type="Node3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0) [node name="StaticBody3D" type="StaticBody3D" parent="."] @@ -16,9 +16,6 @@ size = Vector3(50, 1, 50) [node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"] shape = SubResource("BoxShape3D_34oyu") -[node name="player" parent="." instance=ExtResource("1_e1efq")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.32619, 2.43562, 13.4822) - [node name="light" type="DirectionalLight3D" parent="."] transform = Transform3D(0.545371, 0.353189, 0.76015, 0, -0.90689, 0.421368, 0.838195, -0.229802, -0.494591, 0, 10.2747, 0) diff --git a/menus/create.tscn b/menus/create.tscn new file mode 100644 index 0000000..6efefc9 --- /dev/null +++ b/menus/create.tscn @@ -0,0 +1,60 @@ +[gd_scene load_steps=2 format=3 uid="uid://bl6wir1clomvu"] + +[ext_resource type="Script" path="res://scripts/create.gd" id="1_ewomb"] + +[node name="create" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_ewomb") + +[node name="player_list" type="VBoxContainer" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="list" type="Label" parent="player_list"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 + +[node name="player_customization" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -128.0 +offset_top = -32.0 +offset_right = 128.0 +offset_bottom = 32.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="name" type="TextEdit" parent="player_customization"] +custom_minimum_size = Vector2(256, 64) +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +placeholder_text = "Name" + +[node name="start" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -184.0 +offset_top = -53.0 +grow_horizontal = 0 +grow_vertical = 0 + +[node name="start" type="Button" parent="start"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Start Game" + +[connection signal="pressed" from="start/start" to="." method="_on_start_pressed"] diff --git a/menus/join.tscn b/menus/join.tscn new file mode 100644 index 0000000..f78c95e --- /dev/null +++ b/menus/join.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=2 format=3 uid="uid://bh1ptr4bepla6"] + +[ext_resource type="Script" path="res://scripts/join.gd" id="1_evkiv"] + +[node name="Join" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_evkiv") + +[node name="player_customization" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -128.0 +offset_top = -32.0 +offset_right = 128.0 +offset_bottom = 32.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="name" type="TextEdit" parent="player_customization"] +custom_minimum_size = Vector2(256, 64) +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +placeholder_text = "Name" + +[node name="ip" type="TextEdit" parent="player_customization"] +custom_minimum_size = Vector2(256, 64) +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +placeholder_text = "IP Address" + +[node name="join" type="Button" parent="player_customization"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Join Game" + +[node name="Timer" type="Timer" parent="player_customization"] +one_shot = true + +[connection signal="pressed" from="player_customization/join" to="." method="_on_join_pressed"] +[connection signal="timeout" from="player_customization/Timer" to="." method="_on_timer_timeout"] diff --git a/menus/main_menu.tscn b/menus/main_menu.tscn new file mode 100644 index 0000000..83ebad4 --- /dev/null +++ b/menus/main_menu.tscn @@ -0,0 +1,65 @@ +[gd_scene load_steps=2 format=3 uid="uid://csemv5nsltino"] + +[ext_resource type="Script" path="res://scripts/main_menu.gd" id="1_hvi3a"] + +[node name="main_menu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_hvi3a") + +[node name="main_content" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -179.0 +offset_top = -123.0 +offset_right = 179.0 +offset_bottom = 123.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="main_content"] +layout_mode = 2 +theme_override_font_sizes/font_size = 96 +text = "FreeFTF" + +[node name="create" type="Button" parent="main_content"] +layout_mode = 2 +size_flags_vertical = 0 +theme_override_font_sizes/font_size = 32 +text = "Create Lobby" + +[node name="join" type="Button" parent="main_content"] +layout_mode = 2 +size_flags_vertical = 8 +theme_override_font_sizes/font_size = 32 +text = "Join Lobby" + +[node name="ver_string" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -40.0 +offset_top = -40.0 +grow_horizontal = 0 +grow_vertical = 0 + +[node name="Label" type="Label" parent="ver_string"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Milestone 1" + +[connection signal="pressed" from="main_content/create" to="." method="_on_create_pressed"] +[connection signal="pressed" from="main_content/join" to="." method="_on_join_pressed"] diff --git a/project.godot b/project.godot index 11bd540..eddf589 100644 --- a/project.godot +++ b/project.godot @@ -10,13 +10,14 @@ config_version=5 [application] -config/name="OpenFlee" -run/main_scene="res://maps/base_map.tscn" +config/name="FreeFTF" +run/main_scene="res://menus/main_menu.tscn" config/features=PackedStringArray("4.2", "Forward Plus") [autoload] Game="*res://scripts/game.gd" +Server="*res://scripts/server.gd" [input] @@ -63,5 +64,4 @@ zoom_out={ [rendering] -renderer/rendering_method="gl_compatibility" -renderer/rendering_method.mobile="gl_compatibility" +textures/vram_compression/import_etc2_astc=true diff --git a/scripts/create.gd b/scripts/create.gd new file mode 100644 index 0000000..26cacdb --- /dev/null +++ b/scripts/create.gd @@ -0,0 +1,10 @@ +extends Control + + +func _ready(): + Server.create_game() + + +func _on_start_pressed(): + Server.send_playerinfo(get_tree().root.get_node("create/player_customization/name").text, multiplayer.get_unique_id()) + Server.start_game.rpc(Server.players) diff --git a/scripts/game.gd b/scripts/game.gd index 19c87b7..64db95b 100644 --- a/scripts/game.gd +++ b/scripts/game.gd @@ -1,6 +1,9 @@ extends Node var computers = 0 +var players = 0 func _process(delta): - print(computers) + pass + + diff --git a/scripts/join.gd b/scripts/join.gd new file mode 100644 index 0000000..17b00dd --- /dev/null +++ b/scripts/join.gd @@ -0,0 +1,14 @@ +extends Control + + + +func _on_join_pressed(): + if $player_customization/name.text != "" or $player_customization/ip.text != "": + Server.join_game($player_customization/ip.text) + $player_customization/join.hide() + $player_customization/join.disabled = true + $player_customization/Timer.start() + + +func _on_timer_timeout(): + Server.send_playerinfo.rpc($player_customization/name.text, multiplayer.get_unique_id()) diff --git a/scripts/main_menu.gd b/scripts/main_menu.gd new file mode 100644 index 0000000..9f204a6 --- /dev/null +++ b/scripts/main_menu.gd @@ -0,0 +1,20 @@ +extends Control + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_create_pressed(): + get_tree().change_scene_to_file("res://menus/create.tscn") + + +func _on_join_pressed(): + get_tree().change_scene_to_file("res://menus/join.tscn") + diff --git a/scripts/movement.gd b/scripts/movement.gd index 5b9aaa9..3835ff2 100644 --- a/scripts/movement.gd +++ b/scripts/movement.gd @@ -4,50 +4,67 @@ extends CharacterBody3D const SPEED = 5.0 const JUMP_VELOCITY = 4.5 var zoom = 0 +var player_no +var enabled = false var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") +func _ready(): + player_no = Game.players + Game.players += 1 + print(Server.players) + print(Server.players_numbered[player_no]) + print(multiplayer.get_unique_id()) + if Server.players_numbered[player_no] == multiplayer.get_unique_id(): + enabled = true + $cam_y/Camera3D.current = true func _physics_process(delta): - - if not is_on_floor(): - velocity.y -= gravity * delta - - - if Input.is_action_just_pressed("jump") and is_on_floor(): - velocity.y = JUMP_VELOCITY + if enabled: - var input_dir = Input.get_vector("left", "right", "forwards", "backwards") - var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() - if direction: - velocity.x = direction.x * SPEED - velocity.z = direction.z * SPEED - else: - velocity.x = move_toward(velocity.x, 0, SPEED) - velocity.z = move_toward(velocity.z, 0, SPEED) + if not is_on_floor(): + velocity.y -= gravity * delta - move_and_slide() + + if Input.is_action_just_pressed("jump") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + var input_dir = Input.get_vector("left", "right", "forwards", "backwards") + var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() + if direction: + velocity.x = direction.x * SPEED + velocity.z = direction.z * SPEED + else: + velocity.x = move_toward(velocity.x, 0, SPEED) + velocity.z = move_toward(velocity.z, 0, SPEED) + + move_and_slide() + Server.sync_player.rpc(name, position, rotation) func _input(event): - if event is InputEventMouseMotion and (Input.is_action_pressed("cam_look") or $cam_y/Camera3D.position.z == 0): - var camera_rotation = event.relative * 0.01 - if $cam_y.rotation.x <= 1.6 && camera_rotation.y <= 0: - $cam_y.rotate(Vector3.RIGHT, -camera_rotation.y) - elif $cam_y.rotation.x >= -1.6 && camera_rotation.y >= 0: - $cam_y.rotate(Vector3.RIGHT, -camera_rotation.y) - if $cam_y.rotation.x >= 1.6: - $cam_y.rotation.x = 1.6 - elif $cam_y.rotation.x <= -1.6: - $cam_y.rotation.x = -1.6 - rotate(Vector3.DOWN, camera_rotation.x) + if enabled: + + if event is InputEventMouseMotion and (Input.is_action_pressed("cam_look") or $cam_y/Camera3D.position.z == 0): + var camera_rotation = event.relative * 0.01 + if $cam_y.rotation.x <= 1.6 && camera_rotation.y <= 0: + $cam_y.rotate(Vector3.RIGHT, -camera_rotation.y) + elif $cam_y.rotation.x >= -1.6 && camera_rotation.y >= 0: + $cam_y.rotate(Vector3.RIGHT, -camera_rotation.y) + if $cam_y.rotation.x >= 1.6: + $cam_y.rotation.x = 1.6 + elif $cam_y.rotation.x <= -1.6: + $cam_y.rotation.x = -1.6 + rotate(Vector3.DOWN, camera_rotation.x) func _unhandled_input(event): - if event.is_action_pressed("zoom_in") && $cam_y/Camera3D.position.z > 0: - zoom = -1 - $cam_y/Camera3D.position.z += zoom - elif event.is_action_pressed("zoom_out") && $cam_y/Camera3D.position.z <= 20: - zoom = 1 - $cam_y/Camera3D.position.z += zoom - else: - zoom = 0 + if enabled: + + if event.is_action_pressed("zoom_in") && $cam_y/Camera3D.position.z > 0: + zoom = -1 + $cam_y/Camera3D.position.z += zoom + elif event.is_action_pressed("zoom_out") && $cam_y/Camera3D.position.z <= 20: + zoom = 1 + $cam_y/Camera3D.position.z += zoom + else: + zoom = 0 diff --git a/scripts/server.gd b/scripts/server.gd new file mode 100644 index 0000000..eddc124 --- /dev/null +++ b/scripts/server.gd @@ -0,0 +1,57 @@ +extends Node + +const DEFAULT_SERVER_IP = "127.0.0.1" +const PORT = 36969 +const MAX_CONNECTIONS = 16 + +var players = {} +var players_numbered = [] +var label +var map +var character = preload("res://objects/player.tscn") + +func join_game(ip): + var peer = ENetMultiplayerPeer.new() + var error = peer.create_client(ip, PORT) + if error: + print("error") + return error + multiplayer.multiplayer_peer = peer + + +func create_game(): + var peer = ENetMultiplayerPeer.new() + var error = peer.create_server(PORT, MAX_CONNECTIONS) + if error: + print("error") + return error + multiplayer.multiplayer_peer = peer + print("done") + +@rpc("any_peer", "call_remote", "reliable") +func send_playerinfo(name, id): + if multiplayer.is_server(): + players[id] = name + label = get_tree().root.get_node("create/player_list/list") + for w in players: + label.text = str(label.text +"\n" + players[w]) + +@rpc("authority", "call_local", "reliable") +func start_game(server_players): + players = server_players + players_numbered = players.keys() + get_tree().change_scene_to_file("res://maps/base_map.tscn") + map = get_tree().root.get_node(".") + var i = 0 + for w in players: + var player = character.instantiate() + player.name = "player" + str(i) + i += 1 + player.position.z = -i*1.5 + map.add_child(player) + +@rpc("any_peer", "call_remote", "unreliable") +func sync_player(node_name, position, rotation): + var current_character = get_tree().root.get_node("./"+node_name) + current_character.position = position + current_character.rotation = rotation