Fix the stop stutter, and hide unresearched buildings from the menu
Forgejo #13: releasing the stick paused, then moved again before settling. stop() aims each ship at a braking point ahead of it, but the ship's own velocity was ~0 - the anchor had been carrying it - so it started from REST, accelerated into its own stopping distance, and halted a second time. Measured: 0 -> 45 -> 90 -> 135 -> 180 -> brake. stop() now hands the fleet's motion to the ship, so the release is one continuous decelerating coast (222 -> 0) to the identical endpoint. test_joystick_control now asserts the speed one frame after release is a real fraction of cruise, and never rises afterwards. Forgejo #21: unresearched structures are no longer listed greyed out. They are hidden, and the menu repacks around what is left - a fixed grid with entries hidden would otherwise leave holes where they used to be. An entry alone on its row is centred rather than hanging in the left column. Researched-but-not-usable is still shown greyed: an extractor with no planet under the fleet is "not now", not "not yet". This reverses a documented decision (the old comment argued that always listing everything stops the player wondering whether the game has it at all), so test_skill_tree's matching assertion was updated from greyed-but-listed to hidden. The gate itself is unchanged and still refuses a build forced past the menu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
da8f6a81ea
commit
0e071877e2
6 changed files with 261 additions and 18 deletions
|
|
@ -28,6 +28,18 @@ extends Node2D
|
|||
@onready var build_status: Label = get_node("../UI/BuildMenu/StatusLabel")
|
||||
@onready var build_extractor_button: IconButton = get_node("../UI/BuildMenu/ExtractorButton")
|
||||
@onready var build_hub_button: IconButton = get_node("../UI/BuildMenu/TransportHubButton")
|
||||
@onready var build_menu_entries: Array = [
|
||||
[GameState.BUILDING_MOTHERSHIP, build_mothership_button,
|
||||
get_node("../UI/BuildMenu/MothershipLabel"), get_node("../UI/BuildMenu/MothershipCost")],
|
||||
[GameState.BUILDING_SHIP_CRAFTER, build_crafter_button,
|
||||
get_node("../UI/BuildMenu/CrafterLabel"), get_node("../UI/BuildMenu/CrafterCost")],
|
||||
[GameState.BUILDING_COMMAND_CENTER, build_command_button,
|
||||
get_node("../UI/BuildMenu/CommandLabel"), get_node("../UI/BuildMenu/CommandCost")],
|
||||
[GameState.BUILDING_EXTRACTOR, build_extractor_button,
|
||||
get_node("../UI/BuildMenu/ExtractorLabel"), get_node("../UI/BuildMenu/ExtractorCost")],
|
||||
[GameState.BUILDING_TRANSPORT_HUB, build_hub_button,
|
||||
get_node("../UI/BuildMenu/TransportHubLabel"), get_node("../UI/BuildMenu/TransportHubCost")],
|
||||
]
|
||||
@onready var planet_field: Node2D = get_node("../PlanetField")
|
||||
@onready var info_popup: Control = get_node("../UI/BuildMenu/InfoPopup")
|
||||
@onready var info_title: Label = get_node("../UI/BuildMenu/InfoPopup/Panel/TitleLabel")
|
||||
|
|
@ -185,6 +197,7 @@ func _process(delta: float) -> void:
|
|||
# a planet lights the option up without reopening it.
|
||||
build_extractor_button.enabled = _planet_under_fleet() != null \
|
||||
and GameState.is_building_unlocked(GameState.BUILDING_EXTRACTOR)
|
||||
build_extractor_button.queue_redraw()
|
||||
|
||||
if craft_menu.visible:
|
||||
# Live, so a delivery arriving while the menu is open visibly works
|
||||
|
|
@ -266,14 +279,58 @@ func _planet_under_fleet() -> Node2D:
|
|||
return planet_field.get_planet_fleet_is_on()
|
||||
|
||||
|
||||
# Grid geometry, shared with the layout below. Rows of two, and the menu is
|
||||
# rebuilt from whatever is currently researched (#21) rather than being a
|
||||
# fixed arrangement with holes punched in it.
|
||||
const MENU_ROW_TOPS: Array = [-300.0, -10.0, 280.0]
|
||||
const MENU_COL_X: float = 140.0
|
||||
const MENU_BUTTON_HALF: float = 64.0
|
||||
const MENU_BUTTON_H: float = 128.0
|
||||
const MENU_LABEL_HALF: float = 150.0
|
||||
const MENU_LABEL_H: float = 66.0
|
||||
const MENU_COST_HALF: float = 60.0
|
||||
const MENU_COST_H: float = 52.0
|
||||
|
||||
|
||||
func _place_entry(node: Control, cx: float, top: float, half: float, height: float) -> void:
|
||||
node.offset_left = cx - half
|
||||
node.offset_right = cx + half
|
||||
node.offset_top = top
|
||||
node.offset_bottom = top + height
|
||||
|
||||
|
||||
func _layout_build_menu() -> void:
|
||||
# Structures the player has not researched are hidden outright (#21), and
|
||||
# what remains is repacked so there are no gaps where they used to be.
|
||||
# This reverses the earlier decision to always list everything greyed
|
||||
# out; an option you cannot explain is apparently worse than one you
|
||||
# cannot see yet.
|
||||
var shown: Array = []
|
||||
for entry in build_menu_entries:
|
||||
var visible: bool = GameState.is_building_unlocked(entry[0])
|
||||
entry[1].visible = visible
|
||||
entry[2].visible = visible
|
||||
entry[3].visible = visible
|
||||
if visible:
|
||||
shown.append(entry)
|
||||
|
||||
for i in range(shown.size()):
|
||||
var row: int = i / 2
|
||||
# Centred when it is the only one on its row, rather than hanging in
|
||||
# the left column looking like something is missing beside it.
|
||||
var alone: bool = (i == shown.size() - 1) and (i % 2 == 0)
|
||||
var cx: float = 0.0 if alone else (-MENU_COL_X if i % 2 == 0 else MENU_COL_X)
|
||||
var top: float = MENU_ROW_TOPS[mini(row, MENU_ROW_TOPS.size() - 1)]
|
||||
_place_entry(shown[i][1], cx, top, MENU_BUTTON_HALF, MENU_BUTTON_H)
|
||||
_place_entry(shown[i][2], cx, top + 134.0, MENU_LABEL_HALF, MENU_LABEL_H)
|
||||
_place_entry(shown[i][3], cx, top + 204.0, MENU_COST_HALF, MENU_COST_H)
|
||||
|
||||
|
||||
func _refresh_build_status() -> void:
|
||||
# Every option is always listed, greyed when it cannot be used - showing
|
||||
# them only sometimes would leave the player wondering whether the game
|
||||
# has them at all. Greyed buttons still emit `pressed`, so each one can
|
||||
# explain itself in the info popup.
|
||||
build_crafter_button.enabled = GameState.is_building_unlocked(GameState.BUILDING_SHIP_CRAFTER)
|
||||
build_command_button.enabled = GameState.is_building_unlocked(GameState.BUILDING_COMMAND_CENTER)
|
||||
build_hub_button.enabled = GameState.is_building_unlocked(GameState.BUILDING_TRANSPORT_HUB)
|
||||
_layout_build_menu()
|
||||
# Researched but not usable right here is still shown, greyed: an
|
||||
# extractor needs a planet under the fleet, which is a "not now" rather
|
||||
# than a "not yet".
|
||||
build_extractor_button.enabled = _planet_under_fleet() != null \
|
||||
and GameState.is_building_unlocked(GameState.BUILDING_EXTRACTOR)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue