170 lines
5.8 KiB
GDScript
170 lines
5.8 KiB
GDScript
class_name MainMenu
|
|
extends CanvasLayer
|
|
|
|
## MainMenu - Title menu using pre-designed background image (title_menu.png)
|
|
## The window is sized to match the image (67% of 1024x1536).
|
|
## The image fills the entire window; buttons overlay the pre-drawn slots.
|
|
|
|
signal quick_play
|
|
signal play_game
|
|
signal online_game
|
|
signal open_settings
|
|
signal quit_game
|
|
|
|
# UI Components
|
|
var bg_texture: TextureRect
|
|
var buttons_container: Control
|
|
var quick_play_button: Button
|
|
var play_button: Button
|
|
var online_button: Button
|
|
var settings_button: Button
|
|
var quit_button: Button
|
|
var version_label: Label
|
|
|
|
# Custom font
|
|
var custom_font: Font = preload("res://JimNightshade-Regular.ttf")
|
|
|
|
# Per-button pixel rects: Rect2(x, y, width, height) at 460x689 window size
|
|
# Measured from the pre-drawn button slots in title_menu.png
|
|
const BUTTON_RECTS := [
|
|
Rect2(130, 78, 200, 38), # Quick Play
|
|
Rect2(130, 163, 200, 38), # Play
|
|
Rect2(130, 229, 200, 38), # Online
|
|
Rect2(130, 295, 200, 38), # Settings
|
|
Rect2(130, 360, 200, 38), # Exit
|
|
]
|
|
const DESIGN_SIZE := Vector2(460, 689)
|
|
|
|
func _ready() -> void:
|
|
# Center the window on screen
|
|
var screen := DisplayServer.screen_get_size()
|
|
var win_size := get_tree().root.size
|
|
DisplayServer.window_set_position(Vector2i(
|
|
(screen.x - win_size.x) / 2,
|
|
(screen.y - win_size.y) / 2
|
|
))
|
|
_create_menu()
|
|
|
|
func _create_menu() -> void:
|
|
var win_size := get_tree().root.get_visible_rect().size
|
|
|
|
# Background image fills the whole window
|
|
bg_texture = TextureRect.new()
|
|
add_child(bg_texture)
|
|
bg_texture.texture = load("res://assets/ui/title_menu.png")
|
|
bg_texture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
|
bg_texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
bg_texture.position = Vector2.ZERO
|
|
bg_texture.size = win_size
|
|
bg_texture.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
# Container for buttons
|
|
buttons_container = Control.new()
|
|
add_child(buttons_container)
|
|
buttons_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
# Create buttons overlaying the pre-drawn slots
|
|
quick_play_button = _create_overlay_button("Quick Play", 0)
|
|
quick_play_button.add_theme_color_override("font_color", Color(0.15, 0.13, 0.1))
|
|
quick_play_button.add_theme_color_override("font_hover_color", Color(0.3, 0.25, 0.2))
|
|
quick_play_button.add_theme_color_override("font_pressed_color", Color(0.05, 0.05, 0.05))
|
|
quick_play_button.pressed.connect(_on_quick_play_pressed)
|
|
|
|
play_button = _create_overlay_button("Play", 1)
|
|
play_button.pressed.connect(_on_play_pressed)
|
|
|
|
online_button = _create_overlay_button("Online", 2)
|
|
online_button.disabled = true
|
|
|
|
settings_button = _create_overlay_button("Settings", 3)
|
|
settings_button.disabled = true
|
|
|
|
quit_button = _create_overlay_button("Exit", 4)
|
|
quit_button.pressed.connect(_on_quit_pressed)
|
|
|
|
# Version label
|
|
version_label = Label.new()
|
|
version_label.text = "v0.1.0"
|
|
version_label.add_theme_font_override("font", custom_font)
|
|
version_label.add_theme_font_size_override("font_size", 11)
|
|
version_label.add_theme_color_override("font_color", Color(0.6, 0.6, 0.7, 0.5))
|
|
add_child(version_label)
|
|
|
|
# Position everything
|
|
_reposition_elements()
|
|
|
|
func _create_overlay_button(text: String, slot_index: int) -> Button:
|
|
var button = Button.new()
|
|
button.text = text
|
|
button.add_theme_font_override("font", custom_font)
|
|
button.add_theme_font_size_override("font_size", 20)
|
|
button.add_theme_color_override("font_color", Color(0.85, 0.82, 0.72))
|
|
button.add_theme_color_override("font_hover_color", Color(1.0, 0.95, 0.8))
|
|
button.add_theme_color_override("font_pressed_color", Color(0.7, 0.65, 0.55))
|
|
button.add_theme_color_override("font_disabled_color", Color(0.45, 0.42, 0.38))
|
|
|
|
# Transparent background so the pre-drawn button art shows through
|
|
var transparent = StyleBoxFlat.new()
|
|
transparent.bg_color = Color(0, 0, 0, 0)
|
|
transparent.set_border_width_all(0)
|
|
transparent.set_content_margin_all(0)
|
|
button.add_theme_stylebox_override("normal", transparent)
|
|
|
|
var hover_style = StyleBoxFlat.new()
|
|
hover_style.bg_color = Color(1, 1, 1, 0.1)
|
|
hover_style.set_border_width_all(0)
|
|
hover_style.set_content_margin_all(0)
|
|
button.add_theme_stylebox_override("hover", hover_style)
|
|
|
|
var pressed_style = StyleBoxFlat.new()
|
|
pressed_style.bg_color = Color(0, 0, 0, 0.2)
|
|
pressed_style.set_border_width_all(0)
|
|
pressed_style.set_content_margin_all(0)
|
|
button.add_theme_stylebox_override("pressed", pressed_style)
|
|
|
|
var disabled_style = StyleBoxFlat.new()
|
|
disabled_style.bg_color = Color(0, 0, 0, 0.35)
|
|
disabled_style.set_border_width_all(0)
|
|
disabled_style.set_content_margin_all(0)
|
|
button.add_theme_stylebox_override("disabled", disabled_style)
|
|
|
|
button.set_meta("slot_index", slot_index)
|
|
buttons_container.add_child(button)
|
|
return button
|
|
|
|
func _reposition_elements() -> void:
|
|
var win_size := get_tree().root.get_visible_rect().size
|
|
|
|
# Image fills window
|
|
bg_texture.size = win_size
|
|
|
|
# Scale factor from design size to actual window size
|
|
var scale := Vector2(win_size.x / DESIGN_SIZE.x, win_size.y / DESIGN_SIZE.y)
|
|
var base_font := int(22.0 * scale.y)
|
|
|
|
# Position each button using its individual rect
|
|
for child in buttons_container.get_children():
|
|
if child is Button:
|
|
var slot: int = child.get_meta("slot_index", -1)
|
|
if slot < 0 or slot >= BUTTON_RECTS.size():
|
|
continue
|
|
var rect: Rect2 = BUTTON_RECTS[slot]
|
|
child.position = Vector2(rect.position.x * scale.x, rect.position.y * scale.y)
|
|
child.size = Vector2(rect.size.x * scale.x, rect.size.y * scale.y)
|
|
child.add_theme_font_override("font", custom_font)
|
|
child.add_theme_font_size_override("font_size", base_font)
|
|
|
|
# Version label bottom-right
|
|
version_label.position = Vector2(win_size.x - 80, win_size.y - 24)
|
|
version_label.size = Vector2(72, 18)
|
|
|
|
func _on_quick_play_pressed() -> void:
|
|
quick_play.emit()
|
|
|
|
func _on_play_pressed() -> void:
|
|
play_game.emit()
|
|
|
|
func _on_quit_pressed() -> void:
|
|
quit_game.emit()
|
|
get_tree().quit()
|