feat: Implement the main game scene, initializing core managers, a new message bar system, and a pre-game countdown.
This commit is contained in:
+20
-4
@@ -1575,12 +1575,12 @@ func request_randomize_item(grid_position: Vector2i):
|
||||
func sync_grid_item(x: int, y: int, z: int, item: int):
|
||||
var enhanced_gridmap = $EnhancedGridMap
|
||||
if enhanced_gridmap:
|
||||
# WALL-SAFETY CHECK: Block tiles (7-20) from being placed on walls (4)
|
||||
# WALL-SAFETY CHECK: Block tiles (7-20) from being placed on walls (4) or void (-1)
|
||||
if y == 1 and item >= 7 and item <= 20:
|
||||
var f0 = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z))
|
||||
if f0 == 4:
|
||||
if f0 == 4 or f0 == -1:
|
||||
# Log and block illegal placement
|
||||
print("[Main] Blocked illegal tile (%d) placement on wall at (%d, %d)" % [item, x, z])
|
||||
print("[Main] Blocked illegal tile (%d) placement on wall/void at (%d, %d)" % [item, x, z])
|
||||
return
|
||||
|
||||
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
|
||||
@@ -1909,7 +1909,7 @@ func _show_game_over_panel():
|
||||
var rank_colors = [
|
||||
Color(1.0, 0.84, 0.0), # Gold
|
||||
Color(0.75, 0.75, 0.75), # Silver
|
||||
Color(0.8, 0.5, 0.2) # Bronze
|
||||
Color(0.8, 0.5, 0.2) # Bronze
|
||||
]
|
||||
var rank_emojis = ["🥇", "🥈", "🥉"]
|
||||
|
||||
@@ -2217,6 +2217,22 @@ func _on_resume_pressed():
|
||||
pause_menu.visible = false
|
||||
get_tree().paused = false
|
||||
|
||||
func _on_how_to_play_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
var help_panel = get_node_or_null("HowToPlayPanel")
|
||||
if pause_menu:
|
||||
pause_menu.visible = false
|
||||
if help_panel:
|
||||
help_panel.visible = true
|
||||
|
||||
func _on_how_to_play_back_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
var help_panel = get_node_or_null("HowToPlayPanel")
|
||||
if help_panel:
|
||||
help_panel.visible = false
|
||||
if pause_menu:
|
||||
pause_menu.visible = true
|
||||
|
||||
func _on_settings_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
var settings_panel = get_node_or_null("SettingsPanel")
|
||||
|
||||
@@ -9923,6 +9923,11 @@ custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
text = "Resume"
|
||||
|
||||
[node name="HowToPlayBtn" type="Button" parent="PauseMenu/Panel/VBox" unique_id=987654321]
|
||||
custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
text = "How to Play"
|
||||
|
||||
[node name="SettingsBtn" type="Button" parent="PauseMenu/Panel/VBox" unique_id=215865401]
|
||||
custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
@@ -9933,6 +9938,187 @@ custom_minimum_size = Vector2(200, 45)
|
||||
layout_mode = 2
|
||||
text = "Quit Match"
|
||||
|
||||
[node name="HowToPlayPanel" type="CanvasLayer" parent="." unique_id=123456789]
|
||||
process_mode = 3
|
||||
layer = 11
|
||||
visible = false
|
||||
|
||||
[node name="Background" type="ColorRect" parent="HowToPlayPanel" unique_id=123456790]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0, 0, 0, 0.8)
|
||||
|
||||
[node name="Panel" type="PanelContainer" parent="HowToPlayPanel" unique_id=123456791]
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = -250.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 250.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="HowToPlayPanel/Panel" unique_id=123456792]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
alignment = 1
|
||||
|
||||
[node name="Title" type="Label" parent="HowToPlayPanel/Panel/VBox" unique_id=123456793]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 22
|
||||
text = "How to Play"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="HowToPlayPanel/Panel/VBox" unique_id=123456794]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Free Mode" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456795]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Free Mode" unique_id=123456796]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]Free Mode[/b]
|
||||
|
||||
- Move around the grid and attack Tektons to spawn tiles.
|
||||
- Grab tiles and use the [b]ARRANGE[/b] action to slot them into your player board.
|
||||
- Match a 3x3 pattern shown in your [b]GOALS[/b] to score points and earn powerups.
|
||||
- The player with the highest score when the global match timer ends wins!"
|
||||
|
||||
[node name="Stop n Go" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456797]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Stop n Go" unique_id=123456798]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]Stop n Go[/b]
|
||||
|
||||
- The classic red light, green light experience.
|
||||
- Move forward when the phase is [color=green][b]GO[/b][/color] (Green).
|
||||
- Stop completely when the phase is [color=red][b]STOP[/b][/color] (Red). Moving during a red phase will reset you to the start!
|
||||
- Your objective is to reach the mission tiles at the far end of the arena and safely carry them back to your starting zone.
|
||||
- The first player to complete 3 missions wins."
|
||||
|
||||
[node name="Tekton Doors" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456799]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Tekton Doors" unique_id=123456800]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]Tekton Doors[/b]
|
||||
|
||||
- Navigate a sprawling arena connected by color-coded portal doors.
|
||||
- Grab tiles and match goal patterns to earn mission completions.
|
||||
- Use doors to quickly teleport across rooms, but watch out for closures and traps.
|
||||
- The first player to complete 8 missions wins."
|
||||
|
||||
[node name="Controls" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456805]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Controls" unique_id=123456806]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]Basic Controls[/b]
|
||||
|
||||
• [b]Movement:[/b] W/A/S/D, Arrow Keys, or Virtual Joystick.
|
||||
• [b]Interact:[/b] Click or tap on game elements.
|
||||
• [b]ATTACK:[/b] Strike an adjacent Tekton to make it drop items.
|
||||
• [b]GRAB:[/b] Pick up a nearby tile.
|
||||
• [b]ARRANGE:[/b] Insert a carried tile into your 3x3 Player Board.
|
||||
• [b]THROW:[/b] Toss a carried item away.
|
||||
• [b]KNOCK:[/b] Stun a Tekton temporarily."
|
||||
|
||||
[node name="The Grid" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456807]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/The Grid" unique_id=123456808]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]The Grid & Tiles[/b]
|
||||
|
||||
• The arena is built on a grid. You interact with objects positioned on these grid coordinates.
|
||||
• [b]Tiles:[/b] Core items shaped like Hearts, Diamonds, Stars, and Coins.
|
||||
• [b]Player Board:[/b] A 3x3 grid assigned to you.
|
||||
• [b]Goals:[/b] To score points or progress, you must pick up Tiles and ARRANGE them on your Player Board to match the 3x3 pattern shown in your Goals Window. Matching grants points or mission progression!"
|
||||
|
||||
[node name="Tektons" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456809]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Tektons" unique_id=123456810]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]Tektons[/b]
|
||||
|
||||
• [b]Dynamic Tektons:[/b] Roaming metallic entities. [color=orange]ATTACK[/color] them to force them to drop a valuable Tile.
|
||||
• [b]Static Tektons:[/b] Stationary sentry turrets that occupy a large 3x3 space. They periodically throw tiles and obstacles around themselves. Stay alert when navigating near them!"
|
||||
|
||||
[node name="Skills" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456811]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Skills" unique_id=123456812]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "[b]Skills & Power-ups[/b]
|
||||
|
||||
Earn powerups by matching Goal tiles (in Free Mode and Tekton Doors) or finding them in the arena.
|
||||
|
||||
• [color=yellow][b]Speed Boost:[/b][/color] Gain a temporary burst of movement speed.
|
||||
• [color=gray][b]Wall Build:[/b][/color] Place a temporary wall to block enemies or safely trap other players.
|
||||
• [color=aqua][b]Freeze Area:[/b][/color] Create a frozen zone on the grid that freezes anyone who steps on it.
|
||||
• [color=purple][b]Ghost Mode:[/b][/color] Become temporarily invisible and invincible, allowing you to phase past blockades and opponents safely.
|
||||
|
||||
[i]*Note: In Stop n Go, focus primarily on movement and avoiding the Red phase![/i]"
|
||||
|
||||
[node name="Spacer" type="Control" parent="HowToPlayPanel/Panel/VBox" unique_id=123456801]
|
||||
custom_minimum_size = Vector2(0, 10)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="BackBtn" type="Button" parent="HowToPlayPanel/Panel/VBox" unique_id=123456802]
|
||||
custom_minimum_size = Vector2(0, 40)
|
||||
layout_mode = 2
|
||||
text = "Back"
|
||||
|
||||
[node name="SettingsPanel" type="CanvasLayer" parent="." unique_id=268064562]
|
||||
process_mode = 3
|
||||
layer = 11
|
||||
@@ -10027,8 +10213,10 @@ text = "Back"
|
||||
[connection signal="pressed" from="Menu/Join" to="." method="_on_join_pressed"]
|
||||
[connection signal="text_submitted" from="MessageInput" to="." method="_on_message_input_text_submitted"]
|
||||
[connection signal="pressed" from="PauseMenu/Panel/VBox/ResumeBtn" to="." method="_on_resume_pressed"]
|
||||
[connection signal="pressed" from="PauseMenu/Panel/VBox/HowToPlayBtn" to="." method="_on_how_to_play_pressed"]
|
||||
[connection signal="pressed" from="PauseMenu/Panel/VBox/SettingsBtn" to="." method="_on_settings_pressed"]
|
||||
[connection signal="pressed" from="PauseMenu/Panel/VBox/QuitBtn" to="." method="_on_quit_match_pressed"]
|
||||
[connection signal="pressed" from="HowToPlayPanel/Panel/VBox/BackBtn" to="." method="_on_how_to_play_back_pressed"]
|
||||
[connection signal="value_changed" from="SettingsPanel/Panel/VBox/ButtonSizeRow/ButtonSizeSlider" to="." method="_on_button_size_changed"]
|
||||
[connection signal="value_changed" from="SettingsPanel/Panel/VBox/OpacityRow/OpacitySlider" to="." method="_on_opacity_changed"]
|
||||
[connection signal="toggled" from="SettingsPanel/Panel/VBox/JoystickToggle" to="." method="_on_joystick_toggled"]
|
||||
|
||||
@@ -408,6 +408,11 @@ func _randomize_tiles_around_player(player: Node):
|
||||
# Check if position is valid
|
||||
if not enhanced_gridmap.is_position_valid(pos):
|
||||
continue
|
||||
|
||||
# EXTRA CHECK: Do not spawn tiles on void (-1) or walls (4) on Floor 0
|
||||
var floor_0_item = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
||||
if floor_0_item == -1 or floor_0_item == 4:
|
||||
continue
|
||||
|
||||
# Check if there are tiles nearby or if empty
|
||||
var current_item = enhanced_gridmap.get_cell_item(cell)
|
||||
|
||||
@@ -11,11 +11,15 @@ extends StaticBody3D
|
||||
|
||||
func _ready():
|
||||
add_to_group("StaticTektonStands")
|
||||
print("Static Stand Ready: ", name)
|
||||
print("Static Stand Ready: ", name)
|
||||
|
||||
# Clear 3x3 local GridMap void for late joiners
|
||||
call_deferred("_clear_local_gridmap_area")
|
||||
|
||||
if multiplayer.is_server():
|
||||
# Only randomize if not already set (Main.gd sets it now)
|
||||
if shape_index == -1:
|
||||
shape_index = randi() % 4
|
||||
shape_index = randi() % 4
|
||||
_update_mesh_from_index()
|
||||
else:
|
||||
# Client side:
|
||||
@@ -27,6 +31,29 @@ func _ready():
|
||||
# But just in case, we can try to request it or use a default
|
||||
pass
|
||||
|
||||
func _clear_local_gridmap_area():
|
||||
var main = get_tree().get_root().get_node_or_null("Main")
|
||||
if not main: return
|
||||
var gridmap = main.get_node_or_null("EnhancedGridMap")
|
||||
if not gridmap or not "cell_size" in gridmap: return
|
||||
|
||||
var grid_x = int(round((global_position.x - gridmap.cell_size.x / 2.0) / gridmap.cell_size.x))
|
||||
var grid_z = int(round((global_position.z - gridmap.cell_size.z / 2.0) / gridmap.cell_size.z))
|
||||
|
||||
var floor_count = 3
|
||||
if "floors" in gridmap: floor_count = gridmap.floors
|
||||
|
||||
for dx in range(-1, 2):
|
||||
for dy in range(-1, 2):
|
||||
for f in range(floor_count):
|
||||
gridmap.set_cell_item(Vector3i(grid_x + dx, f, grid_z + dy), -1)
|
||||
|
||||
# Force pathfinding update if methods exist
|
||||
if gridmap.has_method("update_grid_data"):
|
||||
gridmap.update_grid_data()
|
||||
if gridmap.has_method("update_astar_costs"):
|
||||
gridmap.update_astar_costs()
|
||||
|
||||
func _update_mesh_from_index():
|
||||
if not mesh_instance: return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user