Zmiany
0
artifacts/shadow_height_errors.log
Normal file
7
artifacts/shadow_height_test.log
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org
|
||||||
|
OpenGL API 3.3.0 NVIDIA 610.88 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 4070 SUPER
|
||||||
|
|
||||||
|
[MCPRuntimeServer] port: scanning 6570-6585 (default)
|
||||||
|
[MCPRuntimeServer] listening on 127.0.0.1:6570
|
||||||
|
[MCPRegistry] runtime port 6570 registered for c:/users/tomek/documents/godot/randoloot
|
||||||
|
SURFACE WEATHER PASS: six biomes, layered shadow/weather, bounded particles, engine emission and expiry, snow wash
|
||||||
BIN
artifacts/weather_biome_0.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
40
artifacts/weather_biome_0.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://ru2hbrs0q665"
|
||||||
|
path="res://.godot/imported/weather_biome_0.png-56be56101fb8051111e1549c74b1d3f9.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biome_0.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biome_0.png-56be56101fb8051111e1549c74b1d3f9.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
artifacts/weather_biome_1.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
40
artifacts/weather_biome_1.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dsvxij3sfl7r0"
|
||||||
|
path="res://.godot/imported/weather_biome_1.png-e23eb3ba14bf6b2312ebcd08a83a2787.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biome_1.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biome_1.png-e23eb3ba14bf6b2312ebcd08a83a2787.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
artifacts/weather_biome_2.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
40
artifacts/weather_biome_2.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://d2dn14mo4fjsv"
|
||||||
|
path="res://.godot/imported/weather_biome_2.png-09f02d8dabe5cfaf52888c8d341cbad0.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biome_2.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biome_2.png-09f02d8dabe5cfaf52888c8d341cbad0.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
artifacts/weather_biome_3.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
40
artifacts/weather_biome_3.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cy5xf2gcagkpp"
|
||||||
|
path="res://.godot/imported/weather_biome_3.png-255dd2d621d148d1cf2834373e25c76c.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biome_3.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biome_3.png-255dd2d621d148d1cf2834373e25c76c.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
artifacts/weather_biome_4.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
40
artifacts/weather_biome_4.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://de0ybcp2lacgy"
|
||||||
|
path="res://.godot/imported/weather_biome_4.png-9725c1874018ea20ca0488f51ce7ce9e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biome_4.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biome_4.png-9725c1874018ea20ca0488f51ce7ce9e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
artifacts/weather_biome_5.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
40
artifacts/weather_biome_5.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b60b8my0hbfc3"
|
||||||
|
path="res://.godot/imported/weather_biome_5.png-72690658e057b3e6edf27897d3452110.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biome_5.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biome_5.png-72690658e057b3e6edf27897d3452110.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
artifacts/weather_biomes_review.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
40
artifacts/weather_biomes_review.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://wr6q0g4mk4cv"
|
||||||
|
path="res://.godot/imported/weather_biomes_review.png-87628c1fa50d238ad7389e8e4a2b1238.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/weather_biomes_review.png"
|
||||||
|
dest_files=["res://.godot/imported/weather_biomes_review.png-87628c1fa50d238ad7389e8e4a2b1238.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
0
artifacts/weather_errors.log
Normal file
7
artifacts/weather_test.log
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org
|
||||||
|
OpenGL API 3.3.0 NVIDIA 610.88 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 4070 SUPER
|
||||||
|
|
||||||
|
[MCPRuntimeServer] port: scanning 6570-6585 (default)
|
||||||
|
[MCPRuntimeServer] listening on 127.0.0.1:6571
|
||||||
|
[MCPRegistry] runtime port 6571 registered for c:/users/tomek/documents/godot/randoloot
|
||||||
|
SURFACE WEATHER PASS: six biomes, layered shadow/weather, bounded particles, engine emission and expiry, snow wash
|
||||||
@ -1138,3 +1138,11 @@ HANGAR BEZ ZAKLADEK I PRZEGLAD OKIEN — 2026-10-18
|
|||||||
- Regresja slot_unlock_test i freighter_storage_test — PASS.
|
- Regresja slot_unlock_test i freighter_storage_test — PASS.
|
||||||
- Podglad: artifacts/frigate_review_hangar_single.png.
|
- Podglad: artifacts/frigate_review_hangar_single.png.
|
||||||
Pelny przeglad: artifacts/frigate_all_windows_review.png.
|
Pelny przeglad: artifacts/frigate_all_windows_review.png.
|
||||||
|
|
||||||
|
|
||||||
|
Efekty lotu i pogoda (18.10.2026)
|
||||||
|
- Lądownik rzuca miękki cień; podczas ciągu/hamowania wznieca lokalny pył, a na wodzie rozpryski. W tundrze unosi śnieg, przy drzewach czasem liście. Na skale pyłu jest mniej. Dopalacz wzmacnia efekt.
|
||||||
|
- Cząsteczki pozostają w przestrzeni świata i samoczynnie zanikają: maksymalnie 144 cząsteczki podmuchu oraz 190 pogodowych.
|
||||||
|
- Pogoda biomów: doliny i mokradła deszcz, jesienne lasy liście, wyżyny podmuchy, kaniony pył, tundra śnieg. Natężenie przechodzi płynnie między stanami co 38–85 sekund.
|
||||||
|
- Niska mgła nad dolinami pozostaje pod statkiem. Nad sceną są delikatne opady i smugi światła; przy silnym deszczu na mokradłach rzadki słaby błysk. Korony drzew lekko kołyszą się z wiatrem.
|
||||||
|
- Istniejący ambient wiatru reaguje na natężenie pogody. Efekty są kosmetyczne i nie zmieniają szans POI ani zagrożenia.
|
||||||
|
|||||||
15
resources/effects/lander_shadow.gdshader
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
render_mode unshaded;
|
||||||
|
void fragment() {
|
||||||
|
vec2 step_uv = TEXTURE_PIXEL_SIZE*12.0;
|
||||||
|
float a = texture(TEXTURE,UV).a*0.28;
|
||||||
|
a += texture(TEXTURE,UV+step_uv*vec2(1,0)).a*0.12;
|
||||||
|
a += texture(TEXTURE,UV-step_uv*vec2(1,0)).a*0.12;
|
||||||
|
a += texture(TEXTURE,UV+step_uv*vec2(0,1)).a*0.12;
|
||||||
|
a += texture(TEXTURE,UV-step_uv*vec2(0,1)).a*0.12;
|
||||||
|
a += texture(TEXTURE,UV+step_uv).a*0.06;
|
||||||
|
a += texture(TEXTURE,UV-step_uv).a*0.06;
|
||||||
|
a += texture(TEXTURE,UV+step_uv*vec2(1,-1)).a*0.06;
|
||||||
|
a += texture(TEXTURE,UV+step_uv*vec2(-1,1)).a*0.06;
|
||||||
|
COLOR = vec4(0.02,0.035,0.03,a*0.20);
|
||||||
|
}
|
||||||
1
resources/effects/lander_shadow.gdshader.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://dh5qpdlbxshin
|
||||||
8
resources/effects/tree_wind.gdshader
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
uniform vec2 wind_direction = vec2(0.95,0.3);
|
||||||
|
uniform float wind_strength = 0.6;
|
||||||
|
void vertex() {
|
||||||
|
vec2 point = (MODEL_MATRIX*vec4(VERTEX,0.0,1.0)).xy;
|
||||||
|
float sway = sin(TIME*1.35+point.x*0.012+point.y*0.006)*0.7+sin(TIME*2.1+point.y*0.014)*0.3;
|
||||||
|
VERTEX += wind_direction*sway*wind_strength*1.5;
|
||||||
|
}
|
||||||
1
resources/effects/tree_wind.gdshader.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://b87pkow0vmcgg
|
||||||
@ -105,6 +105,7 @@ func _process(delta: float) -> void:
|
|||||||
_refresh_local()
|
_refresh_local()
|
||||||
var gust := sin(_elapsed*0.19)*1.4+sin(_elapsed*0.073)*0.8
|
var gust := sin(_elapsed*0.19)*1.4+sin(_elapsed*0.073)*0.8
|
||||||
var engine_mask := -3.0 if source.engine_thrust_active() else 0.0
|
var engine_mask := -3.0 if source.engine_thrust_active() else 0.0
|
||||||
|
if is_instance_valid(source.weather): gust += source.weather.intensity*2.5
|
||||||
_wind.volume_db = move_toward(_wind.volume_db,WIND_DB[_biome]+gust+engine_mask,delta*26)
|
_wind.volume_db = move_toward(_wind.volume_db,WIND_DB[_biome]+gust+engine_mask,delta*26)
|
||||||
var leaf_target := -60.0 if _near_trees.is_empty() else lerpf(-34,-23,_density)+gust+engine_mask
|
var leaf_target := -60.0 if _near_trees.is_empty() else lerpf(-34,-23,_density)+gust+engine_mask
|
||||||
_foliage.volume_db = move_toward(_foliage.volume_db,leaf_target,delta*8)
|
_foliage.volume_db = move_toward(_foliage.volume_db,leaf_target,delta*8)
|
||||||
|
|||||||
111
scripts/planets/surface_flight_effects.gd
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
extends Node2D
|
||||||
|
## Ground wash stays in world space after emission, independently of the lander.
|
||||||
|
const LIMIT := 144
|
||||||
|
var source: Control
|
||||||
|
var weather: Node2D
|
||||||
|
var _rng := RandomNumberGenerator.new()
|
||||||
|
var _particles: Array[Dictionary] = []
|
||||||
|
var _soft: GradientTexture2D
|
||||||
|
var _shadow: Sprite2D
|
||||||
|
var _emission := 0.0
|
||||||
|
var _tree_timer := 0.0
|
||||||
|
var _near_trees := false
|
||||||
|
var _surface_kind := "dust"
|
||||||
|
var _ground := Color("b5a17a")
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
name = "SurfaceFlightEffects"
|
||||||
|
z_index = 21
|
||||||
|
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
|
||||||
|
_rng.seed = source.progress.visit_seed ^ 0x44555354
|
||||||
|
_ground = (source.world.data.landscape.sand as Color).lerp(source.world.data.landscape.low,0.25)
|
||||||
|
var gradient := Gradient.new()
|
||||||
|
gradient.set_color(0,Color.WHITE)
|
||||||
|
gradient.set_color(1,Color(1,1,1,0))
|
||||||
|
_soft = GradientTexture2D.new()
|
||||||
|
_soft.gradient = gradient
|
||||||
|
_soft.width = 64
|
||||||
|
_soft.height = 64
|
||||||
|
_soft.fill = GradientTexture2D.FILL_RADIAL
|
||||||
|
_soft.fill_from = Vector2(0.5,0.5)
|
||||||
|
_soft.fill_to = Vector2(0.5,1)
|
||||||
|
_shadow = Sprite2D.new()
|
||||||
|
_shadow.name = "LanderShadow"
|
||||||
|
_shadow.texture = source.lander.texture
|
||||||
|
_shadow.scale = source.lander.scale*0.76
|
||||||
|
_shadow.z_index = -1
|
||||||
|
var material := ShaderMaterial.new()
|
||||||
|
material.shader = preload("res://resources/effects/lander_shadow.gdshader")
|
||||||
|
_shadow.material = material
|
||||||
|
add_child(_shadow)
|
||||||
|
|
||||||
|
func surface_kind(point: Vector2) -> String:
|
||||||
|
if int(source.world.data.landscape.index) == 5: return "snow"
|
||||||
|
var h: float = weather.terrain_height(point)
|
||||||
|
if h < 0.29 or (int(source.world.data.landscape.index) == 2 and h < 0.37): return "spray"
|
||||||
|
return "rock" if h > 0.64 else "dust"
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if not is_instance_valid(source): return
|
||||||
|
visible = not source._ending
|
||||||
|
if source._ending: return
|
||||||
|
var pose: Transform2D = source.lander.global_transform
|
||||||
|
pose.origin = source._previous_position.lerp(source.lander.position,Engine.get_physics_interpolation_fraction())
|
||||||
|
var point := pose.origin
|
||||||
|
_shadow.position = point+Vector2(48,64)
|
||||||
|
_shadow.rotation = pose.get_rotation()
|
||||||
|
_shadow.visible = source.lander.visible
|
||||||
|
_tree_timer -= delta
|
||||||
|
if _tree_timer <= 0:
|
||||||
|
_tree_timer = 0.4
|
||||||
|
_near_trees = false
|
||||||
|
for tree in source.world.data.trees:
|
||||||
|
if point.distance_squared_to(tree.position) < 170*170:
|
||||||
|
_near_trees = true
|
||||||
|
break
|
||||||
|
_surface_kind = surface_kind(point)
|
||||||
|
var thrust: bool = source.engine_thrust_active()
|
||||||
|
var brake: bool = not source._dialog.visible and Input.is_action_pressed("ship_brake") and source._motion.velocity.length() > 12
|
||||||
|
var boost: bool = source._motion.boost_active and thrust
|
||||||
|
if thrust or brake:
|
||||||
|
var rate := 60.0 if boost else (26.0 if thrust else 18.0)
|
||||||
|
if _surface_kind == "rock": rate *= 0.3
|
||||||
|
_emission += delta*rate
|
||||||
|
while _emission >= 1:
|
||||||
|
_emission -= 1
|
||||||
|
if _particles.size() < LIMIT: _emit(point,pose.get_rotation(),boost)
|
||||||
|
else: _emission = 0
|
||||||
|
for index in range(_particles.size()-1,-1,-1):
|
||||||
|
var particle: Dictionary = _particles[index]
|
||||||
|
particle.age += delta
|
||||||
|
particle.position += (particle.velocity+weather.wind*0.7)*delta
|
||||||
|
particle.velocity *= exp(-delta*1.3)
|
||||||
|
if particle.age > particle.life: _particles.remove_at(index)
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func _emit(point: Vector2, angle: float, boost: bool) -> void:
|
||||||
|
var kind := _surface_kind
|
||||||
|
if _near_trees and kind == "dust" and _rng.randf() < 0.20: kind = "leaf"
|
||||||
|
var nozzle := Vector2(_rng.randf_range(-29,29),_rng.randf_range(22,42)).rotated(angle)
|
||||||
|
var scatter := Vector2(_rng.randf_range(-32,32),_rng.randf_range(10,45)).rotated(angle)
|
||||||
|
_particles.append({"position":point+nozzle,"velocity":scatter+source._motion.velocity*0.1,"age":0.0,"life":_rng.randf_range(1.1,2.4),"size":_rng.randf_range(9,17)*(1.4 if boost else 1.0),"kind":kind,"angle":_rng.randf_range(-PI,PI)})
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
for particle in _particles:
|
||||||
|
var t := clampf(particle.age/particle.life,0,1)
|
||||||
|
var alpha := sin(t*PI)
|
||||||
|
var kind: String = particle.kind
|
||||||
|
var radius: float = particle.size*(1.0+t*1.9)
|
||||||
|
var color := _ground
|
||||||
|
color.a = alpha*0.14
|
||||||
|
if kind == "rock": color = Color(0.65,0.65,0.59,alpha*0.09)
|
||||||
|
if kind == "snow": color = Color(0.88,0.95,0.95,alpha*0.25)
|
||||||
|
if kind == "spray": color = Color(0.66,0.83,0.80,alpha*0.18)
|
||||||
|
if kind == "leaf":
|
||||||
|
draw_set_transform(particle.position,particle.angle+t*2,Vector2(1,0.45))
|
||||||
|
draw_circle(Vector2.ZERO,2.5,Color(0.49,0.35,0.17,alpha*0.7),true,-1,true)
|
||||||
|
draw_set_transform(Vector2.ZERO)
|
||||||
|
else:
|
||||||
|
draw_texture_rect(_soft,Rect2(particle.position-Vector2.ONE*radius,Vector2.ONE*radius*2),false,color)
|
||||||
|
if kind in ["spray","snow"]:
|
||||||
|
draw_circle(particle.position+Vector2(4,-7)*t,1.4,Color(color,alpha*0.38),true,-1,true)
|
||||||
1
scripts/planets/surface_flight_effects.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://b8fcnm6unlmjh
|
||||||
@ -10,6 +10,8 @@ var progress: Resource
|
|||||||
var world: Node2D
|
var world: Node2D
|
||||||
var lander: Sprite2D
|
var lander: Sprite2D
|
||||||
var camera: Camera2D
|
var camera: Camera2D
|
||||||
|
var weather: Node2D
|
||||||
|
var flight_effects: Node2D
|
||||||
var _hp: ProgressBar
|
var _hp: ProgressBar
|
||||||
var _cargo: Label
|
var _cargo: Label
|
||||||
var _threat: Label
|
var _threat: Label
|
||||||
@ -97,6 +99,15 @@ func _ready() -> void:
|
|||||||
atmosphere.set_script(preload("res://scripts/planets/surface_clouds.gd"))
|
atmosphere.set_script(preload("res://scripts/planets/surface_clouds.gd"))
|
||||||
atmosphere.seed_value = progress.visit_seed
|
atmosphere.seed_value = progress.visit_seed
|
||||||
viewport.add_child(atmosphere)
|
viewport.add_child(atmosphere)
|
||||||
|
weather = Node2D.new()
|
||||||
|
weather.set_script(preload("res://scripts/planets/surface_weather.gd"))
|
||||||
|
weather.source = self
|
||||||
|
viewport.add_child(weather)
|
||||||
|
flight_effects = Node2D.new()
|
||||||
|
flight_effects.set_script(preload("res://scripts/planets/surface_flight_effects.gd"))
|
||||||
|
flight_effects.source = self
|
||||||
|
flight_effects.weather = weather
|
||||||
|
viewport.add_child(flight_effects)
|
||||||
var nature_audio := Node.new()
|
var nature_audio := Node.new()
|
||||||
nature_audio.name = "SurfaceAudio"
|
nature_audio.name = "SurfaceAudio"
|
||||||
nature_audio.set_script(preload("res://scripts/planets/surface_audio.gd"))
|
nature_audio.set_script(preload("res://scripts/planets/surface_audio.gd"))
|
||||||
|
|||||||
22
scripts/planets/surface_tree_canopy.gd
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
extends Node2D
|
||||||
|
var world: Node2D
|
||||||
|
var wind_material: ShaderMaterial
|
||||||
|
func _ready() -> void:
|
||||||
|
name = "WindCanopies"
|
||||||
|
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
|
||||||
|
wind_material = ShaderMaterial.new()
|
||||||
|
wind_material.shader = preload("res://resources/effects/tree_wind.gdshader")
|
||||||
|
material = wind_material
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
for tree in world.data.trees:
|
||||||
|
var shade := float(tree.shade)
|
||||||
|
var color: Color = Color(shade,shade,shade)*world.data.landscape.trees
|
||||||
|
if int(world.data.profile.temperature) < -10: color = color.lerp(Color("d1e1da"),0.4)
|
||||||
|
elif int(world.data.profile.temperature) > 40: color = color.lerp(Color("c6a86b"),0.28)
|
||||||
|
var variant := int(tree.get("variant",-1))
|
||||||
|
var texture: Texture2D = world._tree if variant < 0 else world._nature[variant]
|
||||||
|
var extent := Vector2(tree.size,tree.size*texture.get_height()/texture.get_width())
|
||||||
|
draw_set_transform(tree.position,tree.rotation)
|
||||||
|
draw_texture_rect(texture,Rect2(-extent*0.5,extent),false,color)
|
||||||
|
draw_set_transform(Vector2.ZERO)
|
||||||
1
scripts/planets/surface_tree_canopy.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://bqq7jv5t84lsa
|
||||||
130
scripts/planets/surface_weather.gd
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
extends Node2D
|
||||||
|
## World-space weather: bounded particle pool, slow transitions, no screen-space noise.
|
||||||
|
const LIMIT := 190
|
||||||
|
var source: Control
|
||||||
|
var intensity := 0.15
|
||||||
|
var target_intensity := 0.2
|
||||||
|
var wind := Vector2(18,6)
|
||||||
|
var mode := "wind"
|
||||||
|
var _rng := RandomNumberGenerator.new()
|
||||||
|
var _time := 0.0
|
||||||
|
var _transition := 36.0
|
||||||
|
var _storm_timer := 40.0
|
||||||
|
var _flash := 0.0
|
||||||
|
var _emission := 0.0
|
||||||
|
var _particles: Array[Dictionary] = []
|
||||||
|
var _fog: Array[Sprite2D] = []
|
||||||
|
var _biome := 0
|
||||||
|
var _bolt := PackedVector2Array()
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
name = "SurfaceWeather"
|
||||||
|
z_index = 80
|
||||||
|
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
|
||||||
|
_rng.seed = source.progress.visit_seed ^ 0x57454154
|
||||||
|
_biome = int(source.world.data.landscape.index)
|
||||||
|
mode = ["rain","leaves","rain","wind","dust","snow"][_biome]
|
||||||
|
target_intensity = 0.38 if _biome in [2,5] else 0.18
|
||||||
|
var material := ShaderMaterial.new()
|
||||||
|
material.shader = preload("res://resources/effects/cloud_mist.gdshader")
|
||||||
|
for index in 12:
|
||||||
|
var fog := Sprite2D.new()
|
||||||
|
fog.texture = preload("res://assets/planets/cloud_mist.png")
|
||||||
|
fog.material = material
|
||||||
|
fog.position = Vector2(index%4*1100-1650,index/4*1100-1100)
|
||||||
|
fog.rotation = _rng.randf_range(-PI,PI)
|
||||||
|
fog.scale = Vector2.ONE*_rng.randf_range(650,1100)/fog.texture.get_width()
|
||||||
|
fog.z_as_relative = false
|
||||||
|
fog.z_index = 18
|
||||||
|
fog.modulate = Color(0.79,0.84,0.79,0.0)
|
||||||
|
add_child(fog)
|
||||||
|
_fog.append(fog)
|
||||||
|
|
||||||
|
func _center() -> Vector2:
|
||||||
|
return source.camera.get_screen_center_position()
|
||||||
|
|
||||||
|
func _extent() -> Vector2:
|
||||||
|
return Vector2(get_viewport_rect().size)/source.camera.zoom*0.5+Vector2(140,140)
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if not is_instance_valid(source) or source._ending: return
|
||||||
|
_time += delta
|
||||||
|
_transition -= delta
|
||||||
|
if _transition <= 0:
|
||||||
|
_transition = _rng.randf_range(38,85)
|
||||||
|
target_intensity = _rng.randf_range(0.12,0.85) if _biome in [2,4,5] else _rng.randf_range(0.0,0.58)
|
||||||
|
intensity = move_toward(intensity,target_intensity,delta*0.018)
|
||||||
|
var gust := 0.75+0.25*sin(_time*0.19)+0.12*sin(_time*0.57)
|
||||||
|
wind = Vector2(22,7).rotated(sin(_time*0.045)*0.25)*(0.7+intensity*1.4)*gust
|
||||||
|
if is_instance_valid(source.world.tree_canopy):
|
||||||
|
source.world.tree_canopy.wind_material.set_shader_parameter("wind_direction",wind.normalized())
|
||||||
|
source.world.tree_canopy.wind_material.set_shader_parameter("wind_strength",0.5+intensity*1.4)
|
||||||
|
for index in _fog.size():
|
||||||
|
var fog := _fog[index]
|
||||||
|
fog.position += wind*delta*0.24
|
||||||
|
fog.position.x = wrapf(fog.position.x,-2350,2350)
|
||||||
|
fog.position.y = wrapf(fog.position.y,-2100,2100)
|
||||||
|
var h := terrain_height(fog.position)
|
||||||
|
var valley := 1.0-smoothstep(0.42,0.65,h)
|
||||||
|
fog.modulate.a = (0.035+intensity*0.14)*valley*(1.0 if _biome in [0,1,2,5] else 0.3)
|
||||||
|
if _biome == 4:
|
||||||
|
for fog in _fog: fog.modulate = Color(0.76,0.62,0.39,fog.modulate.a+intensity*0.04)
|
||||||
|
_emission += delta*([13,12,34,8,24,34][_biome])*intensity
|
||||||
|
while _emission >= 1:
|
||||||
|
_emission -= 1
|
||||||
|
if _particles.size() < LIMIT: _spawn()
|
||||||
|
var center := _center()
|
||||||
|
var extent := _extent()
|
||||||
|
for index in range(_particles.size()-1,-1,-1):
|
||||||
|
var p: Dictionary = _particles[index]
|
||||||
|
p.age += delta
|
||||||
|
p.position += (p.velocity+wind)*delta
|
||||||
|
if p.age > p.life or absf(p.position.x-center.x) > extent.x*1.3 or absf(p.position.y-center.y) > extent.y*1.3:
|
||||||
|
_particles.remove_at(index)
|
||||||
|
_flash = move_toward(_flash,0,delta*0.8)
|
||||||
|
_storm_timer -= delta
|
||||||
|
if mode == "rain" and intensity > 0.66 and _storm_timer <= 0:
|
||||||
|
_storm_timer = _rng.randf_range(28,65)
|
||||||
|
_flash = 0.045
|
||||||
|
var point := center+Vector2(_rng.randf_range(-extent.x*0.8,extent.x*0.8),-extent.y*0.7)
|
||||||
|
_bolt = PackedVector2Array([point,point+Vector2(15,30),point+Vector2(4,45),point+Vector2(31,80)])
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func terrain_height(point: Vector2) -> float:
|
||||||
|
var x := clampi(int((point.x+1920)/40),0,95)
|
||||||
|
var y := clampi(int((point.y+1920)/40),0,95)
|
||||||
|
return float(source.world.data.heights[y*96+x])
|
||||||
|
|
||||||
|
func _spawn() -> void:
|
||||||
|
var extent := _extent()
|
||||||
|
var point := _center()+Vector2(_rng.randf_range(-extent.x,extent.x),_rng.randf_range(-extent.y,extent.y))
|
||||||
|
var velocity := Vector2(-25,250) if mode == "rain" else Vector2(_rng.randf_range(-8,8),_rng.randf_range(7,22))
|
||||||
|
_particles.append({"position":point,"velocity":velocity,"age":0.0,"life":_rng.randf_range(3,6),"size":_rng.randf_range(1.1,2.8),"phase":_rng.randf_range(0,TAU)})
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
for p in _particles:
|
||||||
|
var alpha := sin(clampf(p.age/p.life,0,1)*PI)
|
||||||
|
var point: Vector2 = p.position+Vector2(sin(_time*1.6+p.phase)*3,0)
|
||||||
|
match mode:
|
||||||
|
"rain":
|
||||||
|
draw_line(point,point+Vector2(-2,12),Color(0.73,0.83,0.86,alpha*0.26),0.8,true)
|
||||||
|
if terrain_height(point) < 0.32: draw_arc(point+Vector2(-2,12),p.size*1.5,0,TAU,12,Color(0.73,0.83,0.86,alpha*0.10),0.7,true)
|
||||||
|
"snow": draw_circle(point,p.size,Color(0.91,0.96,0.97,alpha*0.55),true,-1,true)
|
||||||
|
"leaves":
|
||||||
|
draw_set_transform(point,sin(_time+p.phase),Vector2(1,0.45))
|
||||||
|
draw_circle(Vector2.ZERO,p.size,Color(0.61,0.43,0.19,alpha*0.55),true,-1,true)
|
||||||
|
_draw_reset()
|
||||||
|
_: draw_line(point,point+wind.normalized()*p.size*7,Color(0.80,0.72,0.53,alpha*0.11),1,true)
|
||||||
|
var center := _center()
|
||||||
|
var extent := _extent()
|
||||||
|
# Very faint broad sun shafts, confined to damp wooded climates.
|
||||||
|
if _biome in [0,1,2]:
|
||||||
|
for index in 2:
|
||||||
|
var start := center+Vector2(-extent.x*0.7+index*extent.x*0.9,-extent.y)
|
||||||
|
draw_colored_polygon(PackedVector2Array([start,start+Vector2(50,0),start+Vector2(380,extent.y*2),start+Vector2(210,extent.y*2)]),Color(0.95,0.87,0.62,0.012*(1.0-intensity)))
|
||||||
|
if _flash > 0:
|
||||||
|
draw_rect(Rect2(center-extent,extent*2),Color(0.78,0.84,1.0,_flash))
|
||||||
|
draw_polyline(_bolt,Color(0.83,0.90,1.0,_flash*6),1.2,true)
|
||||||
|
|
||||||
|
func _draw_reset() -> void:
|
||||||
|
draw_set_transform(Vector2.ZERO)
|
||||||
1
scripts/planets/surface_weather.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://d3omfrwkxohc6
|
||||||
@ -4,6 +4,7 @@ const BUILDING_SCALE := preload("res://scripts/planets/surface_scenery.gd").BUIL
|
|||||||
const GENERATOR := preload("res://scripts/planets/surface_generator.gd")
|
const GENERATOR := preload("res://scripts/planets/surface_generator.gd")
|
||||||
var data: Dictionary
|
var data: Dictionary
|
||||||
var terrain: ImageTexture
|
var terrain: ImageTexture
|
||||||
|
var tree_canopy: Node2D
|
||||||
var _nature: Array[AtlasTexture] = []
|
var _nature: Array[AtlasTexture] = []
|
||||||
var _tree: Texture2D
|
var _tree: Texture2D
|
||||||
var _poi_sprites: Dictionary = {}
|
var _poi_sprites: Dictionary = {}
|
||||||
@ -54,6 +55,10 @@ func _ready() -> void:
|
|||||||
mountains.data = data
|
mountains.data = data
|
||||||
mountains.z_index = -1
|
mountains.z_index = -1
|
||||||
add_child(mountains)
|
add_child(mountains)
|
||||||
|
tree_canopy = Node2D.new()
|
||||||
|
tree_canopy.set_script(preload("res://scripts/planets/surface_tree_canopy.gd"))
|
||||||
|
tree_canopy.world = self
|
||||||
|
add_child(tree_canopy)
|
||||||
for poi in data.pois:
|
for poi in data.pois:
|
||||||
var sprite := Sprite2D.new()
|
var sprite := Sprite2D.new()
|
||||||
if poi.kind == "deposit":
|
if poi.kind == "deposit":
|
||||||
@ -146,15 +151,6 @@ func _draw() -> void:
|
|||||||
_draw_prop(_nature[int(detail.variant)], detail.position, detail.size, detail.rotation, Color(shade,shade,shade))
|
_draw_prop(_nature[int(detail.variant)], detail.position, detail.size, detail.rotation, Color(shade,shade,shade))
|
||||||
for rock in data.rocks:
|
for rock in data.rocks:
|
||||||
_draw_prop(_nature[int(rock.get("variant",4))],rock.position,rock.size,rock.rotation,Color.WHITE)
|
_draw_prop(_nature[int(rock.get("variant",4))],rock.position,rock.size,rock.rotation,Color.WHITE)
|
||||||
for tree in data.trees:
|
|
||||||
var shade := float(tree.shade)
|
|
||||||
var color: Color = Color(shade,shade,shade)*data.landscape.trees
|
|
||||||
if int(data.profile.temperature) < -10:
|
|
||||||
color = color.lerp(Color("d1e1da"), 0.4)
|
|
||||||
elif int(data.profile.temperature) > 40:
|
|
||||||
color = color.lerp(Color("c6a86b"), 0.28)
|
|
||||||
var variant := int(tree.get("variant", -1))
|
|
||||||
_draw_prop(_tree if variant < 0 else _nature[variant], tree.position, tree.size, tree.rotation, color)
|
|
||||||
# Small landing beacon.
|
# Small landing beacon.
|
||||||
draw_circle(Vector2.ZERO, 50, Color(0.5, 0.85, 0.8, 0.12))
|
draw_circle(Vector2.ZERO, 50, Color(0.5, 0.85, 0.8, 0.12))
|
||||||
draw_arc(Vector2.ZERO, 48, 0, TAU, 48, Color("8cd9c2"), 2, true)
|
draw_arc(Vector2.ZERO, 48, 0, TAU, 48, Color("8cd9c2"), 2, true)
|
||||||
|
|||||||
52
tests/previews/surface_weather_preview.gd
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
var sheet := Image.create(1280,1080,false,Image.FORMAT_RGBA8)
|
||||||
|
var progress: Resource = GameState.captain.expedition
|
||||||
|
for biome in 6:
|
||||||
|
var profile: Dictionary = preload("res://scripts/planets/planet_profiles.gd").generate(99,biome,"Pogoda / biom %d" % (biome+1))
|
||||||
|
profile.temperature = 75 if biome == 4 else (-35 if biome == 5 else 20)
|
||||||
|
progress.lander_hp = 100
|
||||||
|
assert(progress.begin_visit(profile))
|
||||||
|
progress.visit_seed = 200+biome
|
||||||
|
var surface := Control.new()
|
||||||
|
surface.set_script(preload("res://scripts/planets/surface_screen.gd"))
|
||||||
|
surface.captain = GameState.captain
|
||||||
|
surface.progress = progress
|
||||||
|
add_child(surface)
|
||||||
|
surface.set_process(false)
|
||||||
|
surface.set_physics_process(false)
|
||||||
|
surface.weather.set_process(false)
|
||||||
|
surface.flight_effects.set_process(false)
|
||||||
|
surface.weather.intensity = 0.75
|
||||||
|
surface.weather.target_intensity = 0.75
|
||||||
|
assert(surface.weather._biome == biome)
|
||||||
|
assert(surface.weather.z_index > surface.lander.z_index)
|
||||||
|
assert(surface.flight_effects.z_index < surface.lander.z_index)
|
||||||
|
Input.action_press("ship_thrust")
|
||||||
|
for frame in 240:
|
||||||
|
surface.weather._process(1.0/60)
|
||||||
|
surface.flight_effects._process(1.0/60)
|
||||||
|
assert(surface.weather._particles.size() > 0)
|
||||||
|
assert(surface.weather._particles.size() <= surface.weather.LIMIT)
|
||||||
|
assert(surface.flight_effects._particles.size() > 0)
|
||||||
|
assert(surface.flight_effects._particles.size() <= surface.flight_effects.LIMIT)
|
||||||
|
assert(surface.flight_effects._shadow.texture == surface.lander.texture)
|
||||||
|
for frame in 5: await get_tree().process_frame
|
||||||
|
await RenderingServer.frame_post_draw
|
||||||
|
var image: Image = get_viewport().get_texture().get_image()
|
||||||
|
assert(image.save_png("res://artifacts/weather_biome_%d.png" % biome) == OK)
|
||||||
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
|
image.resize(640,360,Image.INTERPOLATE_LANCZOS)
|
||||||
|
sheet.blit_rect(image,Rect2i(0,0,640,360),Vector2i(biome%2*640,biome/2*360))
|
||||||
|
Input.action_release("ship_thrust")
|
||||||
|
for frame in 180: surface.flight_effects._process(1.0/60)
|
||||||
|
assert(surface.flight_effects._particles.is_empty(),"Ground wash must expire after stopping engines")
|
||||||
|
if biome == 5: assert(surface.flight_effects.surface_kind(Vector2.ZERO) == "snow")
|
||||||
|
progress.finish_visit(GameState.captain,false)
|
||||||
|
surface.queue_free()
|
||||||
|
await get_tree().process_frame
|
||||||
|
await get_tree().process_frame
|
||||||
|
assert(sheet.save_png("res://artifacts/weather_biomes_review.png") == OK)
|
||||||
|
print("SURFACE WEATHER PASS: six biomes, layered shadow/weather, bounded particles, engine emission and expiry, snow wash")
|
||||||
|
get_tree().quit()
|
||||||
1
tests/previews/surface_weather_preview.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cd8q7210dpt26
|
||||||
6
tests/previews/surface_weather_preview.tscn
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[gd_scene load_steps=2 format=3]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://tests/previews/surface_weather_preview.gd" id="1"]
|
||||||
|
|
||||||
|
[node name="SurfaceWeatherPreview" type="Node"]
|
||||||
|
script = ExtResource("1")
|
||||||