75 lines
2.9 KiB
GDScript
75 lines
2.9 KiB
GDScript
extends Node2D
|
|
|
|
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:
|
|
# The map boundary remains in world space.
|
|
draw_rect(Rect2(-WORLD_SIZE * 0.5, WORLD_SIZE), Color(0.12, 0.52, 0.68, 0.48), false, 3.0)
|
|
|