101 lines
4 KiB
GDScript3
101 lines
4 KiB
GDScript3
|
|
extends Node2D
|
||
|
|
|
||
|
|
# Forgejo #79: a small "+N" with the resource's own mark, rising and fading
|
||
|
|
# where the fleet picked something up.
|
||
|
|
#
|
||
|
|
# Collecting used to be entirely silent - a rock vanished and a number in the
|
||
|
|
# corner of the screen changed. Which number, and by how much, was left for
|
||
|
|
# the player to notice on their own. This says it at the point it happened,
|
||
|
|
# in the resource's own colour, and gets out of the way.
|
||
|
|
#
|
||
|
|
# Built from the SAME glyph scene the resource tables and transfer rows use
|
||
|
|
# (ResourceDefinition.glyph_scene), so a new material added to the catalog
|
||
|
|
# gets a correct pickup mark with no work here - and can never end up with
|
||
|
|
# one mark in the HUD and a different one in the world.
|
||
|
|
|
||
|
|
const RESOURCE_DEFINITIONS = preload("res://ResourceDefinitions.gd")
|
||
|
|
# Deliberately NO class_name, and the constructor below loads this file by
|
||
|
|
# path rather than naming the class. A global class-name identifier - even a
|
||
|
|
# script's own, inside its own static function - needs the class cache already
|
||
|
|
# warm, and it is not when this is reached indirectly through a preview scene
|
||
|
|
# loading Main.tscn. That failed to compile outright, taking Rock and the gas
|
||
|
|
# vents down with it. Callers preload the path too; see Rock.gd.
|
||
|
|
const SELF_PATH: String = "res://ResourcePickupVFX.gd"
|
||
|
|
|
||
|
|
const RISE_DISTANCE: float = 46.0
|
||
|
|
const DURATION: float = 0.85
|
||
|
|
const GLYPH_SIZE: float = 22.0
|
||
|
|
const DIGIT_HEIGHT: float = 20.0
|
||
|
|
# Held fully opaque for the first part of its life, so the eye has time to
|
||
|
|
# catch it before it starts going.
|
||
|
|
const FADE_START: float = 0.45
|
||
|
|
|
||
|
|
var age: float = 0.0
|
||
|
|
var colour: Color = Color.WHITE
|
||
|
|
var start_y: float = 0.0
|
||
|
|
|
||
|
|
|
||
|
|
static func spawn(parent: Node, world_position: Vector2, resource_type: String,
|
||
|
|
amount: int) -> void:
|
||
|
|
if amount <= 0:
|
||
|
|
return
|
||
|
|
var vfx: Node2D = (load(SELF_PATH) as GDScript).new()
|
||
|
|
vfx.position = world_position
|
||
|
|
vfx.build(resource_type, amount)
|
||
|
|
parent.add_child(vfx)
|
||
|
|
|
||
|
|
|
||
|
|
func build(resource_type: String, amount: int) -> void:
|
||
|
|
var definition: Resource = RESOURCE_DEFINITIONS.get_definition(resource_type)
|
||
|
|
colour = definition.color if definition != null else Color.WHITE
|
||
|
|
|
||
|
|
if definition != null and definition.glyph_scene != null:
|
||
|
|
var glyph: Control = definition.glyph_scene.instantiate()
|
||
|
|
glyph.colour = definition.color
|
||
|
|
# Anchors first. The glyph scenes are authored as full-rect Controls
|
||
|
|
# for the panels that host them, and Godot recomputes the size of any
|
||
|
|
# Control with non-equal opposite anchors right after _ready() - so
|
||
|
|
# assigning size without this is overwritten, with a warning, the
|
||
|
|
# moment it enters the tree.
|
||
|
|
glyph.set_anchors_preset(Control.PRESET_TOP_LEFT)
|
||
|
|
glyph.size = Vector2(GLYPH_SIZE, GLYPH_SIZE)
|
||
|
|
glyph.position = Vector2(-2.0, -GLYPH_SIZE * 0.5)
|
||
|
|
add_child(glyph)
|
||
|
|
|
||
|
|
# show_icon off: the resource's own glyph is already beside it, and
|
||
|
|
# NeonNumber's built-in mark is the ore hexagon whatever the amount is.
|
||
|
|
var number := NeonNumber.new()
|
||
|
|
number.show_icon = false
|
||
|
|
number.amount = amount
|
||
|
|
number.digit_height = DIGIT_HEIGHT
|
||
|
|
number.glow_color = colour
|
||
|
|
number.core_color = colour.darkened(0.8)
|
||
|
|
number.size = Vector2(60.0, DIGIT_HEIGHT)
|
||
|
|
number.position = Vector2(GLYPH_SIZE + 4.0, -DIGIT_HEIGHT * 0.5)
|
||
|
|
add_child(number)
|
||
|
|
|
||
|
|
start_y = position.y
|
||
|
|
z_index = 40
|
||
|
|
|
||
|
|
|
||
|
|
func _process(delta: float) -> void:
|
||
|
|
age += delta
|
||
|
|
var t: float = age / DURATION
|
||
|
|
if t >= 1.0:
|
||
|
|
queue_free()
|
||
|
|
return
|
||
|
|
# Eases out: quick off the mark, drifting by the end.
|
||
|
|
position.y = start_y - RISE_DISTANCE * (1.0 - pow(1.0 - t, 2.0))
|
||
|
|
modulate.a = 1.0 if t < FADE_START else 1.0 - (t - FADE_START) / (1.0 - FADE_START)
|
||
|
|
queue_redraw()
|
||
|
|
|
||
|
|
|
||
|
|
func _draw() -> void:
|
||
|
|
# The plus sign, drawn here rather than as a third child - it is two
|
||
|
|
# strokes and giving it its own node would cost more than it saves.
|
||
|
|
var centre := Vector2(-12.0, 0.0)
|
||
|
|
var arm: float = 5.0
|
||
|
|
NeonDraw.draw_glowing_line(self, centre - Vector2(arm, 0.0), centre + Vector2(arm, 0.0),
|
||
|
|
colour, 1.0, 0.5, colour.darkened(0.8))
|
||
|
|
NeonDraw.draw_glowing_line(self, centre - Vector2(0.0, arm), centre + Vector2(0.0, arm),
|
||
|
|
colour, 1.0, 0.5, colour.darkened(0.8))
|