Files
client/spacewar/menu/server_browser.gd
T
anekdotin 0c2628a1a6 Reorganize project into autoload/, menu/, ships/, world/, assets/
Move flat top-level files into topic folders and rewrite every
res:// path reference (scenes, scripts, project.godot) accordingly.
Rename node_2d.tscn -> ships/ship.tscn and lowercase
images/ships/Example_ships -> assets/images/ships/example_ships
for naming consistency. Update overview/structure.md to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 20:28:15 -04:00

284 lines
8.6 KiB
GDScript

extends Control
var _selected_race: int = 0
var _selected_server: String = ""
var _name_input: LineEdit
var _join_button: Button
var _race_buttons: Array[Button] = []
var _server_btn: Button
func _ready() -> void:
_build_ui()
func _build_ui() -> void:
var bg := TextureRect.new()
bg.texture = load("res://assets/images/background/skybox/1.png")
bg.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
bg.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
add_child(bg)
var overlay := ColorRect.new()
overlay.color = Color(0.02, 0.03, 0.1, 0.72)
overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
add_child(overlay)
var header := _make_panel(0, 0, 1280, 60)
add_child(header)
var title_lbl := Label.new()
title_lbl.text = "S P A C E W A R — SERVER BROWSER"
title_lbl.anchor_left = 0.0
title_lbl.anchor_top = 0.0
title_lbl.anchor_right = 1.0
title_lbl.anchor_bottom = 1.0
title_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
title_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
title_lbl.add_theme_font_size_override("font_size", 26)
title_lbl.add_theme_color_override("font_color", Color(0.4, 0.85, 1.0))
header.add_child(title_lbl)
var left := _make_panel(10, 70, 745, 720)
add_child(left)
_build_server_list(left)
var right := _make_panel(765, 70, 505, 720)
add_child(right)
_build_player_setup(right)
func _make_panel(x: float, y: float, w: float, h: float) -> Panel:
var p := Panel.new()
p.anchor_left = 0.0
p.anchor_top = 0.0
p.anchor_right = 0.0
p.anchor_bottom = 0.0
p.offset_left = x
p.offset_top = y
p.offset_right = x + w
p.offset_bottom = y + h
var style := StyleBoxFlat.new()
style.bg_color = Color(0.04, 0.07, 0.16, 0.92)
style.set_corner_radius_all(8)
style.set_border_width_all(1)
style.border_color = Color(0.18, 0.38, 0.65, 0.9)
p.add_theme_stylebox_override("panel", style)
return p
func _vbox_in(parent: Control, margin: float = 16.0) -> VBoxContainer:
var vb := VBoxContainer.new()
vb.anchor_left = 0.0
vb.anchor_top = 0.0
vb.anchor_right = 1.0
vb.anchor_bottom = 1.0
vb.offset_left = margin
vb.offset_top = margin
vb.offset_right = -margin
vb.offset_bottom = -margin
vb.add_theme_constant_override("separation", 10)
parent.add_child(vb)
return vb
func _section_label(txt: String) -> Label:
var lbl := Label.new()
lbl.text = txt
lbl.add_theme_font_size_override("font_size", 18)
lbl.add_theme_color_override("font_color", Color(0.55, 0.82, 1.0))
return lbl
func _field_label(txt: String) -> Label:
var lbl := Label.new()
lbl.text = txt
lbl.add_theme_font_size_override("font_size", 14)
lbl.add_theme_color_override("font_color", Color(0.65, 0.72, 0.82))
return lbl
func _flat_box(color: Color, radius: int = 0) -> StyleBoxFlat:
var s := StyleBoxFlat.new()
s.bg_color = color
s.set_corner_radius_all(radius)
return s
func _build_server_list(parent: Panel) -> void:
var vb := _vbox_in(parent)
vb.add_child(_section_label("Available Servers"))
vb.add_child(HSeparator.new())
var col_hdr := HBoxContainer.new()
vb.add_child(col_hdr)
var h_name := _field_label("Server Name")
h_name.size_flags_horizontal = Control.SIZE_EXPAND_FILL
col_hdr.add_child(h_name)
var h_players := _field_label("Players")
h_players.custom_minimum_size = Vector2(110, 0)
h_players.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
col_hdr.add_child(h_players)
vb.add_child(HSeparator.new())
_server_btn = Button.new()
_server_btn.toggle_mode = true
_server_btn.text = " Trench Wars"
_server_btn.alignment = HORIZONTAL_ALIGNMENT_LEFT
_server_btn.custom_minimum_size = Vector2(0, 54)
_server_btn.add_theme_font_size_override("font_size", 17)
_server_btn.add_theme_color_override("font_color", Color(0.92, 0.95, 1.0))
var sn := _flat_box(Color(0.07, 0.13, 0.25, 1.0), 4)
sn.content_margin_left = 12.0
var sh := _flat_box(Color(0.11, 0.21, 0.4, 1.0), 4)
sh.content_margin_left = 12.0
var sp := _flat_box(Color(0.09, 0.27, 0.52, 1.0), 4)
sp.set_border_width_all(2)
sp.border_color = Color(0.3, 0.65, 1.0, 1.0)
sp.content_margin_left = 12.0
_server_btn.add_theme_stylebox_override("normal", sn)
_server_btn.add_theme_stylebox_override("hover", sh)
_server_btn.add_theme_stylebox_override("pressed", sp)
_server_btn.pressed.connect(_on_server_selected.bind("trench_wars"))
vb.add_child(_server_btn)
# Player count label floated to the right of the server button row
# (separate non-interactive label overlaid via HBox trick)
var row_hb := HBoxContainer.new()
# We already added the button directly to vb; restructure: remove and re-add inside HBox
vb.remove_child(_server_btn)
vb.add_child(row_hb)
row_hb.add_child(_server_btn)
_server_btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL
var pc_lbl := Label.new()
pc_lbl.text = "0 / 32"
pc_lbl.custom_minimum_size = Vector2(80, 0)
pc_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
pc_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
pc_lbl.add_theme_font_size_override("font_size", 14)
pc_lbl.add_theme_color_override("font_color", Color(0.5, 0.65, 0.8))
row_hb.add_child(pc_lbl)
func _build_player_setup(parent: Panel) -> void:
var vb := _vbox_in(parent, 20.0)
vb.add_theme_constant_override("separation", 12)
vb.add_child(_section_label("Player Setup"))
vb.add_child(HSeparator.new())
vb.add_child(_field_label("Player Name:"))
_name_input = LineEdit.new()
_name_input.placeholder_text = "Enter your callsign..."
_name_input.custom_minimum_size = Vector2(0, 44)
_name_input.add_theme_font_size_override("font_size", 16)
_name_input.text_changed.connect(_on_name_changed)
vb.add_child(_name_input)
var gap := Control.new()
gap.custom_minimum_size = Vector2(0, 6)
vb.add_child(gap)
vb.add_child(_field_label("Select Race:"))
var race_hb := HBoxContainer.new()
race_hb.custom_minimum_size = Vector2(0, 58)
race_hb.add_theme_constant_override("separation", 10)
vb.add_child(race_hb)
var race_cfg: Array = [
["Race 1", Color(0.25, 0.5, 1.0)],
["Race 2", Color(1.0, 0.45, 0.2)],
["Race 3", Color(0.25, 0.9, 0.4)],
]
for i in 3:
var btn := _make_race_button(race_cfg[i][0], race_cfg[i][1])
btn.pressed.connect(_on_race_selected.bind(i + 1))
race_hb.add_child(btn)
_race_buttons.append(btn)
var filler := Control.new()
filler.size_flags_vertical = Control.SIZE_EXPAND_FILL
vb.add_child(filler)
_join_button = Button.new()
_join_button.text = "JOIN GAME"
_join_button.custom_minimum_size = Vector2(0, 64)
_join_button.disabled = true
_join_button.add_theme_font_size_override("font_size", 22)
_join_button.add_theme_color_override("font_color", Color(0.35, 1.0, 0.45))
_join_button.add_theme_color_override("font_color_disabled", Color(0.3, 0.35, 0.3, 0.6))
var jn := _flat_box(Color(0.07, 0.28, 0.1, 1.0), 7)
var jh := _flat_box(Color(0.1, 0.42, 0.14, 1.0), 7)
var jd := _flat_box(Color(0.06, 0.09, 0.07, 0.5), 7)
_join_button.add_theme_stylebox_override("normal", jn)
_join_button.add_theme_stylebox_override("hover", jh)
_join_button.add_theme_stylebox_override("disabled", jd)
_join_button.pressed.connect(_on_join_pressed)
vb.add_child(_join_button)
func _make_race_button(label_text: String, col: Color) -> Button:
var btn := Button.new()
btn.text = label_text
btn.toggle_mode = true
btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL
btn.custom_minimum_size = Vector2(0, 58)
btn.add_theme_font_size_override("font_size", 15)
btn.add_theme_color_override("font_color", Color.WHITE)
var dark := Color(col.r * 0.22, col.g * 0.22, col.b * 0.22, 1.0)
var mid := Color(col.r * 0.38, col.g * 0.38, col.b * 0.38, 1.0)
var lite := Color(col.r * 0.5, col.g * 0.5, col.b * 0.5, 1.0)
var s_n := _flat_box(dark, 6)
var s_h := _flat_box(mid, 6)
var s_p := _flat_box(lite, 6)
s_p.set_border_width_all(2)
s_p.border_color = col
btn.add_theme_stylebox_override("normal", s_n)
btn.add_theme_stylebox_override("hover", s_h)
btn.add_theme_stylebox_override("pressed", s_p)
return btn
func _on_name_changed(_text: String) -> void:
_update_join()
func _on_race_selected(race: int) -> void:
_selected_race = race
for i in _race_buttons.size():
_race_buttons[i].button_pressed = (i + 1 == race)
_update_join()
func _on_server_selected(server: String) -> void:
_selected_server = server
_server_btn.button_pressed = true
_update_join()
func _update_join() -> void:
_join_button.disabled = (
_name_input.text.strip_edges().is_empty()
or _selected_race == 0
or _selected_server.is_empty()
)
func _on_join_pressed() -> void:
GameConfig.player_name = _name_input.text.strip_edges()
GameConfig.player_race = _selected_race
get_tree().change_scene_to_file("res://world/world.tscn")