Smooth boosted fleet travel
This commit is contained in:
parent
e5439f7183
commit
fd792e8b63
12 changed files with 90 additions and 8 deletions
|
|
@ -103,6 +103,13 @@ var keyboard_steering: bool = false
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
# Most visuals still animate per rendered frame. The main/surface scenes opt
|
||||||
|
# their roots out of global interpolation, then opt their physics-follow
|
||||||
|
# camera and Ship.tscn hulls back in.
|
||||||
|
# Running the camera after ordinary physics nodes lets it follow the ships'
|
||||||
|
# newest centroid, and interpolation fills the display frames in between.
|
||||||
|
process_physics_priority = 1
|
||||||
|
camera.reset_physics_interpolation()
|
||||||
# #148: the main theme, which outlives this scene - see Music.ensure().
|
# #148: the main theme, which outlives this scene - see Music.ensure().
|
||||||
# This script is the root of BOTH the space scene and the planet
|
# This script is the root of BOTH the space scene and the planet
|
||||||
# surface, so one call here covers the whole game.
|
# surface, so one call here covers the whole game.
|
||||||
|
|
@ -292,7 +299,7 @@ func _process(delta: float) -> void:
|
||||||
_update_pivot(delta)
|
_update_pivot(delta)
|
||||||
|
|
||||||
# Keep the heading fresh while a control is held. Fleet advances its own
|
# Keep the heading fresh while a control is held. Fleet advances its own
|
||||||
# anchor in _process, so this only needs to report the direction. The
|
# anchor in _physics_process, so this only needs to report the direction. The
|
||||||
# keyboard takes precedence, and releasing the keys has to stop the fleet
|
# keyboard takes precedence, and releasing the keys has to stop the fleet
|
||||||
# itself - unlike the stick, there is no centred-again signal to hook.
|
# itself - unlike the stick, there is no centred-again signal to hook.
|
||||||
# #124: the breach drives. One check here covers the stick, the keyboard
|
# #124: the breach drives. One check here covers the stick, the keyboard
|
||||||
|
|
@ -303,6 +310,12 @@ func _process(delta: float) -> void:
|
||||||
else:
|
else:
|
||||||
_apply_steering()
|
_apply_steering()
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
|
_update_camera(delta)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_camera(delta: float) -> void:
|
||||||
var target: Vector2 = fleet.get_centroid()
|
var target: Vector2 = fleet.get_centroid()
|
||||||
if camera.global_position.distance_to(target) <= camera_snap_distance:
|
if camera.global_position.distance_to(target) <= camera_snap_distance:
|
||||||
# Snap and stop dead - see camera_snap_distance. Assigning the exact
|
# Snap and stop dead - see camera_snap_distance. Assigning the exact
|
||||||
|
|
|
||||||
|
|
@ -2634,12 +2634,24 @@ func _advance_resource_converters(delta: float) -> void:
|
||||||
building.conversion_progress = progress
|
building.conversion_progress = progress
|
||||||
|
|
||||||
|
|
||||||
func _advance_distorder_drain(delta: float) -> void:
|
func _distorder_boost_in_use() -> bool:
|
||||||
|
for fleet in get_tree().get_nodes_in_group("player_fleet"):
|
||||||
|
if fleet.has_method("is_using_speed_boost") and fleet.is_using_speed_boost():
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _advance_distorder_drain(delta: float, boost_in_use: bool = true) -> void:
|
||||||
if fleet_speed_multiplier <= 1.0:
|
if fleet_speed_multiplier <= 1.0:
|
||||||
# Nothing owed at 1.0x - and no stale fractional progress should
|
# Nothing owed at 1.0x - and no stale fractional progress should
|
||||||
# carry over into a LATER, unrelated boost.
|
# carry over into a LATER, unrelated boost.
|
||||||
_distorder_drain_progress = 0.0
|
_distorder_drain_progress = 0.0
|
||||||
return
|
return
|
||||||
|
if not boost_in_use:
|
||||||
|
# The fader is a selected cruise speed, not an always-running machine.
|
||||||
|
# Keep any already-earned fraction so stopping cannot erase a nearly
|
||||||
|
# complete unit of cost, but accrue nothing while the fleet is parked.
|
||||||
|
return
|
||||||
# Normalized against the CURRENT ceiling, so "full boost" always costs
|
# Normalized against the CURRENT ceiling, so "full boost" always costs
|
||||||
# ENERGY_DRAIN_PER_SECOND however many distorder vessels widened it -
|
# ENERGY_DRAIN_PER_SECOND however many distorder vessels widened it -
|
||||||
# a bigger fleet buys more speed, not cheaper speed.
|
# a bigger fleet buys more speed, not cheaper speed.
|
||||||
|
|
@ -2897,7 +2909,7 @@ func _process(delta: float) -> void:
|
||||||
_advance_planning()
|
_advance_planning()
|
||||||
_advance_repairs(delta)
|
_advance_repairs(delta)
|
||||||
_advance_resource_converters(delta)
|
_advance_resource_converters(delta)
|
||||||
_advance_distorder_drain(delta)
|
_advance_distorder_drain(delta, _distorder_boost_in_use())
|
||||||
_advance_quests()
|
_advance_quests()
|
||||||
for e in extractors:
|
for e in extractors:
|
||||||
e.mining_progress = float(e.get("mining_progress", 0.0)) + delta * EXTRACTOR_RATE
|
e.mining_progress = float(e.get("mining_progress", 0.0)) + delta * EXTRACTOR_RATE
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@ theme/default_font_size=78
|
||||||
|
|
||||||
pointing/emulate_mouse_from_touch=false
|
pointing/emulate_mouse_from_touch=false
|
||||||
|
|
||||||
|
[physics]
|
||||||
|
|
||||||
|
common/physics_interpolation=true
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
renderer/rendering_method="gl_compatibility"
|
renderer/rendering_method="gl_compatibility"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
[ext_resource type="Script" path="res://ui/IconButton.gd" id="4"]
|
[ext_resource type="Script" path="res://ui/IconButton.gd" id="4"]
|
||||||
|
|
||||||
[node name="PlanetSetupEditor" type="Node2D"]
|
[node name="PlanetSetupEditor" type="Node2D"]
|
||||||
|
physics_interpolation_mode = 2
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
|
|
||||||
[node name="BackgroundLayer" parent="." instance=ExtResource("3")]
|
[node name="BackgroundLayer" parent="." instance=ExtResource("3")]
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
[ext_resource type="Script" path="res://ui/QuestPanel.gd" id="quest_panel"]
|
[ext_resource type="Script" path="res://ui/QuestPanel.gd" id="quest_panel"]
|
||||||
|
|
||||||
[node name="PlanetSurface" type="Node2D"]
|
[node name="PlanetSurface" type="Node2D"]
|
||||||
|
physics_interpolation_mode = 2
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
|
|
||||||
[node name="BackgroundLayer" parent="." instance=ExtResource("3")]
|
[node name="BackgroundLayer" parent="." instance=ExtResource("3")]
|
||||||
|
|
@ -47,8 +48,11 @@ script = ExtResource("dash_ctrl")
|
||||||
script = ExtResource("ability_layout")
|
script = ExtResource("ability_layout")
|
||||||
|
|
||||||
[node name="Camera2D" type="Camera2D" parent="."]
|
[node name="Camera2D" type="Camera2D" parent="."]
|
||||||
|
process_physics_priority = 2
|
||||||
|
physics_interpolation_mode = 1
|
||||||
position = Vector2(0, 0)
|
position = Vector2(0, 0)
|
||||||
zoom = Vector2(1, 1)
|
zoom = Vector2(1, 1)
|
||||||
|
process_callback = 0
|
||||||
|
|
||||||
[node name="SurfaceFeatures" type="Node2D" parent="."]
|
[node name="SurfaceFeatures" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,11 +113,45 @@ func _process(delta: float) -> bool:
|
||||||
root.add_child(main)
|
root.add_child(main)
|
||||||
fleet = main.get_node("Fleet")
|
fleet = main.get_node("Fleet")
|
||||||
fader = main.get_node("UI/SpeedFader")
|
fader = main.get_node("UI/SpeedFader")
|
||||||
fleet.spawn_ships(1, Vector2.ZERO, PackedStringArray([GameState.VESSEL_DISTORDER]))
|
# A carrier supplies the hold the Propulser burns from. The previous
|
||||||
|
# one-Propulser fixture had zero cargo capacity, so its depletion check
|
||||||
|
# accidentally began with no energy regardless of what it deposited.
|
||||||
|
fleet.spawn_ships(2, Vector2.ZERO, PackedStringArray([
|
||||||
|
GameState.VESSEL_CARRIER, GameState.VESSEL_DISTORDER]))
|
||||||
fader._process(0.0)
|
fader._process(0.0)
|
||||||
if not fader.visible:
|
if not fader.visible:
|
||||||
return _fail_now("fader hidden with a distorder ship in the fleet")
|
return _fail_now("fader hidden with a distorder ship in the fleet")
|
||||||
|
if not bool(ProjectSettings.get_setting(
|
||||||
|
"physics/common/physics_interpolation", false)):
|
||||||
|
return _fail_now("physics interpolation is disabled for boosted flight")
|
||||||
|
if fleet.ships[0].physics_interpolation_mode \
|
||||||
|
!= Node.PHYSICS_INTERPOLATION_MODE_ON:
|
||||||
|
return _fail_now("the boosted vessel is not physics-interpolated")
|
||||||
|
if main.get_node("Camera2D").physics_interpolation_mode \
|
||||||
|
!= Node.PHYSICS_INTERPOLATION_MODE_ON:
|
||||||
|
return _fail_now("the fleet camera is not physics-interpolated")
|
||||||
|
|
||||||
|
# #199: choosing a higher cruise speed is free while parked. Once a
|
||||||
|
# heading is active, the exact same multiplier resumes its normal drain.
|
||||||
|
game_state.deposit_fleet_resource(GameState.RESOURCE_ENERGY, 30)
|
||||||
|
game_state.set_fleet_speed_multiplier(GameState.MAX_FLEET_SPEED_MULTIPLIER)
|
||||||
|
var parked_energy: int = game_state.fleet_resource(GameState.RESOURCE_ENERGY)
|
||||||
|
game_state._advance_distorder_drain(5.0,
|
||||||
|
game_state._distorder_boost_in_use())
|
||||||
|
if game_state.fleet_resource(GameState.RESOURCE_ENERGY) != parked_energy:
|
||||||
|
return _fail_now("a parked fleet consumed boost energy")
|
||||||
|
fleet.move_in_direction(Vector2.RIGHT)
|
||||||
|
if not fleet.is_using_speed_boost():
|
||||||
|
return _fail_now("boosted cruise did not report its energy use")
|
||||||
|
game_state._advance_distorder_drain(1.0,
|
||||||
|
game_state._distorder_boost_in_use())
|
||||||
|
if game_state.fleet_resource(GameState.RESOURCE_ENERGY) >= parked_energy:
|
||||||
|
return _fail_now("moving at boosted cruise consumed no energy")
|
||||||
|
fleet.stop()
|
||||||
|
print("parked boost was free; moving boost resumed drain")
|
||||||
|
|
||||||
|
game_state.withdraw_fleet_resource(GameState.RESOURCE_ENERGY,
|
||||||
|
game_state.fleet_resource(GameState.RESOURCE_ENERGY))
|
||||||
game_state.deposit_fleet_resource(GameState.RESOURCE_ENERGY, 4)
|
game_state.deposit_fleet_resource(GameState.RESOURCE_ENERGY, 4)
|
||||||
game_state.set_fleet_speed_multiplier(GameState.MAX_FLEET_SPEED_MULTIPLIER)
|
game_state.set_fleet_speed_multiplier(GameState.MAX_FLEET_SPEED_MULTIPLIER)
|
||||||
fader._process(0.0)
|
fader._process(0.0)
|
||||||
|
|
|
||||||
|
|
@ -67,14 +67,14 @@ func _process(delta: float) -> bool:
|
||||||
return _fail("the Propulser that dashed did not enter cooldown")
|
return _fail("the Propulser that dashed did not enter cooldown")
|
||||||
# The burst should cover substantially more than a linear quarter of
|
# The burst should cover substantially more than a linear quarter of
|
||||||
# its distance at a quarter of its duration, then ease into its stop.
|
# its distance at a quarter of its duration, then ease into its stop.
|
||||||
fleet.set_process(false)
|
fleet.set_physics_process(false)
|
||||||
fleet._advance_dash(fleet.dash_duration * 0.25)
|
fleet._advance_dash(fleet.dash_duration * 0.25)
|
||||||
var early_distance: float = fleet.get_centroid().distance_to(first_origin)
|
var early_distance: float = fleet.get_centroid().distance_to(first_origin)
|
||||||
if early_distance <= DASH_DISTANCE * 0.45 \
|
if early_distance <= DASH_DISTANCE * 0.45 \
|
||||||
or early_distance >= DASH_DISTANCE * 0.7:
|
or early_distance >= DASH_DISTANCE * 0.7:
|
||||||
return _fail("dash has no useful ease-out curve (quarter-time distance %.1f)" \
|
return _fail("dash has no useful ease-out curve (quarter-time distance %.1f)" \
|
||||||
% early_distance)
|
% early_distance)
|
||||||
fleet.set_process(true)
|
fleet.set_physics_process(true)
|
||||||
dash._process(0.0)
|
dash._process(0.0)
|
||||||
if not main.get_node("UI/DashButton").enabled:
|
if not main.get_node("UI/DashButton").enabled:
|
||||||
return _fail("one cooling Propulser disabled a second ready one")
|
return _fail("one cooling Propulser disabled a second ready one")
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
[ext_resource type="Script" uid="uid://dcvdmc68b3nve" path="res://ui/IconButton.gd" id="2"]
|
[ext_resource type="Script" uid="uid://dcvdmc68b3nve" path="res://ui/IconButton.gd" id="2"]
|
||||||
|
|
||||||
[node name="MainMenu" type="Node2D" unique_id=2119550059]
|
[node name="MainMenu" type="Node2D" unique_id=2119550059]
|
||||||
|
physics_interpolation_mode = 2
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
|
|
||||||
[node name="BackgroundLayer" type="CanvasLayer" parent="." unique_id=1572211077]
|
[node name="BackgroundLayer" type="CanvasLayer" parent="." unique_id=1572211077]
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ func teleport_to(world_pos: Vector2) -> void:
|
||||||
ship.move_target += displacement
|
ship.move_target += displacement
|
||||||
ship.velocity = Vector2.ZERO
|
ship.velocity = Vector2.ZERO
|
||||||
ship.fleet_velocity = Vector2.ZERO
|
ship.fleet_velocity = Vector2.ZERO
|
||||||
|
ship.reset_physics_interpolation()
|
||||||
steer_direction = Vector2.ZERO
|
steer_direction = Vector2.ZERO
|
||||||
dash_remaining = 0.0
|
dash_remaining = 0.0
|
||||||
dash_direction = Vector2.ZERO
|
dash_direction = Vector2.ZERO
|
||||||
|
|
@ -242,7 +243,7 @@ func teleport_to(world_pos: Vector2) -> void:
|
||||||
|
|
||||||
|
|
||||||
func move_in_direction(direction: Vector2) -> void:
|
func move_in_direction(direction: Vector2) -> void:
|
||||||
# Joystick steering. Sets the heading; _process advances the anchor.
|
# Joystick steering. Sets the heading; _physics_process advances the anchor.
|
||||||
#
|
#
|
||||||
# This used to park a target 2000 units ahead and let the ships chase
|
# This used to park a target 2000 units ahead and let the ships chase
|
||||||
# it. That made formation changes barely register while flying: with
|
# it. That made formation changes barely register while flying: with
|
||||||
|
|
@ -275,7 +276,13 @@ func is_dashing() -> bool:
|
||||||
return dash_remaining > 0.0
|
return dash_remaining > 0.0
|
||||||
|
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
func is_using_speed_boost() -> bool:
|
||||||
|
return GameState.fleet_speed_multiplier > 1.0 \
|
||||||
|
and steer_direction != Vector2.ZERO and not is_dashing() \
|
||||||
|
and not ships.is_empty()
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
# #158: a building may pay a local cost out of the hold when the fleet is
|
# #158: a building may pay a local cost out of the hold when the fleet is
|
||||||
# actually standing at it, and the autoload has no other way to know
|
# actually standing at it, and the autoload has no other way to know
|
||||||
# where that is. Written before the early return below - a parked fleet
|
# where that is. Written before the early return below - a parked fleet
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
radius = 16.0
|
radius = 16.0
|
||||||
|
|
||||||
[node name="Ship" type="Area2D"]
|
[node name="Ship" type="Area2D"]
|
||||||
|
physics_interpolation_mode = 1
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,7 @@ func _complete_whiteout() -> void:
|
||||||
whiteout_teleported = true
|
whiteout_teleported = true
|
||||||
fleet.teleport_to(DEFAULT_SPAWN)
|
fleet.teleport_to(DEFAULT_SPAWN)
|
||||||
camera.global_position = fleet.get_centroid()
|
camera.global_position = fleet.get_centroid()
|
||||||
|
camera.reset_physics_interpolation()
|
||||||
camera.offset = Vector2.ZERO
|
camera.offset = Vector2.ZERO
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ shader_parameter/cell_size = 60.0
|
||||||
shader_parameter/bg_color = Color(0.02, 0.02, 0.08, 1)
|
shader_parameter/bg_color = Color(0.02, 0.02, 0.08, 1)
|
||||||
|
|
||||||
[node name="Main" type="Node2D"]
|
[node name="Main" type="Node2D"]
|
||||||
|
physics_interpolation_mode = 2
|
||||||
script = ExtResource("3")
|
script = ExtResource("3")
|
||||||
|
|
||||||
[node name="BackgroundLayer" type="CanvasLayer" parent="."]
|
[node name="BackgroundLayer" type="CanvasLayer" parent="."]
|
||||||
|
|
@ -94,8 +95,11 @@ script = ExtResource("dash_ctrl")
|
||||||
script = ExtResource("ability_layout")
|
script = ExtResource("ability_layout")
|
||||||
|
|
||||||
[node name="Camera2D" type="Camera2D" parent="."]
|
[node name="Camera2D" type="Camera2D" parent="."]
|
||||||
|
process_physics_priority = 2
|
||||||
|
physics_interpolation_mode = 1
|
||||||
position = Vector2(0, 0)
|
position = Vector2(0, 0)
|
||||||
zoom = Vector2(1, 1)
|
zoom = Vector2(1, 1)
|
||||||
|
process_callback = 0
|
||||||
|
|
||||||
[node name="EnemySpawner" type="Node2D" parent="."]
|
[node name="EnemySpawner" type="Node2D" parent="."]
|
||||||
script = ExtResource("4")
|
script = ExtResource("4")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue