Background

This commit is contained in:
Tomasz Boruc 2026-10-15 18:51:38 +02:00
parent d2bf034d98
commit 4d4403d6d1
6 changed files with 162 additions and 13 deletions

View File

@ -0,0 +1,13 @@
# Space parallax artwork
Generated with the built-in imagegen tool on 2026-10-15.
Files: deep_space.png (far background), nebula_dust.png (transparent cloud overlay).
Consumer: scripts/game/space_level_background.gd.
Camera-relative speeds: distant painting 0.04, dust 0.14, stars 0.18 / 0.42.
Prompt — deep_space.png:
Use case: stylized-concept. Create a final production game background texture, landscape 3:2, high resolution. Realistic painterly deep outer space, vast distant indigo and muted teal nebula filaments, faint violet dust, two small very distant spiral galaxies with delicate warm cores, sparse fine distant stars. Elegant astronomical realism with painterly detail, deep near-black navy negative space across the center for a top-down spaceship game. Low-key lighting, restrained contrast, no huge bright blobs, no planets, no ships, no text, no interface, no border. Clouds soft and diffuse at all four edges, edges almost black so repeated tiles remain subtle. This is the far background parallax layer.
Prompt — nebula_dust.png:
Use case: stylized-concept. Production transparent overlay texture for a realistic painterly outer-space game parallax foreground, landscape 3:2. Only a few wispy small nebula clouds of muted blue teal and violet interstellar dust, translucent feathery irregular filaments, widely separated with large empty transparent areas, off-center composition. A handful of tiny soft starlight points embedded in clouds. Realistic astronomical painting, subtle dim luminosity, intricate fine texture. True alpha transparent background around and between clouds, soft alpha cloud edges. All four image edges fully transparent with generous margin. No solid background, no checkerboard, no planets, no spacecraft, no text, no frame.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

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

View File

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

@ -1,18 +1,74 @@
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 DUST_TEXTURE := preload("res://assets/background/space/nebula_dust.png")
const STAR_TILE := Vector2(2048.0, 1536.0)
var _far_sprite: Sprite2D
func _ready() -> void:
# Let the engine synchronize parallax with the interpolated camera transform.
# No camera sampling or per-frame rebuilding of draw commands is needed.
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
var distant := _make_layer("DistantGalaxies", 0.04)
_far_sprite = Sprite2D.new()
_far_sprite.texture = FAR_TEXTURE
_far_sprite.modulate = Color(0.8, 0.85, 0.95)
distant.add_child(_far_sprite)
_resize_background()
get_viewport().size_changed.connect(_resize_background)
var dust := _make_layer("NebulaDust", 0.14)
dust.repeat_size = Vector2(DUST_TEXTURE.get_size())
dust.repeat_times = 3
var dust_sprite := Sprite2D.new()
dust_sprite.texture = DUST_TEXTURE
dust_sprite.centered = false
dust_sprite.modulate = Color(0.65, 0.75, 0.9, 0.22)
dust.add_child(dust_sprite)
_make_stars("DistantStars", 0.18, 210, 0)
_make_stars("NearStars", 0.42, 90, 1)
func _make_layer(layer_name: String, speed: float) -> Parallax2D:
var layer := Parallax2D.new()
layer.name = layer_name
layer.scroll_scale = Vector2.ONE * speed
add_child(layer)
return layer
func _resize_background() -> void:
var view_size := get_viewport_rect().size
var camera := get_viewport().get_camera_2d()
if is_instance_valid(camera):
view_size /= camera.zoom
# Native resolution at 720p; retain aspect ratio and cover camera travel.
_far_sprite.position = view_size * 0.5
var required := view_size + WORLD_SIZE * 0.04 + Vector2(32.0, 32.0)
var ratio := required / FAR_TEXTURE.get_size()
_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:
var rng := RandomNumberGenerator.new()
rng.seed = GameState.system_seed + seed_offset
var svg := '<svg xmlns="http://www.w3.org/2000/svg" width="2048" height="1536">'
for index in count:
var point := Vector2(rng.randf_range(4.0, STAR_TILE.x - 4.0), rng.randf_range(4.0, STAR_TILE.y - 4.0))
svg += '<circle cx="%.3f" cy="%.3f" r="%.3f" fill="#b8d4ff" opacity="%.3f"/>' % [point.x, point.y, rng.randf_range(0.5, 1.4), rng.randf_range(0.18, 0.65)]
svg += '</svg>'
var image := Image.new()
if image.load_svg_from_string(svg) != OK:
return
image.generate_mipmaps()
var layer := _make_layer(layer_name, speed)
layer.repeat_size = STAR_TILE
layer.repeat_times = 3
var sprite := Sprite2D.new()
sprite.texture = ImageTexture.create_from_image(image)
sprite.centered = false
layer.add_child(sprite)
func _draw() -> void: func _draw() -> void:
var half_size := WORLD_SIZE * 0.5 # The map boundary remains in world space.
draw_rect(Rect2(-half_size, WORLD_SIZE), Color("050b18"), true) draw_rect(Rect2(-WORLD_SIZE * 0.5, WORLD_SIZE), Color(0.12, 0.52, 0.68, 0.48), false, 3.0)
var rng := RandomNumberGenerator.new()
rng.seed = GameState.system_seed
for index in 420:
var point := Vector2(
rng.randf_range(-half_size.x + 35.0, half_size.x - 35.0),
rng.randf_range(-half_size.y + 35.0, half_size.y - 35.0)
)
var radius := rng.randf_range(0.7, 2.0)
var color := Color(0.58, 0.76, 1.0, rng.randf_range(0.2, 0.72))
draw_circle(point, radius, color)
draw_rect(Rect2(-half_size, WORLD_SIZE), Color(0.12, 0.52, 0.68, 0.48), false, 3.0)