Efejty swietlen gwiazdy
This commit is contained in:
parent
dc9f97d1cc
commit
b5fdf0cecc
@ -6,6 +6,7 @@ func _ready() -> void:
|
|||||||
enemy = get_parent() as CharacterBody2D
|
enemy = get_parent() as CharacterBody2D
|
||||||
top_level = true
|
top_level = true
|
||||||
z_index = 30
|
z_index = 30
|
||||||
|
light_mask = 4
|
||||||
_update_position()
|
_update_position()
|
||||||
|
|
||||||
func _process(_delta: float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
|
|||||||
@ -56,6 +56,7 @@ func configure(player: CharacterBody2D, ship_texture: Texture2D) -> void:
|
|||||||
var visual_size := get_visual_size()
|
var visual_size := get_visual_size()
|
||||||
_sprite.scale = Vector2.ONE * (visual_size / largest_dimension)
|
_sprite.scale = Vector2.ONE * (visual_size / largest_dimension)
|
||||||
_sprite.modulate = Color("ffc785") if loot_tier == 1 else Color.WHITE
|
_sprite.modulate = Color("ffc785") if loot_tier == 1 else Color.WHITE
|
||||||
|
preload("res://scripts/game/ship_shadow.gd").attach_to(_sprite)
|
||||||
|
|
||||||
func get_visual_size() -> float:
|
func get_visual_size() -> float:
|
||||||
return 112.0 if loot_tier == 2 else (68.0 if loot_tier == 1 else 56.0)
|
return 112.0 if loot_tier == 2 else (68.0 if loot_tier == 1 else 56.0)
|
||||||
|
|||||||
@ -100,6 +100,7 @@ func _ready() -> void:
|
|||||||
_sprite.texture = ship_texture
|
_sprite.texture = ship_texture
|
||||||
var largest_dimension := maxf(ship_texture.get_width(), ship_texture.get_height())
|
var largest_dimension := maxf(ship_texture.get_width(), ship_texture.get_height())
|
||||||
_sprite.scale = Vector2.ONE * (64.0 / largest_dimension)
|
_sprite.scale = Vector2.ONE * (64.0 / largest_dimension)
|
||||||
|
preload("res://scripts/game/ship_shadow.gd").attach_to(_sprite)
|
||||||
# Inventory children have already applied the restored equipment bonuses.
|
# Inventory children have already applied the restored equipment bonuses.
|
||||||
hull = max_hull
|
hull = max_hull
|
||||||
shields = max_shields
|
shields = max_shields
|
||||||
|
|||||||
54
scripts/game/ship_shadow.gd
Normal file
54
scripts/game/ship_shadow.gd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
# Cache one simplified silhouette per texture, shared by all ships of that type.
|
||||||
|
static var _silhouettes: Dictionary = {}
|
||||||
|
|
||||||
|
static func attach_to(sprite: Sprite2D) -> void:
|
||||||
|
if sprite.texture == null:
|
||||||
|
return
|
||||||
|
sprite.light_mask = 2
|
||||||
|
if sprite.has_node("ShipShadow"):
|
||||||
|
return
|
||||||
|
var texture := sprite.texture
|
||||||
|
var key := texture.get_instance_id()
|
||||||
|
if not _silhouettes.has(key):
|
||||||
|
var image := texture.get_image()
|
||||||
|
if image == null or image.is_empty():
|
||||||
|
return
|
||||||
|
if image.is_compressed():
|
||||||
|
image.decompress()
|
||||||
|
var original_size := Vector2(image.get_size())
|
||||||
|
var factor := minf(1.0, 128.0 / maxf(original_size.x, original_size.y))
|
||||||
|
image.resize(maxi(1, roundi(original_size.x * factor)), maxi(1, roundi(original_size.y * factor)), Image.INTERPOLATE_BILINEAR)
|
||||||
|
var bitmap := BitMap.new()
|
||||||
|
bitmap.create_from_image_alpha(image, 0.25)
|
||||||
|
var polygons := bitmap.opaque_to_polygons(Rect2i(Vector2i.ZERO, image.get_size()), 1.5)
|
||||||
|
var silhouette := PackedVector2Array()
|
||||||
|
var largest_area := 0.0
|
||||||
|
for polygon in polygons:
|
||||||
|
var area := _polygon_area(polygon)
|
||||||
|
if area > largest_area:
|
||||||
|
largest_area = area
|
||||||
|
silhouette = polygon
|
||||||
|
var image_scale := original_size / Vector2(image.get_size())
|
||||||
|
for index in silhouette.size():
|
||||||
|
silhouette[index] = silhouette[index] * image_scale - original_size * 0.5
|
||||||
|
_silhouettes[key] = silhouette
|
||||||
|
var points: PackedVector2Array = _silhouettes[key]
|
||||||
|
if points.size() < 3:
|
||||||
|
return
|
||||||
|
var polygon := OccluderPolygon2D.new()
|
||||||
|
polygon.polygon = points
|
||||||
|
polygon.cull_mode = OccluderPolygon2D.CULL_DISABLED
|
||||||
|
var occluder := LightOccluder2D.new()
|
||||||
|
occluder.name = "ShipShadow"
|
||||||
|
occluder.occluder = polygon
|
||||||
|
occluder.occluder_light_mask = 1
|
||||||
|
occluder.show_behind_parent = true
|
||||||
|
sprite.add_child(occluder)
|
||||||
|
|
||||||
|
static func _polygon_area(points: PackedVector2Array) -> float:
|
||||||
|
var area := 0.0
|
||||||
|
for index in points.size():
|
||||||
|
area += points[index].cross(points[(index + 1) % points.size()])
|
||||||
|
return absf(area) * 0.5
|
||||||
1
scripts/game/ship_shadow.gd.uid
Normal file
1
scripts/game/ship_shadow.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://b2jj0dueysvnp
|
||||||
53
scripts/game/star_lighting.gd
Normal file
53
scripts/game/star_lighting.gd
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
const LIGHT_RADIUS := 3400.0
|
||||||
|
const LIGHT_ENERGY := 0.28
|
||||||
|
const SHIP_LIGHT_ENERGY := 0.16
|
||||||
|
const LIGHT_COLOR := Color(1.0, 0.93, 0.82)
|
||||||
|
|
||||||
|
static func attach_to(star: Node2D) -> void:
|
||||||
|
var gradient := Gradient.new()
|
||||||
|
gradient.offsets = PackedFloat32Array([0.0, 0.25, 0.65, 1.0])
|
||||||
|
gradient.colors = PackedColorArray([Color.WHITE, Color(1, 1, 1, 0.9), Color(1, 1, 1, 0.5), Color(1, 1, 1, 0)])
|
||||||
|
var texture := GradientTexture2D.new()
|
||||||
|
texture.gradient = gradient
|
||||||
|
texture.width = 512
|
||||||
|
texture.height = 512
|
||||||
|
texture.fill = GradientTexture2D.FILL_RADIAL
|
||||||
|
texture.fill_from = Vector2(0.5, 0.5)
|
||||||
|
texture.fill_to = Vector2(0.5, 0.0)
|
||||||
|
|
||||||
|
var light := PointLight2D.new()
|
||||||
|
light.name = "StarLight"
|
||||||
|
light.texture = texture
|
||||||
|
light.texture_scale = LIGHT_RADIUS * 2.0 / texture.width
|
||||||
|
light.color = LIGHT_COLOR
|
||||||
|
light.energy = LIGHT_ENERGY
|
||||||
|
light.range_item_cull_mask = 1
|
||||||
|
light.shadow_enabled = true
|
||||||
|
light.shadow_item_cull_mask = 1
|
||||||
|
light.shadow_filter = Light2D.SHADOW_FILTER_PCF5
|
||||||
|
light.shadow_filter_smooth = 2.0
|
||||||
|
star.add_child(light)
|
||||||
|
|
||||||
|
# A separate mask lights hulls without their own silhouettes darkening them.
|
||||||
|
var hull_light := PointLight2D.new()
|
||||||
|
hull_light.name = "HullLight"
|
||||||
|
hull_light.texture = texture
|
||||||
|
hull_light.texture_scale = light.texture_scale
|
||||||
|
hull_light.color = LIGHT_COLOR
|
||||||
|
hull_light.energy = SHIP_LIGHT_ENERGY
|
||||||
|
hull_light.range_item_cull_mask = 2
|
||||||
|
star.add_child(hull_light)
|
||||||
|
|
||||||
|
var glow := Sprite2D.new()
|
||||||
|
glow.name = "StarGlow"
|
||||||
|
glow.texture = texture
|
||||||
|
glow.scale = Vector2.ONE * (float(star.get("radius")) * 5.0 / texture.width)
|
||||||
|
glow.modulate = Color(LIGHT_COLOR, 0.09)
|
||||||
|
glow.z_index = -1
|
||||||
|
var material := CanvasItemMaterial.new()
|
||||||
|
material.blend_mode = CanvasItemMaterial.BLEND_MODE_ADD
|
||||||
|
material.light_mode = CanvasItemMaterial.LIGHT_MODE_UNSHADED
|
||||||
|
glow.material = material
|
||||||
|
star.add_child(glow)
|
||||||
1
scripts/game/star_lighting.gd.uid
Normal file
1
scripts/game/star_lighting.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://kmnxv1hp273t
|
||||||
@ -14,8 +14,15 @@ func _ready() -> void:
|
|||||||
sprite.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
|
sprite.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
|
||||||
var longest_side := maxf(body_texture.get_width(), body_texture.get_height())
|
var longest_side := maxf(body_texture.get_width(), body_texture.get_height())
|
||||||
sprite.scale = Vector2.ONE * (radius * 2.0 / longest_side)
|
sprite.scale = Vector2.ONE * (radius * 2.0 / longest_side)
|
||||||
|
if is_star:
|
||||||
|
var material := CanvasItemMaterial.new()
|
||||||
|
material.light_mode = CanvasItemMaterial.LIGHT_MODE_UNSHADED
|
||||||
|
sprite.material = material
|
||||||
add_child(sprite)
|
add_child(sprite)
|
||||||
|
if is_star:
|
||||||
|
preload("res://scripts/game/star_lighting.gd").attach_to(self)
|
||||||
_label = Label.new()
|
_label = Label.new()
|
||||||
|
_label.light_mask = 4
|
||||||
_label.position = Vector2(-160, radius + 14)
|
_label.position = Vector2(-160, radius + 14)
|
||||||
_label.size = Vector2(320, 54)
|
_label.size = Vector2(320, 54)
|
||||||
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
|||||||
@ -13,6 +13,12 @@ func _ready() -> void:
|
|||||||
get_tree().current_scene = game
|
get_tree().current_scene = game
|
||||||
_freeze(game)
|
_freeze(game)
|
||||||
_assert_boss_and_health(game)
|
_assert_boss_and_health(game)
|
||||||
|
var star := game.get_node("CelestialBodies/CentralStar")
|
||||||
|
var star_light: PointLight2D = star.get_node("StarLight")
|
||||||
|
assert(star_light.shadow_enabled and star_light.energy < 0.5)
|
||||||
|
assert(star_light.position == Vector2.ZERO)
|
||||||
|
assert(star_light.shadow_filter == Light2D.SHADOW_FILTER_PCF5)
|
||||||
|
assert(star.get_node("HullLight").get("range_item_cull_mask") == 2)
|
||||||
assert(GameState.system_level == 1 and int(game.call("get_remaining_enemies")) == 5)
|
assert(GameState.system_level == 1 and int(game.call("get_remaining_enemies")) == 5)
|
||||||
assert(not game.has_node("WeaponTestTarget"))
|
assert(not game.has_node("WeaponTestTarget"))
|
||||||
assert(game.get_node("CelestialBodies").get_child_count() >= 2)
|
assert(game.get_node("CelestialBodies").get_child_count() >= 2)
|
||||||
@ -146,10 +152,14 @@ func _freeze(game: Node2D) -> void:
|
|||||||
game.set_physics_process(false)
|
game.set_physics_process(false)
|
||||||
game.get_node("PlayerShip").set_physics_process(false)
|
game.get_node("PlayerShip").set_physics_process(false)
|
||||||
game.get_node("PlayerShip/WeaponController").set_physics_process(false)
|
game.get_node("PlayerShip/WeaponController").set_physics_process(false)
|
||||||
|
assert(game.get_node("PlayerShip/Sprite2D/ShipShadow") is LightOccluder2D)
|
||||||
for enemy in get_tree().get_nodes_in_group("enemies"):
|
for enemy in get_tree().get_nodes_in_group("enemies"):
|
||||||
if game.is_ancestor_of(enemy):
|
if game.is_ancestor_of(enemy):
|
||||||
var data: Dictionary = game.get("system_data")
|
var data: Dictionary = game.get("system_data")
|
||||||
assert(enemy.get_node("Sprite2D").get("texture") == game.ENEMY_TEXTURES[int(data["enemy_texture_index"])])
|
assert(enemy.get_node("Sprite2D").get("texture") == game.ENEMY_TEXTURES[int(data["enemy_texture_index"])])
|
||||||
|
var shadow: LightOccluder2D = enemy.get_node("Sprite2D/ShipShadow")
|
||||||
|
assert(shadow.occluder.polygon.size() >= 3)
|
||||||
|
assert(shadow.global_scale.is_equal_approx(enemy.get_node("Sprite2D").global_scale))
|
||||||
enemy.set_physics_process(false)
|
enemy.set_physics_process(false)
|
||||||
|
|
||||||
func _assert_boss_and_health(game: Node2D) -> void:
|
func _assert_boss_and_health(game: Node2D) -> void:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user