0c2628a1a6
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>
284 lines
8.6 KiB
GDScript
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")
|