From c3e507301121b3f38f8a982db3a4a68e3afab39d Mon Sep 17 00:00:00 2001 From: Spencer Killen Date: Mon, 3 Jun 2024 11:05:52 -0600 Subject: [PATCH] broken ass code' --- camera/PersonalUI.gd | 19 +++++++++ camera/camera.tscn | 26 ++++++++++++- level/PlayerSpawner.gd | 4 +- level/level.gd | 87 ++++++++++++++++++++++++++++++++++++------ level/level.tscn | 7 ++-- player/player.gd | 35 +++++++++++------ 6 files changed, 150 insertions(+), 28 deletions(-) create mode 100644 camera/PersonalUI.gd diff --git a/camera/PersonalUI.gd b/camera/PersonalUI.gd new file mode 100644 index 0000000..8f08033 --- /dev/null +++ b/camera/PersonalUI.gd @@ -0,0 +1,19 @@ +extends Control + +@onready var level := Level.find_level(self) + +const personal_msg_1 := "You're not it, run!" +const personal_msg_2 := "You're it, run!" + +func get_player() -> Player: + return owner.get_parent() + +func _ready(): + level.state_enter_tagger_change.connect(tagger_change) + +func tagger_change(next: Player): + if get_player() == next: + $Label.text = personal_msg_2 + else: + $Label.text = personal_msg_1 + diff --git a/camera/camera.tscn b/camera/camera.tscn index d9c9204..3b4dea1 100644 --- a/camera/camera.tscn +++ b/camera/camera.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://brgqf2ebuyhuy"] +[gd_scene load_steps=4 format=3 uid="uid://brgqf2ebuyhuy"] [ext_resource type="Script" path="res://camera/camera.gd" id="1_veqr4"] +[ext_resource type="Script" path="res://camera/PersonalUI.gd" id="2_u54jc"] [sub_resource type="SphereShape3D" id="SphereShape3D_5lewf"] @@ -16,3 +17,26 @@ margin = 0.5 [node name="Camera3D" type="Camera3D" parent="SpringArm3D"] unique_name_in_owner = true + +[node name="PersonalUI" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -126.0 +grow_horizontal = 2 +grow_vertical = 0 +size_flags_vertical = 8 +script = ExtResource("2_u54jc") + +[node name="Label" type="Label" parent="PersonalUI"] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -20.0 +offset_right = 20.0 +offset_bottom = 23.0 +grow_horizontal = 2 +theme_override_colors/font_color = Color(1, 0, 0, 1) diff --git a/level/PlayerSpawner.gd b/level/PlayerSpawner.gd index 4d2b973..fc49a73 100644 --- a/level/PlayerSpawner.gd +++ b/level/PlayerSpawner.gd @@ -14,4 +14,6 @@ func spawn_player(owner_id: int): return player func despawn_player(owner_id: int): - get_node(spawn_path).get_node(str(owner_id)).queue_free() + var node := get_node(spawn_path).get_node(str(owner_id)) + node.queue_free() + await node.tree_exited diff --git a/level/level.gd b/level/level.gd index a4681e5..9039f19 100644 --- a/level/level.gd +++ b/level/level.gd @@ -9,6 +9,7 @@ enum GameState { } var game_state: GameState = GameState.WAITING +var safe_player: Player var game_tagger: Player signal state_change(old: GameState, new: GameState) @@ -19,13 +20,18 @@ signal state_leave_tagger_ungrounded signal state_enter_tagger_change(new_tagger: Player) signal state_leave_tagger_change -const MIN_PLAYERS := 2 +const MIN_PLAYERS := 3 const global_msg_1 := "Waiting for at least {min_players} players to join" const global_msg_2 := "Game is starting soon, {tagger_username} is it!" const global_msg_3 := "{tagger_username} is it! Run!" const global_msg_4 := "{old_tagger_username} caught {tagger_username}!" const global_msg_5 := "{old_tagger_username} left. {tagger_username} is now it!" +@rpc("any_peer", "reliable", "call_local") +func push_global_message(msg: String): + %GlobalMessage.text = msg + print(msg) + func set_tagger_grounded(v: bool): if v and game_state == GameState.TAGGER_CHANGE: _change_state(GameState.TAGGER_GROUNDED) @@ -40,12 +46,14 @@ func set_tagger_grounded(v: bool): func not_enough_players() -> bool: if %Players.get_children().size() < MIN_PLAYERS: + game_tagger = null _change_state(GameState.WAITING) - %GlobalMessage.text = global_msg_1.format({"min_players": MIN_PLAYERS}) + push_global_message.rpc(global_msg_1.format({"min_players": MIN_PLAYERS})) return true return false func change_to_random_tagger(): + safe_player = null game_tagger = %Players.get_children().pick_random() _change_state(GameState.TAGGER_CHANGE) @@ -55,19 +63,32 @@ func tagger_left_game(): var old_tagger_username := game_tagger.username change_to_random_tagger() var tagger_username := game_tagger.username - %GlobalMessage.text = global_msg_5.format({ + push_global_message.rpc(global_msg_5.format({ "old_tagger_username": old_tagger_username, - "tagger_username": tagger_username}) + "tagger_username": tagger_username})) func set_tagger(who: Player): - if game_state == GameState.WAITING: - return - game_tagger.tree_exiting.disconnect(tagger_left_game) - who.tree_exiting.connect(tagger_left_game) + safe_player = game_tagger game_tagger = who _change_state(GameState.TAGGER_CHANGE) func _change_state(new_state: GameState): + var id := -1 + if game_tagger != null: + id = game_tagger.get_multiplayer_authority() + var safe_player_id := -1 + if safe_player != null: + safe_player_id = safe_player.get_multiplayer_authority() + _change_state_full.rpc(new_state, id, safe_player_id) + +@rpc("any_peer", "reliable", "call_local") +func _change_state_full(new_state: GameState, new_tagger_id: int, new_safe_player_id: int): + game_tagger = null + safe_player = null + if new_tagger_id != -1: + game_tagger = find_player_by_id(new_tagger_id) + if new_safe_player_id != -1: + safe_player = find_player_by_id(new_safe_player_id) if game_state == new_state: return if new_state == GameState.WAITING: @@ -89,22 +110,66 @@ func _change_state(new_state: GameState): state_leave_tagger_ungrounded.emit() if old_state == GameState.TAGGER_CHANGE: state_leave_tagger_change.emit() - +func tagging_possible(_tagger: Player, tagee: Player) -> bool: + if game_state != GameState.TAGGER_GROUNDED and game_state != GameState.TAGGER_UNGROUNDED: + return false + return safe_player != tagee func _ready(): # Hacky way to start level without going though multiplayer screens if get_parent() == get_tree().root: %PlayerSpawner.spawn(multiplayer.get_unique_id()) + +func player_ground(v: bool, player: Player): + if game_tagger == player: + set_tagger_grounded(v) + +func player_tag(who: Player, player: Player): + if not tagging_possible(player, who) or game_tagger != player: + return + var old_tagger_username := game_tagger.username + var tagger_username := player.username + push_global_message.rpc(global_msg_4.format({ + "old_tagger_username": old_tagger_username, + "tagger_username": tagger_username})) + set_tagger(who) + +func start_game(): + change_to_random_tagger() + push_global_message.rpc(global_msg_3.format({"tagger_username" : game_tagger.username})) + # Called from the server func server_add_player(id: int): %PlayerSpawner.spawn(id) - + if not not_enough_players() and game_state == GameState.WAITING: + start_game() + + func server_remove_player(id: int): - %PlayerSpawner.despawn_player(id) + var player := find_player_by_id(id) + var tagger_left := (game_tagger == player) + await %PlayerSpawner.despawn_player(id) + if not_enough_players(): + return + if tagger_left: + tagger_left_game() + +func client_add_player(player: Player): + if not player.is_multiplayer_authority(): + return + player.ground.connect(player_ground.bind(player)) + player.tag.connect(player_tag.bind(player)) + + +func client_remove_player(_node): + pass static func find_level(node: Node) -> Level: while not (node is Level): node = node.get_parent() return node + +func find_player_by_id(id: int) -> Player: + return %Players.get_node(str(id)) diff --git a/level/level.tscn b/level/level.tscn index 0b01d8d..2d5abbd 100644 --- a/level/level.tscn +++ b/level/level.tscn @@ -15,9 +15,6 @@ size = Vector2(100, 100) size = Vector3(100, 100, 1) [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_285vp"] -properties/0/path = NodePath("SharedUI/SharedMessage:text") -properties/0/spawn = true -properties/0/replication_mode = 1 [node name="level" instance=ExtResource("1_s37in")] script = ExtResource("2_s1bx6") @@ -92,8 +89,12 @@ unique_name_in_owner = true layout_mode = 2 offset_right = 1152.0 offset_bottom = 23.0 +theme_override_colors/font_color = Color(1, 0, 0, 1) text = "Waiting for at least 2 players to join" horizontal_alignment = 1 [node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." index="10"] replication_config = SubResource("SceneReplicationConfig_285vp") + +[connection signal="despawned" from="PlayerSpawner" to="." method="client_remove_player"] +[connection signal="spawned" from="PlayerSpawner" to="." method="client_add_player"] diff --git a/player/player.gd b/player/player.gd index 8804a99..98ad7ca 100644 --- a/player/player.gd +++ b/player/player.gd @@ -12,12 +12,23 @@ var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") # Set by camera child, switch to signals if becomes too spaghetti var movement_dir: Vector2 = Vector2.ZERO + +# Signals fire continously every frame they're true +signal tag(player: Player) +signal ground(v: bool) + +func _process(_delta): + ground.emit(is_on_ground()) + var player := get_first_bumper() + if player != null: + tag.emit(player) + # Using signals to maintain a list of currently colliding players because it simplifies # Memory management substantially since nodes are not GC'd # Connected nodes are the colliding nodes -signal is_bumping(src: Player) +signal check_bumping(src: Player) var _is_grounded := false -signal is_grounded +signal check_grounded func _ready(): if username == "": @@ -25,7 +36,7 @@ func _ready(): func is_on_ground() -> bool: _is_grounded = false - is_grounded.emit(self) + check_grounded.emit(self) var v := _is_grounded _is_grounded = false return v @@ -55,7 +66,7 @@ func _bump_check(src: Player): func get_first_bumper() -> Player: _first_bumper = null - is_bumping.emit(self) + check_bumping.emit(self) var player := _first_bumper _first_bumper = null return player @@ -64,26 +75,26 @@ func _on_tag_detection_area_entered(area): if not (area.get_parent() is Player): return var _other_player: Player = area.get_parent() - if is_bumping.is_connected(_bump_check): + if check_bumping.is_connected(_bump_check): return - is_bumping.connect(_bump_check) + check_bumping.connect(_bump_check) func _on_tag_detection_area_exited(area): if not (area.get_parent() is Player): return var _other_player: Player = area.get_parent() - if not is_bumping.is_connected(_bump_check): + if not check_bumping.is_connected(_bump_check): return - is_bumping.disconnect(_bump_check) + check_bumping.disconnect(_bump_check) func _on_tag_detection_body_entered(body): if "grounded" in body: - if not is_grounded.is_connected(body.grounded): - is_grounded.connect(body.grounded) + if not check_grounded.is_connected(body.grounded): + check_grounded.connect(body.grounded) func _on_tag_detection_body_exited(body): if "grounded" in body: - if is_grounded.is_connected(body.grounded): - is_grounded.disconnect(body.grounded) + if check_grounded.is_connected(body.grounded): + check_grounded.disconnect(body.grounded)