Files
room_glitch/games/launcher/arcade_launcher.gd
T

176 lines
6.7 KiB
GDScript

extends Node
@export var hardware_scenario: ScenarioDefinition = preload("res://data/scenarios/proof_of_concept.tres")
## Standalone arcade selector. Room/scenario startup remains separate.
const GAMES := [
["Pac-Man", "pacman/Pacman", "pacman", "JOYSTICK"],
["Galaga", "galaga/Galaga", "galaga", "JOYSTICK / FIRE"],
["Tempest", "tempest/Tempest", "tempest", "JOYSTICK OR TRACKBALL / FIRE / SUPERZAPPER"],
["Missile Command", "missile_command/MissileCommand", "missilecommand", "TRACKBALL / THREE LAUNCH BUTTONS"],
["Frogger", "frogger/Frogger", "frogger", "JOYSTICK"],
["Space Invaders", "space_invaders/SpaceInvaders", "spaceinvaders", "JOYSTICK / FIRE"],
["Robotron 2084", "robotron/Robotron", "robotron", "JOYSTICK / FOUR DIRECTIONAL FIRE BUTTONS"],
]
var selected := 0
var game: Node
var menu: Control
var list: ItemList
var description: Label
var switching := false
var setup: CanvasLayer
var control_status: Label
var gpio_status: Label
func _ready() -> void:
if "--managed-cabinet" in OS.get_cmdline_user_args():
set_process_input(false)
add_child(preload("res://core/network/managed_cabinet.gd").new())
return
if "--operator" in OS.get_cmdline_user_args():
set_process_input(false)
add_child(preload("res://operator/ArcadeRoomOperator.tscn").instantiate())
return
var layer := CanvasLayer.new()
add_child(layer)
menu = Control.new()
menu.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
layer.add_child(menu)
var background := ColorRect.new()
background.color = Color("080d18")
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
menu.add_child(background)
var center := CenterContainer.new()
center.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
menu.add_child(center)
var column := VBoxContainer.new()
column.custom_minimum_size = Vector2(700, 0)
column.add_theme_constant_override("separation", 18)
center.add_child(column)
var title := Label.new()
title.text = "ARCADE GALLERY"
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
title.add_theme_font_size_override("font_size", 46)
title.modulate = Color("75e8ef")
column.add_child(title)
list = ItemList.new()
list.custom_minimum_size = Vector2(700, 520)
list.fixed_icon_size = Vector2i(48, 48)
list.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
list.add_theme_font_size_override("font_size", 28)
list.add_theme_constant_override("v_separation", 12)
list.focus_mode = Control.FOCUS_NONE
column.add_child(list)
for entry in GAMES:
list.add_item(entry[0], load("res://games/launcher/icons/ico_%s.png" % entry[2]))
list.add_item("Control Setup")
list.item_selected.connect(_select)
list.item_activated.connect(func(index: int): _select(index); launch.call_deferred())
description = Label.new()
description.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
description.add_theme_font_size_override("font_size", 18)
column.add_child(description)
var hint := Label.new()
hint.text = "JOYSTICK: CHOOSE START: PLAY SELECT: RETURN TO MENU"
hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
hint.modulate = Color("91a1bb")
column.add_child(hint)
control_status = Label.new()
control_status.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
control_status.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
control_status.add_theme_font_size_override("font_size", 16)
column.add_child(control_status)
ArcadeControls.changed.connect(_refresh_control_status)
_refresh_control_status()
gpio_status = Label.new()
gpio_status.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
gpio_status.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
gpio_status.text = HardwareManager.status
column.add_child(gpio_status)
HardwareManager.status_changed.connect(func(message: String): gpio_status.text = message)
_select(0)
if ArcadeControls.bindings.is_empty(): open_setup.call_deferred()
func _refresh_control_status() -> void:
control_status.text = ArcadeControls.problem if not ArcadeControls.problem.is_empty() else "CONTROL SETUP: LAST MENU ENTRY / F1"
func _select(index: int) -> void:
selected = wrapi(index, 0, GAMES.size() + 1)
list.select(selected)
list.ensure_current_is_visible()
description.text = GAMES[selected][3] if selected < GAMES.size() else "CONFIGURE THIS CABINET'S JOYSTICKS AND BUTTONS"
func _input(event: InputEvent) -> void:
if ArcadeControls.handle_quit(event): return
if is_instance_valid(setup): return
if event.is_echo() or switching: return
if event is InputEventKey and event.pressed and event.physical_keycode == KEY_F1:
get_viewport().set_input_as_handled()
if is_instance_valid(game): return_to_menu()
open_setup.call_deferred()
return
if is_instance_valid(game):
if event.is_action_pressed("arcade_menu"):
get_viewport().set_input_as_handled()
switching = true
return_to_menu.call_deferred()
return
if event.is_action_pressed("arcade_down"):
_select(selected + 1)
elif event.is_action_pressed("arcade_up"):
_select(selected - 1)
elif event.is_action_pressed("arcade_start"):
switching = true
launch.call_deferred()
else:
return
get_viewport().set_input_as_handled()
func launch() -> void:
if selected == GAMES.size():
open_setup()
switching = false
return
if is_instance_valid(game): return
var scene := load("res://games/%s.tscn" % GAMES[selected][1]) as PackedScene
if scene == null:
switching = false
return
game = scene.instantiate()
RoomRuntime.active_assignment = null
if hardware_scenario != null:
for assignment in hardware_scenario.assignments:
if assignment.game != null and assignment.game.scene == scene:
RoomRuntime.configure(assignment)
game.game_started.connect(func(): RoomRuntime.fire_game_event(GameEvents.STARTED))
game.game_won.connect(func(): RoomRuntime.fire_game_event(GameEvents.WON))
game.game_lost.connect(func(): RoomRuntime.fire_game_event(GameEvents.LOST))
game.game_reset.connect(func(): RoomRuntime.fire_game_event(GameEvents.RESET))
break
if GAMES[selected][2] == "missilecommand":
game.set("relative_mouse_aim", true)
if GAMES[selected][2] in ["missilecommand", "tempest"]:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
menu.hide()
add_child(game)
# Present the game's attract screen; Start begins its own opening sequence.
switching = false
func open_setup() -> void:
if is_instance_valid(setup): return
setup = preload("res://games/launcher/control_setup.gd").new()
menu.hide()
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
setup.closed.connect(func(): menu.show(); _select(selected))
add_child(setup)
func return_to_menu() -> void:
if is_instance_valid(game):
remove_child(game)
game.queue_free()
game = null
RoomRuntime.active_assignment = null
HardwareManager.active_cabinet = null
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
menu.show()
_select(selected)
switching = false