mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
fix(presentation): simplify camera and engine effects
This commit is contained in:
@@ -1,93 +0,0 @@
|
||||
Copyright 2018 The Orbitron Project Authors (https://github.com/theleagueof/orbitron), with Reserved Font Name: "Orbitron"
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Binary file not shown.
@@ -1,36 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="font_data_dynamic"
|
||||
type="FontFile"
|
||||
uid="uid://bhbpb712ouagv"
|
||||
path="res://.godot/imported/Orbitron-Medium.ttf-0d3cd88166f12a3096066c2eef570744.fontdata"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/fonts/Orbitron-Medium.ttf"
|
||||
dest_files=["res://.godot/imported/Orbitron-Medium.ttf-0d3cd88166f12a3096066c2eef570744.fontdata"]
|
||||
|
||||
[params]
|
||||
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
allow_system_fallback=true
|
||||
force_autohinter=false
|
||||
modulate_color_glyphs=false
|
||||
hinting=3
|
||||
subpixel_positioning=4
|
||||
keep_rounding_remainders=true
|
||||
oversampling=0.0
|
||||
Fallbacks=null
|
||||
fallbacks=[]
|
||||
Compress=null
|
||||
compress=true
|
||||
preload=[]
|
||||
language_support={}
|
||||
script_support={}
|
||||
opentype_features={}
|
||||
@@ -1,10 +1,9 @@
|
||||
[gd_scene load_steps=10 format=3 uid="uid://c8kak2l3m4n5"]
|
||||
[gd_scene load_steps=9 format=3 uid="uid://c8kak2l3m4n5"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://du7y176h5aaq4" path="res://scripts/HUDController.gd" id="1_hud_controller"]
|
||||
[ext_resource type="Script" path="res://scripts/hud_attitude_indicator.gd" id="2_adi"]
|
||||
[ext_resource type="Script" path="res://scripts/hud_heading_tape.gd" id="3_tape"]
|
||||
[ext_resource type="Script" path="res://scripts/hud_gauge.gd" id="4_gauge"]
|
||||
[ext_resource type="Theme" path="res://themes/hud_theme.tres" id="5_theme"]
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_hud"]
|
||||
font_size = 32
|
||||
@@ -51,7 +50,6 @@ anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
theme = ExtResource("5_theme")
|
||||
|
||||
[node name="ScoreboardPanel" type="PanelContainer" parent="Control"]
|
||||
layout_mode = 1
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
[gd_scene load_steps=5 format=3]
|
||||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ship_camera.gd" id="1_rig"]
|
||||
[ext_resource type="Shader" path="res://shaders/post_process.gdshader" id="2_post"]
|
||||
|
||||
[sub_resource type="CameraAttributesPractical" id="CameraAttributes_gameplay"]
|
||||
dof_blur_far_enabled = true
|
||||
dof_blur_far_distance = 24.0
|
||||
dof_blur_far_transition = 14.0
|
||||
dof_blur_near_enabled = true
|
||||
dof_blur_near_distance = 1.25
|
||||
dof_blur_near_transition = 0.75
|
||||
dof_blur_amount = 0.08
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_post"]
|
||||
shader = ExtResource("2_post")
|
||||
|
||||
@@ -20,7 +11,6 @@ script = ExtResource("1_rig")
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
current = true
|
||||
attributes = SubResource("CameraAttributes_gameplay")
|
||||
|
||||
[node name="PostProcess" type="CanvasLayer" parent="."]
|
||||
layer = 0
|
||||
|
||||
@@ -73,7 +73,7 @@ func _draw() -> void:
|
||||
draw_line(Vector2(-half_chord, horizon_y), Vector2(half_chord, horizon_y), LINE_COLOR, 2.0)
|
||||
|
||||
# Pitch ladder: rungs every 10 degrees, labelled, scrolling with pitch.
|
||||
var font := hud_font()
|
||||
var font := ThemeDB.fallback_font
|
||||
for ladder_deg: int in [-30, -20, -10, 10, 20, 30]:
|
||||
var y := horizon_y - ladder_deg * px_per_deg
|
||||
if absf(y) > radius - 12.0:
|
||||
|
||||
@@ -37,7 +37,7 @@ func _process(delta: float) -> void:
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
var font := hud_font()
|
||||
var font := ThemeDB.fallback_font
|
||||
var fraction := clampf(_value / max_value, 0.0, 1.0)
|
||||
var reading := value_format % _value
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ func _process(delta: float) -> void:
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
var font := hud_font()
|
||||
var font := ThemeDB.fallback_font
|
||||
var center_x := size.x / 2.0
|
||||
var px_per_deg := size.x / VISIBLE_RANGE
|
||||
|
||||
|
||||
@@ -23,11 +23,3 @@ static func angle_delta_deg(from: float, to: float) -> float:
|
||||
|
||||
func _smoothing_weight(delta: float) -> float:
|
||||
return 1.0 - exp(-SMOOTHING * delta) # frame-rate independent
|
||||
|
||||
|
||||
# Procedural draw calls do not automatically consume a Control's theme font;
|
||||
# resolve it explicitly so every instrument uses the same packaged typeface
|
||||
# as ordinary Labels instead of ThemeDB's debug-looking fallback.
|
||||
func hud_font() -> Font:
|
||||
var font := get_theme_default_font()
|
||||
return font if font else ThemeDB.fallback_font
|
||||
|
||||
+42
-28
@@ -117,8 +117,7 @@ const ATTITUDE_THRESHOLD = 1.0 # degrees
|
||||
const THRUST_THRESHOLD = 1.0 # percent
|
||||
|
||||
var _engine_cores: Array[MeshInstance3D] = []
|
||||
var _engine_plumes: Array[GPUParticles3D] = []
|
||||
var _turbo_flames: Array[GPUParticles3D] = []
|
||||
var _engine_flames: Array[MeshInstance3D] = []
|
||||
var _engine_lights: Array[OmniLight3D] = []
|
||||
var _impact_sparks: GPUParticles3D
|
||||
|
||||
@@ -215,7 +214,7 @@ func _build_movement_vfx() -> void:
|
||||
for x in [-0.42, 0.42]:
|
||||
var engine_pos := Vector3(x, -0.05, 1.42)
|
||||
|
||||
var core_mat := _vfx_material(Color(0.35, 0.85, 1.0, 1.0), 1.0)
|
||||
var core_mat := _vfx_material(Color(1.0, 0.48, 0.1, 1.0), 1.0)
|
||||
var core_mesh := SphereMesh.new()
|
||||
core_mesh.radius = 0.11
|
||||
core_mesh.height = 0.22
|
||||
@@ -228,28 +227,37 @@ func _build_movement_vfx() -> void:
|
||||
add_child(core)
|
||||
_engine_cores.append(core)
|
||||
|
||||
var plume := _make_particles(
|
||||
"EnginePlumeL" if x < 0.0 else "EnginePlumeR",
|
||||
Color(0.3, 0.82, 1.0, 0.72), Vector2(0.16, 0.42), 36, 0.24,
|
||||
Vector3(0, 0, 1), 12.0, 2.0, 5.0
|
||||
)
|
||||
plume.position = engine_pos + Vector3(0, 0, 0.08)
|
||||
add_child(plume)
|
||||
_engine_plumes.append(plume)
|
||||
|
||||
var turbo := _make_particles(
|
||||
"TurboFlameL" if x < 0.0 else "TurboFlameR",
|
||||
Color(0.78, 0.34, 1.0, 0.9), Vector2(0.22, 0.72), 48, 0.18,
|
||||
Vector3(0, 0, 1), 7.0, 6.0, 10.0
|
||||
)
|
||||
turbo.position = engine_pos + Vector3(0, 0, 0.12)
|
||||
add_child(turbo)
|
||||
_turbo_flames.append(turbo)
|
||||
# A single conventional orange flame replaces the layered particle plume
|
||||
# and separate purple turbo effect. Turbo only lengthens and brightens the
|
||||
# same flame, keeping the engine silhouette simple and readable.
|
||||
var flame_mat := StandardMaterial3D.new()
|
||||
flame_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
flame_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
||||
flame_mat.cull_mode = BaseMaterial3D.CULL_DISABLED
|
||||
flame_mat.albedo_color = Color(1.0, 0.34, 0.04, 0.92)
|
||||
flame_mat.emission_enabled = true
|
||||
flame_mat.emission = Color(1.0, 0.16, 0.015)
|
||||
flame_mat.emission_energy_multiplier = 2.0
|
||||
var flame_mesh := CylinderMesh.new()
|
||||
flame_mesh.top_radius = 0.015
|
||||
flame_mesh.bottom_radius = 0.14
|
||||
flame_mesh.height = 1.0
|
||||
flame_mesh.radial_segments = 12
|
||||
flame_mesh.material = flame_mat
|
||||
var flame := MeshInstance3D.new()
|
||||
flame.name = "EngineFlameL" if x < 0.0 else "EngineFlameR"
|
||||
flame.position = engine_pos + Vector3(0, 0, 0.3)
|
||||
flame.rotation_degrees.x = 90.0
|
||||
flame.mesh = flame_mesh
|
||||
flame.visible = false
|
||||
flame.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
|
||||
add_child(flame)
|
||||
_engine_flames.append(flame)
|
||||
|
||||
var light := OmniLight3D.new()
|
||||
light.name = "EngineLightL" if x < 0.0 else "EngineLightR"
|
||||
light.position = engine_pos
|
||||
light.light_color = Color(0.3, 0.75, 1.0)
|
||||
light.light_color = Color(1.0, 0.32, 0.08)
|
||||
light.omni_range = 3.5
|
||||
light.omni_attenuation = 2.0
|
||||
light.shadow_enabled = false
|
||||
@@ -308,18 +316,24 @@ func _make_particles(
|
||||
|
||||
|
||||
func _update_movement_vfx() -> void:
|
||||
if _engine_plumes.is_empty():
|
||||
if _engine_flames.is_empty():
|
||||
return
|
||||
# These are the two rear main engines, so lateral/vertical maneuvering jets
|
||||
# must not make them flare. Reverse thrust also comes from separate attitude
|
||||
# jets conceptually; only positive Z drives this rear-facing plume.
|
||||
# jets conceptually; only positive Z drives this rear-facing flame.
|
||||
var thrust := clampf(maxf(_current_action.thrust.z, 0.0), 0.0, 1.0)
|
||||
var turbo := _current_action.turbo and thrust > 0.05
|
||||
for i in _engine_plumes.size():
|
||||
_engine_plumes[i].emitting = thrust > 0.02
|
||||
_engine_plumes[i].amount_ratio = 0.25 + thrust * 0.75
|
||||
_engine_plumes[i].speed_scale = 0.65 + thrust * 0.75
|
||||
_turbo_flames[i].emitting = turbo
|
||||
for i in _engine_flames.size():
|
||||
var flame := _engine_flames[i]
|
||||
var flame_length := 0.28 + thrust * 0.82 + (0.62 if turbo else 0.0)
|
||||
var flame_width := 0.72 + thrust * 0.32 + (0.12 if turbo else 0.0)
|
||||
flame.visible = thrust > 0.02
|
||||
flame.scale = Vector3(flame_width, flame_length, flame_width)
|
||||
# CylinderMesh is centred on local Y (rotated to ship +Z), so moving its
|
||||
# centre by half the length keeps the flame root fixed at the engine bell.
|
||||
flame.position.z = 1.48 + flame_length * 0.5
|
||||
var flame_mat := flame.mesh.material as StandardMaterial3D
|
||||
flame_mat.emission_energy_multiplier = 1.8 + thrust * 2.2 + (1.8 if turbo else 0.0)
|
||||
_engine_lights[i].light_energy = 0.35 + thrust * 2.1 + (2.3 if turbo else 0.0)
|
||||
var core_mat := _engine_cores[i].mesh.material as StandardMaterial3D
|
||||
core_mat.emission_energy_multiplier = 0.65 + thrust * 2.0 + (2.0 if turbo else 0.0)
|
||||
|
||||
@@ -183,9 +183,6 @@ func _update_speed_feel(delta: float) -> void:
|
||||
_effective_distance = lerpf(
|
||||
_effective_distance, camera_distance + _turbo_blend * turbo_distance_kick, feel_t
|
||||
)
|
||||
post_material.set_shader_parameter(
|
||||
"motion_blur_amount", _speed_blend * _speed_blend * 0.006 + _turbo_blend * 0.006
|
||||
)
|
||||
post_material.set_shader_parameter("chromatic_aberration", _turbo_blend * 0.007)
|
||||
post_material.set_shader_parameter("vignette_strength", 0.22 + _turbo_blend * 0.16)
|
||||
|
||||
@@ -233,8 +230,7 @@ func begin_goal_cut(goal_position: Vector3) -> void:
|
||||
camera.fov = 58.0
|
||||
camera.look_at(_goal_cut_look_at, Vector3.UP)
|
||||
# A hard, stationary cinematic camera must not inherit the scoring frame's
|
||||
# ship-speed smear or turbo chroma. Keep only a deliberate cinematic edge.
|
||||
post_material.set_shader_parameter("motion_blur_amount", 0.0)
|
||||
# turbo chroma; keep only a deliberate cinematic edge.
|
||||
post_material.set_shader_parameter("chromatic_aberration", 0.0)
|
||||
post_material.set_shader_parameter("vignette_strength", 0.3)
|
||||
|
||||
@@ -243,6 +239,5 @@ func end_goal_cut() -> void:
|
||||
_goal_cut_active = false
|
||||
_speed_blend = 0.0
|
||||
_turbo_blend = 0.0
|
||||
post_material.set_shader_parameter("motion_blur_amount", 0.0)
|
||||
post_material.set_shader_parameter("chromatic_aberration", 0.0)
|
||||
post_material.set_shader_parameter("vignette_strength", 0.22)
|
||||
|
||||
@@ -1,37 +1,21 @@
|
||||
shader_type canvas_item;
|
||||
render_mode unshaded;
|
||||
|
||||
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
|
||||
uniform float motion_blur_amount : hint_range(0.0, 0.03) = 0.0;
|
||||
uniform sampler2D screen_texture : hint_screen_texture, filter_linear;
|
||||
uniform float chromatic_aberration : hint_range(0.0, 0.02) = 0.0;
|
||||
uniform float vignette_strength : hint_range(0.0, 1.0) = 0.22;
|
||||
|
||||
|
||||
vec4 motion_sample(vec2 uv) {
|
||||
// A restrained centre-directed velocity smear. The camera script scales it
|
||||
// with ship speed/turbo; mipmapped screen reads soften the outer samples.
|
||||
if (motion_blur_amount < 0.0001) {
|
||||
return textureLod(screen_texture, uv, 0.0);
|
||||
}
|
||||
vec2 step_uv = (uv - vec2(0.5)) * motion_blur_amount;
|
||||
vec4 color = textureLod(screen_texture, uv, 0.0) * 0.36;
|
||||
color += textureLod(screen_texture, uv - step_uv * 0.35, 0.5) * 0.25;
|
||||
color += textureLod(screen_texture, uv - step_uv * 0.7, 1.0) * 0.21;
|
||||
color += textureLod(screen_texture, uv - step_uv, 1.5) * 0.18;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void fragment() {
|
||||
vec2 radial = UV - vec2(0.5);
|
||||
vec2 chroma = radial * chromatic_aberration;
|
||||
vec4 center = motion_sample(UV);
|
||||
vec4 center = texture(screen_texture, UV);
|
||||
vec3 color = center.rgb;
|
||||
// The branch is driven by one uniform for the whole draw, so non-turbo
|
||||
// frames avoid eight redundant screen taps without causing warp divergence.
|
||||
// frames avoid two redundant screen taps without causing warp divergence.
|
||||
if (chromatic_aberration > 0.0001) {
|
||||
color.r = motion_sample(UV + chroma).r;
|
||||
color.b = motion_sample(UV - chroma).b;
|
||||
color.r = texture(screen_texture, UV + chroma).r;
|
||||
color.b = texture(screen_texture, UV - chroma).b;
|
||||
}
|
||||
|
||||
// Aspect-correct vignette, always subtle and tightened slightly on turbo.
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
[gd_resource type="Theme" load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="FontFile" path="res://assets/fonts/Orbitron-Medium.ttf" id="1_font"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_panel"]
|
||||
bg_color = Color(0.035, 0.05, 0.085, 0.76)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.3, 0.7, 1, 0.38)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
content_margin_left = 12.0
|
||||
content_margin_top = 8.0
|
||||
content_margin_right = 12.0
|
||||
content_margin_bottom = 8.0
|
||||
|
||||
[resource]
|
||||
default_font = ExtResource("1_font")
|
||||
default_font_size = 14
|
||||
Label/colors/font_color = Color(0.86, 0.94, 1, 1)
|
||||
Label/colors/font_shadow_color = Color(0, 0, 0, 0.72)
|
||||
Label/constants/outline_size = 1
|
||||
Label/constants/shadow_offset_x = 2
|
||||
Label/constants/shadow_offset_y = 2
|
||||
PanelContainer/styles/panel = SubResource("StyleBoxFlat_panel")
|
||||
@@ -16,14 +16,14 @@ The largest gap between this and a AAA-feeling product is presentation, not code
|
||||
|
||||
- [ ] **Audio — there is none.** Zero sound files, zero `AudioStreamPlayer` nodes, no bus layout. Needs: engine hum pitched to throttle, turbo whoosh, ball impacts scaled by collision impulse, wall scrapes, goal explosion, crowd bed, UI clicks, countdown beeps, music. Can be driven off `Ship`'s existing telemetry signals.
|
||||
- [x] SSAO/SSIL in the arena Environments — cheapest single perceived-quality win available; grounds the ships against the deck and gives the fillets and goal recesses real depth.
|
||||
- [x] VFX on anything that moves: throttle-reactive engine cores and plumes, distinct turbo flames, a speed-scaled ball trail, contact sparks and team-tinted goal bursts.
|
||||
- [x] VFX on anything that moves: throttle-reactive engine cores and simple rear flames, a speed-scaled ball trail, contact sparks and team-tinted goal bursts.
|
||||
- [x] Impact feedback — intensity-scaled screen shake, unscaled hit-stop, HUD flash and controller rumble on ball contact.
|
||||
- [x] Camera feel in `ship_camera.gd` — speed-based FOV widening, turbo kick-back and decaying impact shake.
|
||||
- [x] Goal celebration sequence: goal burst, team-tinted flash/title card, dedicated camera cut and slow-motion beat after authoritative score registration and before reset/kickoff.
|
||||
- [x] Local lighting / dynamic GI — four local pitch lights plus SDFGI provide bounce and contact lighting for the runtime-generated arena shell; the shader's `hull_fill` stand-in is retired. (The shell is generated in `_ready`, so it cannot participate in an editor LightmapGI bake.)
|
||||
- [x] Dress `arena_03` — its asteroid field now has mining stations, debris clusters and a distant planet.
|
||||
- [x] Custom font + a real `Theme` resource for the HUD. Packaged Orbitron typography, shared label styling and themed procedural-instrument text replace `ThemeDB.fallback_font`.
|
||||
- [x] Post-processing beyond glow: camera DoF plus speed-scaled motion blur, a cinematic vignette and turbo-driven chromatic aberration.
|
||||
- [ ] Custom font + a real `Theme` resource for the HUD. `ThemeDB.fallback_font` at 10-13 px reads as a debug overlay.
|
||||
- [x] Post-processing beyond glow: a cinematic vignette and turbo-driven chromatic aberration. DoF and motion blur were intentionally omitted after playtesting.
|
||||
|
||||
## Multiplayer (long term)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user