diff --git a/level/Ground.gd b/level/Ground.gd deleted file mode 100644 index 55a1cc6..0000000 --- a/level/Ground.gd +++ /dev/null @@ -1,8 +0,0 @@ -extends Node3D - -func grounded(src: Player): - src._is_grounded = true - - - - diff --git a/level/level.gd b/level/level.gd index 9039f19..caea3f9 100644 --- a/level/level.gd +++ b/level/level.gd @@ -9,7 +9,6 @@ enum GameState { } var game_state: GameState = GameState.WAITING -var safe_player: Player var game_tagger: Player signal state_change(old: GameState, new: GameState) @@ -20,7 +19,7 @@ signal state_leave_tagger_ungrounded signal state_enter_tagger_change(new_tagger: Player) signal state_leave_tagger_change -const MIN_PLAYERS := 3 +const MIN_PLAYERS := 2 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!" @@ -53,7 +52,6 @@ func not_enough_players() -> bool: return false func change_to_random_tagger(): - safe_player = null game_tagger = %Players.get_children().pick_random() _change_state(GameState.TAGGER_CHANGE) @@ -68,7 +66,6 @@ func tagger_left_game(): "tagger_username": tagger_username})) func set_tagger(who: Player): - safe_player = game_tagger game_tagger = who _change_state(GameState.TAGGER_CHANGE) @@ -76,19 +73,13 @@ 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) + _change_state_full.rpc(new_state, id) @rpc("any_peer", "reliable", "call_local") -func _change_state_full(new_state: GameState, new_tagger_id: int, new_safe_player_id: int): +func _change_state_full(new_state: GameState, new_tagger_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: @@ -114,7 +105,7 @@ func _change_state_full(new_state: GameState, new_tagger_id: int, new_safe_playe 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 + return true func _ready(): # Hacky way to start level without going though multiplayer screens @@ -125,7 +116,13 @@ func _ready(): func player_ground(v: bool, player: Player): if game_tagger == player: set_tagger_grounded(v) - + +func teleport(who: Player): + if not who.is_multiplayer_authority(): + push_error("Don't have the authority to teleport") + return + who.position = Vector3.ZERO + func player_tag(who: Player, player: Player): if not tagging_possible(player, who) or game_tagger != player: return @@ -134,6 +131,7 @@ func player_tag(who: Player, player: Player): push_global_message.rpc(global_msg_4.format({ "old_tagger_username": old_tagger_username, "tagger_username": tagger_username})) + teleport(player) set_tagger(who) func start_game(): diff --git a/level/level.tscn b/level/level.tscn index a94f0b0..7cdca8c 100644 --- a/level/level.tscn +++ b/level/level.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=14 format=3 uid="uid://b00brfkibo5cj"] +[gd_scene load_steps=13 format=3 uid="uid://b00brfkibo5cj"] [ext_resource type="PackedScene" uid="uid://bq654gwim6col" path="res://level/level.glb" id="1_s37in"] [ext_resource type="Environment" uid="uid://covjrwmk4rplw" path="res://level/world_environment.tres" id="2_ptkl6"] @@ -6,7 +6,6 @@ [ext_resource type="Script" path="res://addons/smoother/smoother.gd" id="5_2tyle"] [ext_resource type="Script" path="res://level/PlayerSpawner.gd" id="6_7ww0m"] [ext_resource type="MeshLibrary" uid="uid://cgh6y5j8wgi36" path="res://level/mesh_library/level_mesh_library.glb" id="6_d34iv"] -[ext_resource type="Script" path="res://level/Ground.gd" id="8_yu1ir"] [sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_ujmev"] margin = 2.067 @@ -18,6 +17,7 @@ size = Vector3(2, 0.1, 2) size = Vector2(100, 100) [sub_resource type="BoxShape3D" id="BoxShape3D_m3lo5"] +size = Vector3(100, 100, 1) [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_285vp"] @@ -51,7 +51,7 @@ visible = false [node name="Players" type="Node3D" parent="." index="3"] unique_name_in_owner = true -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 11.4823, 12, 16.4239) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.78702, 68.686, -4.61699) [node name="PlayerSpawner" type="MultiplayerSpawner" parent="." index="4"] unique_name_in_owner = true @@ -81,7 +81,7 @@ data = { } metadata/_editor_floor_ = Vector3(0, 2, 0) -[node name="MeshInstance3D" type="MeshInstance3D" parent="." index="8"] +[node name="MeshInstance3D" type="MeshInstance3D" parent="." index="8" groups=["ground"]] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.001, 0, 0) mesh = SubResource("QuadMesh_8lqeb") skeleton = NodePath("../Cube") @@ -89,7 +89,7 @@ skeleton = NodePath("../Cube") [node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D" index="0"] [node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D" index="0"] -transform = Transform3D(100, 0, 0, 0, 100, 0, 0, 0, 1, 0, 0, -0.5) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.5) shape = SubResource("BoxShape3D_m3lo5") [node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." index="9"] @@ -107,12 +107,11 @@ layout_mode = 0 offset_right = 40.0 offset_bottom = 23.0 -[node name="Ground" type="Area3D" parent="." index="11"] +[node name="Ground" type="Area3D" parent="." index="11" groups=["ground"]] transform = Transform3D(9, 0, 0, 0, 9, 0, 0, 0, 9, 4.85232, 7.93442, -4.42363) [node name="CollisionShape3D" type="CollisionShape3D" parent="Ground" index="0"] shape = SubResource("BoxShape3D_0y3ka") -script = ExtResource("8_yu1ir") [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 48d1bbb..5a2b841 100644 --- a/player/player.gd +++ b/player/player.gd @@ -19,16 +19,15 @@ signal ground(v: bool) func _process(_delta): ground.emit(is_on_ground()) - var player := get_first_bumper() + var player := get_first_tagging() if player != null: + print("tag") 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 check_bumping(src: Player) -var _is_grounded := false -signal check_grounded +# Signals being abused as weak hashsets +# Never emit +signal player_tagging_hashset +signal ground_touching_hashset func _ready(): if username == "": @@ -36,11 +35,7 @@ func _ready(): $Sphere.set_instance_shader_parameter("color", Color.DARK_ORANGE) func is_on_ground() -> bool: - _is_grounded = false - check_grounded.emit(self) - var v := _is_grounded - _is_grounded = false - return v + return player_tagging_hashset.get_connections().size() > 0 func _physics_process(delta): @@ -59,43 +54,39 @@ func _physics_process(delta): move_and_slide() -var _first_bumper: Player = null - -func _bump_check(src: Player): - if src._first_bumper == null: - src._first_bumper = self - -func get_first_bumper() -> Player: - _first_bumper = null - check_bumping.emit(self) - var player := _first_bumper - _first_bumper = null - return player +func id(): + return self + +func get_first_tagging() -> Player: + var connections := player_tagging_hashset.get_connections() + if connections.size() == 0: + return null + return connections[0]["callable"].call() func _on_tag_detection_area_entered(area): - if not (area.get_parent() is Player): + if not (area.get_parent() is Player) or area.get_parent() == self: return - var _other_player: Player = area.get_parent() - if check_bumping.is_connected(_bump_check): + var other_player: Player = area.get_parent() + if player_tagging_hashset.is_connected(other_player.id): return - check_bumping.connect(_bump_check) + player_tagging_hashset.connect(other_player.id) func _on_tag_detection_area_exited(area): - if not (area.get_parent() is Player): + if not (area.get_parent() is Player) or area.get_parent() == self: return - var _other_player: Player = area.get_parent() - if not check_bumping.is_connected(_bump_check): + var other_player: Player = area.get_parent() + if not player_tagging_hashset.is_connected(other_player.id): return - check_bumping.disconnect(_bump_check) + player_tagging_hashset.disconnect(other_player.id) -func _on_tag_detection_body_entered(body): - if "grounded" in body: - if not check_grounded.is_connected(body.grounded): - check_grounded.connect(body.grounded) +func _on_ground_detection_node_entered(node: Node): + if node.is_in_group("ground"): + if not ground_touching_hashset.is_connected(node.get_tree): + ground_touching_hashset.connect(node.get_tree) -func _on_tag_detection_body_exited(body): - if "grounded" in body: - if check_grounded.is_connected(body.grounded): - check_grounded.disconnect(body.grounded) +func _on_ground_detection_node_exited(node: Node): + if node.is_in_group("ground"): + if ground_touching_hashset.is_connected(node.get_tree): + ground_touching_hashset.disconnect(node.get_tree) diff --git a/player/player.tscn b/player/player.tscn index f0809ec..883fbd1 100644 --- a/player/player.tscn +++ b/player/player.tscn @@ -32,7 +32,14 @@ collision_mask = 8388609 [node name="CollisionShape3D" type="CollisionShape3D" parent="TagDetection" index="0"] shape = SubResource("SphereShape3D_ylark") +[node name="GroundDetection" type="Area3D" parent="." index="4"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="GroundDetection" index="0"] +shape = SubResource("SphereShape3D_ylark") + [connection signal="area_entered" from="TagDetection" to="." method="_on_tag_detection_area_entered"] [connection signal="area_exited" from="TagDetection" to="." method="_on_tag_detection_area_exited"] -[connection signal="body_entered" from="TagDetection" to="." method="_on_tag_detection_body_entered"] -[connection signal="body_exited" from="TagDetection" to="." method="_on_tag_detection_body_exited"] +[connection signal="area_entered" from="GroundDetection" to="." method="_on_ground_detection_node_entered"] +[connection signal="area_exited" from="GroundDetection" to="." method="_on_ground_detection_node_exited"] +[connection signal="body_entered" from="GroundDetection" to="." method="_on_ground_detection_node_entered"] +[connection signal="body_exited" from="GroundDetection" to="." method="_on_ground_detection_node_exited"]