extends Node2D var W: float = 960.0 var H: float = 600.0 # Cockpit palette const COL_BG := Color(0.0, 0.04, 0.02, 0.90) const COL_PRIMARY := Color(0.0, 1.0, 0.533, 1.0) # phosphor green const COL_ACCENT := Color(0.27, 1.0, 0.8, 1.0) const COL_DIM := Color(0.0, 0.27, 0.13, 0.6) # lines / brackets only const COL_TEXT := Color(0.3, 0.68, 0.46, 0.88) # readable secondary text const COL_P2 := Color(0.27, 1.0, 0.67, 1.0) const COL_OVERLAY := Color(0.0, 0.0, 0.04, 0.78) var is_p2_mode: bool = false var selected: int = 0 var ships: Array = [] var blink_phase: float = 0.0 var enter_blink: bool = true var enter_timer: float = 0.0 func start_select(p2_mode: bool, start_sel: int, ship_data: Array) -> void: is_p2_mode = p2_mode selected = start_sel ships = ship_data visible = true blink_phase = 0.0 func set_selection(idx: int) -> void: selected = idx queue_redraw() func _process(delta: float) -> void: blink_phase += delta enter_timer += delta if enter_timer >= 0.5: enter_timer = 0.0 enter_blink = not enter_blink queue_redraw() func _draw() -> void: var vs: Vector2 = get_viewport_rect().size W = vs.x; H = vs.y # Background overlay so live simulation shows through draw_rect(get_viewport_rect(), COL_OVERLAY) # ── Header bar ─────────────────────────────────────────────────────────── draw_rect(Rect2(0, 0, W, 52.0), Color(0.0, 0.04, 0.02, 0.92)) draw_line(Vector2(0, 52), Vector2(W, 52), COL_DIM, 1.0) var header_col := COL_PRIMARY if not is_p2_mode else COL_P2 _draw_text_centered(Tr.t("select_header"), W * 0.5, 14.0, 10, COL_TEXT) var sub := Tr.t("select_pilot1") if not is_p2_mode else Tr.t("select_pilot2") _draw_text_centered(sub, W * 0.5, 30.0, 13, header_col) # Outer corner brackets _draw_corner_brackets(8.0, 8.0, W - 8.0, H - 8.0, COL_DIM, 16.0) # ── Ship boxes ─────────────────────────────────────────────────────────── # 2×2 Grid Layout (supports 4 ships, falls back for 3) var n := ships.size() var cols: int = 2 if n >= 4 else min(n, 3) var box_w := 220.0; var box_h := 180.0 if cols == 3: box_w = 210.0; box_h = 220.0 var row_h: float = box_h + 16.0 var col_space: float = (W - box_w * cols) / float(cols + 1) var grid_start_y: float = 72.0 for i in n: var col_i: int = i % cols var row_i: int = int(i / cols) var bx: float = col_space + col_i * (box_w + col_space) var by: float = grid_start_y + row_i * row_h var is_sel := i == selected var pulse := 0.5 + 0.5 * sin(blink_phase * 3.0) # Box background draw_rect(Rect2(bx, by, box_w, box_h), Color(0.0, 0.04, 0.02, 0.72)) # Corner L-brackets instead of full border var bracket_col: Color if is_sel: bracket_col = Color(COL_ACCENT.r, COL_ACCENT.g, COL_ACCENT.b, 0.6 + 0.4 * pulse) else: bracket_col = COL_DIM _draw_corner_brackets(bx, by, bx + box_w, by + box_h, bracket_col, 16.0) # Ship preview var cx := bx + box_w * 0.5 var cy := by + box_h * 0.42 var preview_heading := blink_phase * 0.6 if is_sel else -PI * 0.5 _draw_ship_preview(cx, cy, preview_heading, ships[i]) # Ship name var name_col := COL_ACCENT if is_sel else COL_TEXT _draw_text_centered(ships[i]["name"], cx, by + box_h - 42.0, 12, name_col) # Ship identifier or boost hint var sub_str: String match ships[i]["id"]: "classic": sub_str = "1 SHIELD · BALANCED" "inferno": sub_str = "SPEED+ · RAM DAMAGE" "aurora": sub_str = "2 SHIELDS · BH RESIST" "titan": sub_str = "[SHIFT] BOOST" _: sub_str = ships[i]["id"].to_upper() _draw_text_centered(sub_str, cx, by + box_h - 24.0, 8, Color(COL_TEXT.r, COL_TEXT.g, COL_TEXT.b, 0.85)) # ── Footer ─────────────────────────────────────────────────────────────── draw_rect(Rect2(0, H - 48.0, W, 48.0), Color(0.0, 0.04, 0.02, 0.92)) draw_line(Vector2(0, H - 48.0), Vector2(W, H - 48.0), COL_DIM, 1.0) _draw_text_centered(Tr.hint("select_choose"), W * 0.5, H - 44.0, 9, COL_TEXT) if not is_p2_mode: if enter_blink: _draw_text_centered(Tr.hint("select_confirm"), W * 0.5, H - 26.0, 11, COL_PRIMARY) else: _draw_text_centered(Tr.hint("select_join"), W * 0.3, H - 26.0, 10, COL_P2 if enter_blink else COL_DIM) _draw_text_centered(Tr.hint("select_solo"), W * 0.7, H - 26.0, 10, COL_PRIMARY if enter_blink else COL_DIM) # ── Drawing helpers ─────────────────────────────────────────────────────────── func _draw_corner_brackets(x1: float, y1: float, x2: float, y2: float, col: Color, arm: float) -> void: # Top-left draw_line(Vector2(x1, y1), Vector2(x1 + arm, y1), col, 1.5) draw_line(Vector2(x1, y1), Vector2(x1, y1 + arm), col, 1.5) # Top-right draw_line(Vector2(x2, y1), Vector2(x2 - arm, y1), col, 1.5) draw_line(Vector2(x2, y1), Vector2(x2, y1 + arm), col, 1.5) # Bottom-left draw_line(Vector2(x1, y2), Vector2(x1 + arm, y2), col, 1.5) draw_line(Vector2(x1, y2), Vector2(x1, y2 - arm), col, 1.5) # Bottom-right draw_line(Vector2(x2, y2), Vector2(x2 - arm, y2), col, 1.5) draw_line(Vector2(x2, y2), Vector2(x2, y2 - arm), col, 1.5) func _draw_ship_preview(cx: float, cy: float, heading: float, ship: Dictionary) -> void: var cos_h := cos(heading); var sin_h := sin(heading) var preview_scale := 5.5 var hull_pixels := [ [3, 0, "nose"], [2, -1, "mid"], [2, 1, "mid"], [1, 0, "dim"], [0, -2, "accent"],[0, 2, "accent"], [0, 0, "bright"],[-1,-1, "dim"], [-1, 1, "dim"], [-2,-2, "shadow"],[-2, 2, "shadow"],[-2, 0, "edge"], ] for px_data in hull_pixels: var lx: float = px_data[0] * preview_scale var ly: float = px_data[1] * preview_scale var col: Color = ship.get(px_data[2], Color.WHITE) var rx := cx + lx * cos_h - ly * sin_h var ry := cy + lx * sin_h + ly * cos_h draw_rect(Rect2(rx - 2, ry - 2, 5, 5), col) func _draw_text_centered(text: String, x: float, y: float, font_size: int, col: Color) -> void: var font := ThemeDB.fallback_font var tw := font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x draw_string(font, Vector2(x - tw * 0.5, y + font_size), text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, col) func _draw_text(text: String, x: float, y: float, font_size: int, col: Color) -> void: var font := ThemeDB.fallback_font draw_string(font, Vector2(x, y + font_size), text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, col)