From c9652ae651e6d4f863240474b70c9f2c92d2ac1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Thu, 20 Jan 2022 16:50:44 +0100 Subject: [PATCH] Add very basic multiplayer --- menu/about.tscn | 4 +- menu/default_theme.tres | 10 ++ menu/main_menu.gd | 8 +- menu/main_menu.tscn | 49 +++--- menu/multiplayer_menu.gd | 59 +++++++ menu/multiplayer_menu.tscn | 151 ++++++++++++++++++ menu/pause_menu.gd | 2 + menu/pause_menu.tscn | 26 ++- menu/settings_menu.tscn | 8 +- menu/start_menu.tscn | 13 +- network/multiplayer_controller.gd | 121 ++++++++++++++ project.godot | 3 +- scenes/base_track_level.gd | 35 +++- .../{GlobalSettings.gd => global_settings.gd} | 0 vehicles/vehicle.gd | 27 ++++ 15 files changed, 453 insertions(+), 63 deletions(-) create mode 100644 menu/default_theme.tres create mode 100644 menu/multiplayer_menu.gd create mode 100644 menu/multiplayer_menu.tscn create mode 100644 network/multiplayer_controller.gd rename settings/{GlobalSettings.gd => global_settings.gd} (100%) diff --git a/menu/about.tscn b/menu/about.tscn index 1176839..0cb8230 100644 --- a/menu/about.tscn +++ b/menu/about.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://menu/about.gd" type="Script" id=1] [ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=2] +[ext_resource path="res://menu/default_theme.tres" type="Theme" id=3] [sub_resource type="DynamicFont" id=1] size = 48 @@ -13,6 +14,7 @@ font_data = ExtResource( 2 ) [node name="About" type="Panel"] anchor_right = 1.0 anchor_bottom = 1.0 +theme = ExtResource( 3 ) script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false diff --git a/menu/default_theme.tres b/menu/default_theme.tres new file mode 100644 index 0000000..f0b1160 --- /dev/null +++ b/menu/default_theme.tres @@ -0,0 +1,10 @@ +[gd_resource type="Theme" load_steps=3 format=2] + +[ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] + +[sub_resource type="DynamicFont" id=1] +size = 32 +font_data = ExtResource( 1 ) + +[resource] +default_font = SubResource( 1 ) diff --git a/menu/main_menu.gd b/menu/main_menu.gd index d13eaf1..6df43a8 100644 --- a/menu/main_menu.gd +++ b/menu/main_menu.gd @@ -3,13 +3,17 @@ extends Panel func _ready() -> void: # gdlint: ignore=max-line-length - $MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/StartButton.grab_focus() + $MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/SingleplayerButton.grab_focus() -func _on_StartButton_pressed() -> void: +func _on_SingleplayerButton_pressed() -> void: get_tree().change_scene("res://menu/start_menu.tscn") +func _on_MultiplayerButton_pressed() -> void: + get_tree().change_scene("res://menu/multiplayer_menu.tscn") + + func _on_ExitButton_pressed() -> void: get_tree().quit() diff --git a/menu/main_menu.tscn b/menu/main_menu.tscn index dbf97f2..f97ca41 100644 --- a/menu/main_menu.tscn +++ b/menu/main_menu.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] [ext_resource path="res://menu/main_menu.gd" type="Script" id=2] @@ -6,6 +6,7 @@ [ext_resource path="res://assets/kenneylogo.png" type="Texture" id=4] [ext_resource path="res://assets/kritaicon.png" type="Texture" id=5] [ext_resource path="res://assets/blendericon.png" type="Texture" id=6] +[ext_resource path="res://menu/default_theme.tres" type="Theme" id=7] [sub_resource type="DynamicFont" id=1] size = 64 @@ -18,6 +19,7 @@ font_data = ExtResource( 1 ) [node name="MainMenu" type="Panel"] anchor_right = 1.0 anchor_bottom = 1.0 +theme = ExtResource( 7 ) script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false @@ -63,39 +65,41 @@ __meta__ = { } [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer"] -margin_left = 398.0 -margin_top = 80.0 -margin_right = 586.0 -margin_bottom = 296.0 +margin_left = 348.0 +margin_top = 52.0 +margin_right = 636.0 +margin_bottom = 324.0 -[node name="StartButton" type="Button" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer"] -margin_right = 188.0 +[node name="SingleplayerButton" type="Button" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer"] +margin_right = 288.0 margin_bottom = 48.0 -custom_fonts/font = SubResource( 2 ) -text = "Start" +text = "Singleplayer" + +[node name="MultiplayerButton" type="Button" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer"] +margin_top = 56.0 +margin_right = 288.0 +margin_bottom = 104.0 +text = "Multiplayer" [node name="SettingsButton" type="Button" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer"] -margin_top = 56.0 -margin_right = 188.0 -margin_bottom = 104.0 -custom_fonts/font = SubResource( 2 ) +margin_top = 112.0 +margin_right = 288.0 +margin_bottom = 160.0 text = "Settings" [node name="AboutButton" type="Button" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer"] -margin_top = 112.0 -margin_right = 188.0 -margin_bottom = 160.0 -custom_fonts/font = SubResource( 2 ) +margin_top = 168.0 +margin_right = 288.0 +margin_bottom = 216.0 text = "About" __meta__ = { "_edit_use_anchors_": false } [node name="ExitButton" type="Button" parent="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer"] -margin_top = 168.0 -margin_right = 188.0 -margin_bottom = 216.0 -custom_fonts/font = SubResource( 2 ) +margin_top = 224.0 +margin_right = 288.0 +margin_bottom = 272.0 text = "Exit" [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VSplitContainer/VSplitContainer"] @@ -146,7 +150,8 @@ __meta__ = { "_edit_use_anchors_": false } -[connection signal="pressed" from="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/StartButton" to="." method="_on_StartButton_pressed"] +[connection signal="pressed" from="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/SingleplayerButton" to="." method="_on_SingleplayerButton_pressed"] +[connection signal="pressed" from="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/MultiplayerButton" to="." method="_on_MultiplayerButton_pressed"] [connection signal="pressed" from="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/SettingsButton" to="." method="_on_SettingsButton_pressed"] [connection signal="pressed" from="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/AboutButton" to="." method="_on_AboutButton_pressed"] [connection signal="pressed" from="MarginContainer/VSplitContainer/VSplitContainer/CenterContainer/VBoxContainer/ExitButton" to="." method="_on_ExitButton_pressed"] diff --git a/menu/multiplayer_menu.gd b/menu/multiplayer_menu.gd new file mode 100644 index 0000000..fa81039 --- /dev/null +++ b/menu/multiplayer_menu.gd @@ -0,0 +1,59 @@ +extends Panel + +const BUGGY = "res://vehicles/buggy.tscn" +const BEETLE = "res://vehicles/beetlecar.tscn" +const BUGMOBILE = "res://vehicles/bugmobile.tscn" +const TEST_SCENE = "res://scenes/test_level.tscn" +const INFINITE_LOOP_SCENE = "res://scenes/infinite_loop_track_level.tscn" +const ROUNDING_ERROR = "res://scenes/rounding_error_track_level.tscn" +const SCARAB = "res://scenes/scarab_track_level.tscn" +const RACE_CONDITION = "res://scenes/race_condition_track_level.tscn" +const GUI_SCENE = "res://player/gui.tscn" + +var vehicles = [BEETLE, BUGGY, BUGMOBILE] +var tracks = [INFINITE_LOOP_SCENE, ROUNDING_ERROR, RACE_CONDITION, SCARAB, TEST_SCENE] + +# gdlint: ignore=max-line-length +onready var vehicle_selector = $MarginContainer/VSplitContainer/CenterContainer/GridContainer/VehicleSelector +# gdlint: ignore=max-line-length +onready var track_selector = $MarginContainer/VSplitContainer/CenterContainer/GridContainer/TrackSelector +onready var ip = $MarginContainer/VSplitContainer/CenterContainer/GridContainer/IpBox +onready var port = $MarginContainer/VSplitContainer/CenterContainer/GridContainer/PortBox + + +func _ready() -> void: + vehicle_selector.grab_focus() + vehicle_selector.add_item("Beetlecar") + vehicle_selector.add_item("Buggy") + vehicle_selector.add_item("Bugmobile") + + track_selector.add_item("Infinite Loop") + track_selector.add_item("Rounding Error") + track_selector.add_item("Race Condition") + track_selector.add_item("Scarab") + track_selector.add_item("Testing grounds") + + +func _on_JoinButton_pressed() -> void: + if vehicle_selector.get_selected_id() < 0: + return + if track_selector.get_selected_id() < 0: + return + var vehicle = vehicles[vehicle_selector.get_selected_id()] + MultiplayerController.create_client(ip.text, int(float(port.text)), vehicle) + queue_free() + + +func _on_HostButton_pressed() -> void: + if vehicle_selector.get_selected_id() < 0: + return + if track_selector.get_selected_id() < 0: + return + var vehicle = vehicles[vehicle_selector.get_selected_id()] + var track = tracks[track_selector.get_selected_id()] + MultiplayerController.create_server(int(float(port.text)), track, vehicle) + queue_free() + + +func _on_BackButton_pressed() -> void: + get_tree().change_scene("res://menu/main_menu.tscn") diff --git a/menu/multiplayer_menu.tscn b/menu/multiplayer_menu.tscn new file mode 100644 index 0000000..889c000 --- /dev/null +++ b/menu/multiplayer_menu.tscn @@ -0,0 +1,151 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] +[ext_resource path="res://menu/multiplayer_menu.gd" type="Script" id=2] +[ext_resource path="res://menu/default_theme.tres" type="Theme" id=3] + +[sub_resource type="DynamicFont" id=3] +size = 64 +font_data = ExtResource( 1 ) + +[node name="StartMenu" type="Panel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +theme = ExtResource( 3 ) +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="MarginContainer" type="MarginContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 20.0 +margin_top = 20.0 +margin_right = -20.0 +margin_bottom = -20.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VSplitContainer" type="VSplitContainer" parent="MarginContainer"] +margin_right = 984.0 +margin_bottom = 560.0 +dragger_visibility = 1 + +[node name="HSplitContainer" type="HSplitContainer" parent="MarginContainer/VSplitContainer"] +margin_right = 984.0 +margin_bottom = 72.0 +dragger_visibility = 1 + +[node name="BackButton" type="Button" parent="MarginContainer/VSplitContainer/HSplitContainer"] +margin_right = 116.0 +margin_bottom = 72.0 +text = "Back" + +[node name="Title" type="Label" parent="MarginContainer/VSplitContainer/HSplitContainer"] +margin_left = 140.0 +margin_right = 984.0 +margin_bottom = 72.0 +custom_fonts/font = SubResource( 3 ) +text = "Multiplayer" +align = 1 +valign = 1 + +[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VSplitContainer"] +margin_top = 96.0 +margin_right = 984.0 +margin_bottom = 560.0 + +[node name="GridContainer" type="GridContainer" parent="MarginContainer/VSplitContainer/CenterContainer"] +margin_left = 199.0 +margin_top = 72.0 +margin_right = 785.0 +margin_bottom = 392.0 +custom_constants/vseparation = 16 +custom_constants/hseparation = 32 +columns = 2 + +[node name="Ip" type="Label" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_top = 10.0 +margin_right = 204.0 +margin_bottom = 46.0 +text = "IP: " +align = 2 + +[node name="IpBox" type="LineEdit" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_left = 236.0 +margin_right = 586.0 +margin_bottom = 56.0 +rect_min_size = Vector2( 350, 0 ) +text = "127.0.0.1" +align = 1 + +[node name="Port" type="Label" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_top = 82.0 +margin_right = 204.0 +margin_bottom = 118.0 +text = "Port: " +align = 2 + +[node name="PortBox" type="LineEdit" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_left = 236.0 +margin_top = 72.0 +margin_right = 586.0 +margin_bottom = 128.0 +rect_min_size = Vector2( 350, 0 ) +text = "30661" +align = 1 + +[node name="Vehicle" type="Label" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_top = 150.0 +margin_right = 204.0 +margin_bottom = 186.0 +text = "Vehicle: " +align = 2 + +[node name="VehicleSelector" type="OptionButton" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_left = 236.0 +margin_top = 144.0 +margin_right = 586.0 +margin_bottom = 192.0 +text = "Select vehicle" +align = 1 + +[node name="Track" type="Label" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_top = 214.0 +margin_right = 204.0 +margin_bottom = 250.0 +text = "Track: " +align = 2 + +[node name="TrackSelector" type="OptionButton" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_left = 236.0 +margin_top = 208.0 +margin_right = 586.0 +margin_bottom = 256.0 +text = "Select track" +align = 1 + +[node name="JoinButton" type="Button" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_top = 272.0 +margin_right = 204.0 +margin_bottom = 320.0 +text = "Join Game" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="HostButton" type="Button" parent="MarginContainer/VSplitContainer/CenterContainer/GridContainer"] +margin_left = 236.0 +margin_top = 272.0 +margin_right = 586.0 +margin_bottom = 320.0 +text = "Host Game" +__meta__ = { +"_edit_use_anchors_": false +} + +[connection signal="pressed" from="MarginContainer/VSplitContainer/HSplitContainer/BackButton" to="." method="_on_BackButton_pressed"] +[connection signal="pressed" from="MarginContainer/VSplitContainer/CenterContainer/GridContainer/JoinButton" to="." method="_on_JoinButton_pressed"] +[connection signal="pressed" from="MarginContainer/VSplitContainer/CenterContainer/GridContainer/HostButton" to="." method="_on_HostButton_pressed"] diff --git a/menu/pause_menu.gd b/menu/pause_menu.gd index a24e403..13ef641 100644 --- a/menu/pause_menu.gd +++ b/menu/pause_menu.gd @@ -18,5 +18,7 @@ func _on_ContinueButton_pressed(): func _on_ExitButton_pressed(): get_tree().paused = false + if MultiplayerController.connected: + MultiplayerController.quit() get_tree().change_scene("res://menu/main_menu.tscn") get_tree().root.get_child(get_tree().root.get_child_count() - 1).queue_free() diff --git a/menu/pause_menu.tscn b/menu/pause_menu.tscn index 08a0d8e..006ef0c 100644 --- a/menu/pause_menu.tscn +++ b/menu/pause_menu.tscn @@ -1,20 +1,15 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] +[ext_resource path="res://menu/default_theme.tres" type="Theme" id=1] [ext_resource path="res://menu/pause_menu.gd" type="Script" id=2] -[sub_resource type="DynamicFont" id=1] -font_data = ExtResource( 1 ) - -[sub_resource type="DynamicFont" id=2] -font_data = ExtResource( 1 ) - [node name="PauseMenu" type="PopupDialog"] pause_mode = 2 anchor_left = 0.25 anchor_top = 0.25 anchor_right = 0.75 anchor_bottom = 0.75 +theme = ExtResource( 1 ) script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false @@ -35,8 +30,7 @@ dragger_visibility = 1 [node name="Title" type="Label" parent="MarginContainer/VSplitContainer"] margin_right = 472.0 -margin_bottom = 18.0 -custom_fonts/font = SubResource( 1 ) +margin_bottom = 36.0 text = "Game Paused" align = 1 valign = 1 @@ -45,23 +39,21 @@ __meta__ = { } [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VSplitContainer"] -margin_top = 42.0 +margin_top = 60.0 margin_right = 472.0 margin_bottom = 260.0 alignment = 1 [node name="ContinueButton" type="Button" parent="MarginContainer/VSplitContainer/VBoxContainer"] -margin_top = 89.0 +margin_top = 48.0 margin_right = 472.0 -margin_bottom = 113.0 -custom_fonts/font = SubResource( 2 ) +margin_bottom = 96.0 text = "Continue" [node name="ExitButton" type="Button" parent="MarginContainer/VSplitContainer/VBoxContainer"] -margin_top = 117.0 +margin_top = 104.0 margin_right = 472.0 -margin_bottom = 141.0 -custom_fonts/font = SubResource( 2 ) +margin_bottom = 152.0 text = "Exit to main menu" [connection signal="pressed" from="MarginContainer/VSplitContainer/VBoxContainer/ContinueButton" to="." method="_on_ContinueButton_pressed"] diff --git a/menu/settings_menu.tscn b/menu/settings_menu.tscn index 1cedd69..1bc91fc 100644 --- a/menu/settings_menu.tscn +++ b/menu/settings_menu.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=8 format=2] [ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] [ext_resource path="res://menu/settings_menu.gd" type="Script" id=2] +[ext_resource path="res://menu/default_theme.tres" type="Theme" id=3] [sub_resource type="DynamicFont" id=1] size = 64 @@ -20,6 +21,7 @@ font_data = ExtResource( 1 ) [node name="SettingsMenu" type="Panel"] anchor_right = 1.0 anchor_bottom = 1.0 +theme = ExtResource( 3 ) script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false @@ -44,12 +46,12 @@ margin_bottom = 72.0 dragger_visibility = 1 [node name="BackButton" type="Button" parent="MarginContainer/VSplitContainer/HSplitContainer"] -margin_right = 75.0 +margin_right = 116.0 margin_bottom = 72.0 text = "Back" [node name="Title" type="Label" parent="MarginContainer/VSplitContainer/HSplitContainer"] -margin_left = 99.0 +margin_left = 140.0 margin_right = 984.0 margin_bottom = 72.0 custom_fonts/font = SubResource( 1 ) diff --git a/menu/start_menu.tscn b/menu/start_menu.tscn index 40682cf..c4d061e 100644 --- a/menu/start_menu.tscn +++ b/menu/start_menu.tscn @@ -2,18 +2,16 @@ [ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] [ext_resource path="res://menu/start_menu.gd" type="Script" id=2] +[ext_resource path="res://menu/default_theme.tres" type="Theme" id=3] [sub_resource type="DynamicFont" id=1] size = 64 font_data = ExtResource( 1 ) -[sub_resource type="DynamicFont" id=2] -size = 32 -font_data = ExtResource( 1 ) - [node name="StartMenu" type="Panel"] anchor_right = 1.0 anchor_bottom = 1.0 +theme = ExtResource( 3 ) script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false @@ -41,12 +39,12 @@ margin_bottom = 72.0 dragger_visibility = 1 [node name="BackButton" type="Button" parent="MarginContainer/VSplitContainer/HSplitContainer"] -margin_right = 75.0 +margin_right = 116.0 margin_bottom = 72.0 text = "Back" [node name="Title" type="Label" parent="MarginContainer/VSplitContainer/HSplitContainer"] -margin_left = 99.0 +margin_left = 140.0 margin_right = 984.0 margin_bottom = 72.0 custom_fonts/font = SubResource( 1 ) @@ -68,7 +66,6 @@ margin_bottom = 312.0 [node name="VehicleSelector" type="OptionButton" parent="MarginContainer/VSplitContainer/CenterContainer/VBoxContainer"] margin_right = 349.0 margin_bottom = 48.0 -custom_fonts/font = SubResource( 2 ) text = "Select vehicle" align = 1 @@ -76,7 +73,6 @@ align = 1 margin_top = 56.0 margin_right = 349.0 margin_bottom = 104.0 -custom_fonts/font = SubResource( 2 ) text = "Select Track" align = 1 __meta__ = { @@ -87,7 +83,6 @@ __meta__ = { margin_top = 112.0 margin_right = 349.0 margin_bottom = 160.0 -custom_fonts/font = SubResource( 2 ) text = "Start" __meta__ = { "_edit_use_anchors_": false diff --git a/network/multiplayer_controller.gd b/network/multiplayer_controller.gd new file mode 100644 index 0000000..d0ba5e0 --- /dev/null +++ b/network/multiplayer_controller.gd @@ -0,0 +1,121 @@ +extends Node + +const GUI_SCENE = "res://player/gui.tscn" + +var enet_peer = NetworkedMultiplayerENet.new() +var peers = {} +var peers_vehicles = {} + +var current_track: Node = null +var current_track_path: String +var current_vehicle: String +var connected = false + + +func _ready(): + enet_peer.connect("peer_connected", self, "_peer_connected") + enet_peer.connect("peer_disconnected", self, "_peer_disconnected") + get_tree().connect("connected_to_server", self, "_connected_to_server") + enet_peer.connect("server_disconnected", self, "_server_disconnected") + get_tree().connect("connection_failed", self, "_connection_failed") + + +func create_server(port, track, vehicle): + current_track_path = track + current_track = load(track).instance() + current_vehicle = vehicle + enet_peer.create_server(port, 2) + get_tree().network_peer = enet_peer + peers[1] = true + create_player(1, vehicle) + get_tree().root.call_deferred("add_child", current_track) + connected = true + + +func create_client(address, port, vehicle): + current_vehicle = vehicle + peers[get_tree().get_network_unique_id()] = true + enet_peer.create_client(address, port) + get_tree().network_peer = enet_peer + + +func _peer_connected(peer_id): + print("_peer_connected(%s)" % peer_id) + peers[peer_id] = false + rpc_id(peer_id, "add_player", get_tree().get_network_unique_id(), current_vehicle) + if get_tree().get_network_unique_id() == 1: + rpc_id(peer_id, "select_track", current_track_path) + + +func _peer_disconnected(peer_id): + print("_peer_disconnected(%s)" % peer_id) + peers.erase(peer_id) + destroy_player(peer_id) + print("new peers state: %s" % peers) + + +func _connected_to_server(): + print("_connected_to_server") + connected = true + + +func _connection_failed(): + connected = false + current_track = null + peers_vehicles.clear() + _server_disconnected() + + +func _server_disconnected(): + connected = false + current_track = null + peers.clear() + peers_vehicles.clear() + get_tree().root.get_child(get_tree().root.get_child_count() - 1).queue_free() + get_tree().change_scene("res://menu/main_menu.tscn") + + +func create_player(peer_id, vehicle_path): + var vehicle = load(vehicle_path).instance() + var gui + if peer_id == get_tree().get_network_unique_id(): + gui = load(GUI_SCENE).instance() + vehicle.connect("speed_updated", gui, "update_speed") + vehicle.connect("rpm_updated", gui, "update_rpm") + vehicle.connect("gear_updated", gui, "update_gear") + vehicle.set_network_master(peer_id) + vehicle.name = String(peer_id) + if peer_id == get_tree().get_network_unique_id(): + current_track.call_deferred("spawn_player", vehicle, gui) + else: + current_track.call_deferred("spawn_vehicle", vehicle) + + +func destroy_player(peer_id): + current_track.remove_player(String(peer_id)) + + +func quit(): + enet_peer.close_connection() + connected = false + current_track = null + peers.clear() + peers_vehicles.clear() + + +remote func add_player(peer_id, vehicle_path): + if peers[peer_id] == false: + peers[peer_id] = true + if current_track != null: + create_player(peer_id, vehicle_path) + else: + peers_vehicles[peer_id] = vehicle_path + + +remote func select_track(track_path): + current_track = load(track_path).instance() + get_tree().root.call_deferred("add_child", current_track) + create_player(get_tree().get_network_unique_id(), current_vehicle) + for peer in peers_vehicles: + create_player(peer, peers_vehicles[peer]) + peers_vehicles.clear() diff --git a/project.godot b/project.godot index 2d9fe61..3140465 100644 --- a/project.godot +++ b/project.godot @@ -57,7 +57,8 @@ config/icon="res://icon.png" [autoload] -GlobalSettings="*res://settings/GlobalSettings.gd" +GlobalSettings="*res://settings/global_settings.gd" +MultiplayerController="*res://network/multiplayer_controller.gd" [editor_plugins] diff --git a/scenes/base_track_level.gd b/scenes/base_track_level.gd index 41cd8ea..d938664 100644 --- a/scenes/base_track_level.gd +++ b/scenes/base_track_level.gd @@ -8,25 +8,32 @@ var player_node: BuggedVehicle var gui: Node var camera_controller: CameraController var player_controller: PlayerVehicleController +var ready = false onready var track = $Track func _ready() -> void: - reset_player_to(track.get_furthest_checkpoint(), player_node) - add_child(player_node) - add_child(gui) - player_controller = PLAYER_CONTROLLER.new() - player_controller.vehicle_path = player_node.get_path() - player_node.add_child(player_controller) - camera_controller = CAMERA_CONTROLLER.new() - camera_controller.attach_cameras_to(player_node) + if player_node != null: + _spawn_in_player() + ready = true func spawn_player(player_node: BuggedVehicle, gui: Node) -> void: self.player_node = player_node self.player_node.add_child(player_controller) self.gui = gui + if ready: + _spawn_in_player() + + +func spawn_vehicle(vehicle: BuggedVehicle) -> void: + reset_player_to(track.get_furthest_checkpoint(), vehicle) + add_child(vehicle) + + +func remove_player(peer_id: String) -> void: + get_node(peer_id).queue_free() func reset_player_to(node_to_reset_to: Node, player_node: BuggedVehicle) -> void: @@ -39,6 +46,18 @@ func reset_player_to(node_to_reset_to: Node, player_node: BuggedVehicle) -> void player_node.reset_transform.origin += node_to_reset_to.global_transform.basis.y * 3 +func _spawn_in_player(): + print("SPAWNING IN PLAYER") + reset_player_to(track.get_furthest_checkpoint(), player_node) + add_child(player_node) + add_child(gui) + player_controller = PLAYER_CONTROLLER.new() + player_controller.vehicle_path = player_node.get_path() + player_node.add_child(player_controller) + camera_controller = CAMERA_CONTROLLER.new() + camera_controller.attach_cameras_to(player_node) + + func _process(_delta: float) -> void: if Input.is_action_just_released("reset_vehicle"): reset_player_to(track.get_furthest_checkpoint(), player_node) diff --git a/settings/GlobalSettings.gd b/settings/global_settings.gd similarity index 100% rename from settings/GlobalSettings.gd rename to settings/global_settings.gd diff --git a/vehicles/vehicle.gd b/vehicles/vehicle.gd index 5a1bfac..0892d25 100644 --- a/vehicles/vehicle.gd +++ b/vehicles/vehicle.gd @@ -74,6 +74,17 @@ class VehicleInputs: # Left is positive, right is negative var steering = 0.0 + func to_array() -> Array: + return [gear_request, clutch, throttle, brake, handbrake, steering] + + func from_array(array: Array) -> void: + gear_request = array[0] + clutch = array[1] + throttle = array[2] + brake = array[3] + handbrake = array[4] + steering = array[5] + func _ready(): for wheel in [frwheel, flwheel, rrwheel, rlwheel]: @@ -245,6 +256,9 @@ func _physics_process(delta: float): steering = steering_input * lerp(max_steer_angle_rad, speed_steer_angle_rad, steer_speed_factor) emit_signal("steering_updated", steering, steering / max_steer_angle_rad) + if get_network_master() == get_tree().get_network_unique_id(): + _synchronize() + func _generate_engine_sound(rpm_factor): engine_sound_player.pitch_scale = base_engine_pitch + 2 * rpm_factor @@ -264,3 +278,16 @@ func _generate_engine_sound(rpm_factor): ) to_fill -= 1 fill_percent += fill_segment + + +func _synchronize(): + rpc("sync_position", transform) + rpc("sync_inputs", inputs.to_array()) + + +remote func sync_position(position: Transform): + reset_transform = position + + +remote func sync_inputs(remote_inputs): + inputs.from_array(remote_inputs)