Nowe tła

This commit is contained in:
Tomasz Boruc 2026-10-15 22:22:52 +02:00
parent d7581d2f70
commit e857aa8181
17 changed files with 324 additions and 53 deletions

View File

@ -0,0 +1,23 @@
# Space background variants
Generated with built-in imagegen. The original deep_space.png remains the first background. New artwork cycles through systems 2–6, then repeats every six systems. Native Parallax2D motion, dust and star layers are unchanged.
## teal_veil.png
Use case: stylized-concept. Final production landscape 3:2 background texture for a top-down space RPG, at least 1536 by 1024 pixels. Realistic painterly astronomical space art, extremely fine sharp dust filaments and delicate stars. Preserve dark near-black navy central negative space for readable spaceship combat. Rich detail at outer regions, restrained low-key luminosity, no overexposed masses, no planets, no ships, no text, no interface, no border. Entire image is deep space. Variant: turquoise veil. Vast elegant teal and cyan nebula curtains drifting diagonally from the lower left to the upper right, deep blue dark dust channels, a very small distant warm spiral galaxy near the upper left. Dense intricate wisps but broad dark center, subdued silver starlight.
## crimson_rift.png
Use case: stylized-concept. Final production landscape 3:2 background texture for a top-down space RPG, at least 1536 by 1024 pixels. Realistic painterly astronomical space art, extremely fine sharp dust filaments and delicate stars. Preserve dark near-black navy central negative space for readable spaceship combat. Rich detail at outer regions, restrained low-key luminosity, no overexposed masses, no planets, no ships, no text, no interface, no border. Entire image is deep space. Variant: crimson rift. Deep ruby and burgundy emission nebula filaments around a sweeping dark interstellar dust rift. Muted copper edges and faint magenta distant star clusters. A tiny faraway edge-on galaxy in one outer quadrant. Mysterious deep space, asymmetric painted composition, dark broad center, no giant bright object.
## amber_expanse.png
Use case: stylized-concept. Final production landscape 3:2 background texture for a top-down space RPG, at least 1536 by 1024 pixels. Realistic painterly astronomical space art, extremely fine sharp dust filaments and delicate stars. Preserve dark near-black navy central negative space for readable spaceship combat. Rich detail at outer regions, restrained low-key luminosity, no overexposed masses, no planets, no ships, no text, no interface, no border. Entire image is deep space. Variant: amber expanse. Immense fine warm gold and bronze interstellar clouds sweeping around a dark navy central void, delicate smoky copper filaments, subtle deep blue counterlight and sparse pale gold stars, a small distant galaxy embedded near the outer right edge. Atmospheric and ancient, luminosity restrained, richly layered natural astrophotographic structure.
## violet_spiral.png
Use case: stylized-concept. Final production landscape 3:2 background texture for a top-down space RPG, at least 1536 by 1024 pixels. Realistic painterly astronomical space art, extremely fine sharp dust filaments and delicate stars. Preserve dark near-black navy central negative space for readable spaceship combat. Rich detail at outer regions, restrained low-key luminosity, no overexposed masses, no planets, no ships, no text, no interface, no border. Entire image is deep space. Variant: violet spiral. A distant gently inclined spiral galaxy with violet and lilac arms in the far upper-right quadrant, moderate small size and dim warm center, vast muted plum and indigo wisps curving along the outer image edges, exceptionally fine cosmic dust lanes, soft blue distant star clusters. Majority central space remains dark, mysterious and spacious, no huge galactic core.
## frozen_void.png
Use case: stylized-concept. Final production landscape 3:2 background texture for a top-down space RPG, at least 1536 by 1024 pixels. Realistic painterly astronomical space art, extremely fine sharp dust filaments and delicate stars. Preserve dark near-black navy central negative space for readable spaceship combat. Rich detail at outer regions, restrained low-key luminosity, no overexposed masses, no planets, no ships, no text, no interface, no border. Entire image is deep space. Variant: frozen void. Vast nearly black deep intergalactic space, cold slate-blue and silver-white cirrus-like interstellar dust along the left and lower outer regions, very faint icy cyan tendrils, two tiny remote galaxies and sparse crisp distant stars. Quiet, austere and spacious. Broad clean near-black central combat area, high-detail subtle cloud structure, low saturation and low brightness.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ds3otmcvnigjl"
path="res://.godot/imported/amber_expanse.png-3f0d05b567168730e5a7f3165b1f792e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/background/space/amber_expanse.png"
dest_files=["res://.godot/imported/amber_expanse.png-3f0d05b567168730e5a7f3165b1f792e.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=true
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://4le8obqsnyls"
path="res://.godot/imported/crimson_rift.png-64a6106d291393c89fe92f833ccc307a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/background/space/crimson_rift.png"
dest_files=["res://.godot/imported/crimson_rift.png-64a6106d291393c89fe92f833ccc307a.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=true
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ctuoqueipre6u"
path="res://.godot/imported/frozen_void.png-27db06ffcfc6a21d856449611e6a0f6a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/background/space/frozen_void.png"
dest_files=["res://.godot/imported/frozen_void.png-27db06ffcfc6a21d856449611e6a0f6a.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=true
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ca7inlb4051jg"
path="res://.godot/imported/teal_veil.png-c156d68322d84804e2034f3ec932d377.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/background/space/teal_veil.png"
dest_files=["res://.godot/imported/teal_veil.png-c156d68322d84804e2034f3ec932d377.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=true
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ba4150mb4y0ks"
path="res://.godot/imported/violet_spiral.png-353286ec4f5d83fdeddcc8a4d50b4cbc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/background/space/violet_spiral.png"
dest_files=["res://.godot/imported/violet_spiral.png-353286ec4f5d83fdeddcc8a4d50b4cbc.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=true
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

View File

@ -242,7 +242,7 @@ func _layout_debug() -> void:
var top := _captain_panel.position.y + _captain_panel.size.y + 6.0 var top := _captain_panel.position.y + _captain_panel.size.y + 6.0
if is_instance_valid(_passive_skills): if is_instance_valid(_passive_skills):
_passive_skills.position = Vector2(_captain_panel.position.x, top) _passive_skills.position = Vector2(_captain_panel.position.x, top)
_passive_skills.size = Vector2(320, _passive_skills.get_combined_minimum_size().y) _passive_skills.size = Vector2(36, _passive_skills.get_combined_minimum_size().y)
if _passive_skills.visible: if _passive_skills.visible:
top += _passive_skills.size.y + 8.0 top += _passive_skills.size.y + 8.0
debug_toggle.position = Vector2(12, top) debug_toggle.position = Vector2(12, top)
@ -463,53 +463,13 @@ func _refresh_passive_skills() -> void:
var rank := GameState.captain.get_skill_rank(skill) var rank := GameState.captain.get_skill_rank(skill)
if rank <= 0 or bool(catalog.DATA[skill]["active"]): if rank <= 0 or bool(catalog.DATA[skill]["active"]):
continue continue
var accent := Color(catalog.DATA[skill]["color"])
var card := PanelContainer.new()
card.name = skill
card.custom_minimum_size = Vector2(320, 54)
card.tooltip_text = catalog.description(skill, rank)
var style := StyleBoxFlat.new()
style.bg_color = Color(0.025, 0.042, 0.064, 0.94)
style.border_color = accent.darkened(0.6)
style.set_border_width_all(1)
style.border_width_left = 2
style.set_corner_radius_all(7)
style.set_content_margin_all(8)
card.add_theme_stylebox_override("panel", style)
_passive_skills.add_child(card)
var row := HBoxContainer.new()
row.add_theme_constant_override("separation", 10)
card.add_child(row)
var icon := Button.new() var icon := Button.new()
icon.name = skill
icon.set_script(preload("res://scripts/ui/captain_skill_button.gd")) icon.set_script(preload("res://scripts/ui/captain_skill_button.gd"))
icon.call("configure", catalog.icon(skill), accent) icon.call("configure", catalog.icon(skill), Color(catalog.DATA[skill]["color"]))
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
icon.disabled = true icon.disabled = true
row.add_child(icon) icon.mouse_default_cursor_shape = Control.CURSOR_HELP
var contents := VBoxContainer.new() icon.tooltip_text = "%s · poziom %d / 3\n%s" % [catalog.DATA[skill]["name"], rank, catalog.description(skill, rank)]
contents.size_flags_horizontal = Control.SIZE_EXPAND_FILL _passive_skills.add_child(icon)
contents.add_theme_constant_override("separation", 3)
row.add_child(contents)
var header := HBoxContainer.new()
contents.add_child(header)
var title := _passive_label(catalog.DATA[skill]["name"], 14, Color("dfedf4"))
title.size_flags_horizontal = Control.SIZE_EXPAND_FILL
header.add_child(title)
header.add_child(_passive_label("●".repeat(rank) + "○".repeat(3 - rank), 10, accent))
var value := roundi(GameState.captain.get_skill_bonus(skill) * 100)
var summary := ""
match skill:
"business_shark": summary = "−%d%% kosztów zakupów" % value
"efficient_magazine": summary = "−%d%% zużycia amunicji" % value
"miner": summary = "+%d surowca / asteroidę" % roundi(GameState.captain.get_skill_bonus(skill))
contents.add_child(_passive_label(summary, 12, accent))
_passive_skills.visible = _passive_skills.get_child_count() > 0 _passive_skills.visible = _passive_skills.get_child_count() > 0
_layout_debug.call_deferred() _layout_debug.call_deferred()
func _passive_label(text: String, font_size: int, color: Color) -> Label:
var label := Label.new()
label.text = text
label.add_theme_font_override("font", ThemeDB.fallback_font)
label.add_theme_font_size_override("font_size", font_size)
label.add_theme_color_override("font_color", color)
return label

View File

@ -1,7 +1,14 @@
extends Node2D extends Node2D
const WORLD_SIZE := Vector2(5200.0, 3600.0) const WORLD_SIZE := Vector2(5200.0, 3600.0)
const FAR_TEXTURE := preload("res://assets/background/space/deep_space.png") const BACKGROUND_PATHS := [
"res://assets/background/space/deep_space.png",
"res://assets/background/space/teal_veil.png",
"res://assets/background/space/crimson_rift.png",
"res://assets/background/space/amber_expanse.png",
"res://assets/background/space/violet_spiral.png",
"res://assets/background/space/frozen_void.png",
]
const DUST_TEXTURE := preload("res://assets/background/space/nebula_dust.png") const DUST_TEXTURE := preload("res://assets/background/space/nebula_dust.png")
const STAR_TILE := Vector2(2048.0, 1536.0) const STAR_TILE := Vector2(2048.0, 1536.0)
@ -13,7 +20,9 @@ func _ready() -> void:
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
var distant := _make_layer("DistantGalaxies", 0.04) var distant := _make_layer("DistantGalaxies", 0.04)
_far_sprite = Sprite2D.new() _far_sprite = Sprite2D.new()
_far_sprite.texture = FAR_TEXTURE # Only the artwork changes between systems; parallax layers stay identical.
var background_index := posmod(GameState.system_level - 1, BACKGROUND_PATHS.size())
_far_sprite.texture = load(BACKGROUND_PATHS[background_index]) as Texture2D
_far_sprite.modulate = Color(0.8, 0.85, 0.95) _far_sprite.modulate = Color(0.8, 0.85, 0.95)
distant.add_child(_far_sprite) distant.add_child(_far_sprite)
_resize_background() _resize_background()
@ -45,7 +54,7 @@ func _resize_background() -> void:
# Native resolution at 720p; retain aspect ratio and cover camera travel. # Native resolution at 720p; retain aspect ratio and cover camera travel.
_far_sprite.position = view_size * 0.5 _far_sprite.position = view_size * 0.5
var required := view_size + WORLD_SIZE * 0.04 + Vector2(32.0, 32.0) var required := view_size + WORLD_SIZE * 0.04 + Vector2(32.0, 32.0)
var ratio := required / FAR_TEXTURE.get_size() var ratio := required / _far_sprite.texture.get_size()
_far_sprite.scale = Vector2.ONE * maxf(1.0, maxf(ratio.x, ratio.y)) _far_sprite.scale = Vector2.ONE * maxf(1.0, maxf(ratio.x, ratio.y))
func _make_stars(layer_name: String, speed: float, count: int, seed_offset: int) -> void: func _make_stars(layer_name: String, speed: float, count: int, seed_offset: int) -> void:

View File

@ -13,9 +13,9 @@ var max_range := 800.0
var weapon_kind := ItemDefinition.WeaponKind.PLASMA var weapon_kind := ItemDefinition.WeaponKind.PLASMA
var homing_target: Node2D var homing_target: Node2D
var missile_homing := true var missile_homing := true
var homing_turn_acceleration := 2.3 var homing_turn_acceleration := 5.0
var homing_max_turn_speed := 1.7 var homing_max_turn_speed := 3.0
var missile_steering_acceleration := 520.0 var missile_steering_acceleration := 1400.0
var target_acquisition_range := 360.0 var target_acquisition_range := 360.0
var seeker_arm_delay := 0.35 var seeker_arm_delay := 0.35
var _flight_velocity := Vector2.ZERO var _flight_velocity := Vector2.ZERO
@ -83,7 +83,7 @@ func _physics_process(delta: float) -> void:
PI PI
) )
desired_turn_velocity = clampf( desired_turn_velocity = clampf(
angle_error * 2.0, angle_error * 4.0,
-homing_max_turn_speed, -homing_max_turn_speed,
homing_max_turn_speed homing_max_turn_speed
) )

View File

@ -0,0 +1,72 @@
extends Node2D
const PROJECTILE := preload("res://scenes/game/weapon_projectile.tscn")
func _ready() -> void:
seed(1234)
# Both stationary and crossing targets should be intercepted on the first pass.
for target_velocity in [Vector2.ZERO, Vector2(0, 55)]:
var target := CharacterBody2D.new()
target.position = Vector2(350, 70)
target.velocity = target_velocity
add_child(target)
var missile := _missile(target, 1200.0)
var closest := INF
for step in 240:
var previous: Vector2 = missile.position
target.position += target_velocity / 120.0
missile._physics_process(1.0 / 120.0)
var near := Geometry2D.get_closest_point_to_segment(target.position, previous, missile.position)
closest = minf(closest, near.distance_to(target.position))
assert(absf(missile._turn_velocity) <= missile.homing_max_turn_speed + 0.001)
if closest < 18.0 or missile.is_queued_for_deletion():
break
assert(closest < 18.0, "Missile missed a reachable intercept: %.2f" % closest)
missile.free()
target.free()
# Compare actual flight direction against the previous turn limits.
var side_target := Node2D.new()
side_target.position = Vector2(100, 200)
add_child(side_target)
var faster := _missile(side_target, 600.0)
var previous := _missile(side_target, 600.0)
previous.homing_turn_acceleration = 2.3
previous.homing_max_turn_speed = 1.7
previous.missile_steering_acceleration = 520.0
for step in 48:
faster._physics_process(1.0 / 120.0)
previous._physics_process(1.0 / 120.0)
assert(faster._heading > previous._heading * 1.5)
assert(faster._flight_velocity.angle() > previous._flight_velocity.angle() * 1.5)
assert(faster.homing_target == side_target)
faster.free()
previous.free()
side_target.free()
# Preserve the original pursuit behavior beyond acquisition range.
var far_target := Node2D.new()
far_target.position = Vector2(5000, 0)
far_target.add_to_group("enemies")
add_child(far_target)
var limited := _missile(far_target, 200.0)
limited._has_locked_target = true
for step in 120:
limited._physics_process(1.0 / 120.0)
if limited.is_queued_for_deletion():
break
assert(not limited.is_queued_for_deletion() and limited.homing_target == far_target)
assert(limited._has_locked_target)
limited.free()
far_target.free()
print("MISSILE_GUIDANCE_TEST: PASS (stationary and moving intercepts, faster heading and actual flight turn, original target pursuit)")
get_tree().quit()
func _missile(target: Node2D, flight_range: float) -> Area2D:
var missile := PROJECTILE.instantiate() as Area2D
missile.configure(Vector2.ZERO, Vector2.RIGHT, ItemDefinition.WeaponKind.MISSILE, 400.0, 10.0, flight_range, target)
missile.collision_mask = 0
add_child(missile)
missile.set_physics_process(false)
missile.set_process(false)
return missile

View File

@ -0,0 +1 @@
uid://2y4073uore6t

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://tests/abilities/missile_guidance_test.gd" id="1"]
[node name="MissileGuidanceTest" type="Node2D"]
script = ExtResource("1")