Fogo e fumaça
Dois emissores empilhados com rampas de cor diferentes, uma chama aditiva e uma coluna de fumaça acima dela. Clique para soprar uma brisa nos dois.
O editor acima está rodando este projeto. Mude uma linha e ele recarrega.
Classes do Godot usadas
CPUParticles2DGradientCanvasItemMaterial
O código
scripts/main.gd
extends Node
const FIRE_RISE: float = -110.0
const SMOKE_RISE: float = -40.0
const BREEZE: float = 120.0
var fire: CPUParticles2D
var smoke: CPUParticles2D
var windy: bool = false
func _ready() -> void:
_add_background()
var view: Vector2 = get_viewport().get_visible_rect().size
var base: Vector2 = Vector2(view.x * 0.5, view.y * 0.78)
var dot: GradientTexture2D = _make_dot()
_add_brazier(base)
smoke = CPUParticles2D.new()
smoke.position = base - Vector2(0, 150)
smoke.texture = dot
smoke.amount = 80
smoke.lifetime = 2.8
smoke.preprocess = 2.8
smoke.emission_shape = CPUParticles2D.EMISSION_SHAPE_RECTANGLE
smoke.emission_rect_extents = Vector2(24, 6)
smoke.direction = Vector2(0, -1)
smoke.spread = 14.0
smoke.initial_velocity_min = 40.0
smoke.initial_velocity_max = 95.0
smoke.gravity = Vector2(0, SMOKE_RISE)
smoke.angular_velocity_min = -35.0
smoke.angular_velocity_max = 35.0
smoke.scale_amount_min = 1.8
smoke.scale_amount_max = 4.0
smoke.scale_amount_curve = _make_growth_curve()
smoke.color_ramp = _make_ramp(
PackedFloat32Array([0.0, 0.3, 1.0]),
PackedColorArray([Color(0.44, 0.46, 0.54, 0.0), Color(0.44, 0.46, 0.54, 0.45), Color(0.3, 0.31, 0.38, 0.0)])
)
add_child(smoke)
fire = CPUParticles2D.new()
fire.position = base
fire.texture = dot
fire.amount = 160
fire.lifetime = 1.3
fire.preprocess = 1.3
fire.emission_shape = CPUParticles2D.EMISSION_SHAPE_RECTANGLE
fire.emission_rect_extents = Vector2(32, 5)
fire.direction = Vector2(0, -1)
fire.spread = 16.0
fire.initial_velocity_min = 105.0
fire.initial_velocity_max = 210.0
fire.gravity = Vector2(0, FIRE_RISE)
fire.damping_min = 10.0
fire.damping_max = 45.0
fire.scale_amount_min = 1.0
fire.scale_amount_max = 2.1
fire.scale_amount_curve = _make_shrink_curve()
fire.color_ramp = _make_ramp(
PackedFloat32Array([0.0, 0.3, 0.7, 1.0]),
PackedColorArray([Color(1.0, 0.9, 0.6, 0.34), Color(0.95, 0.8, 0.45, 0.32), Color(0.99, 0.45, 0.42, 0.26), Color(0.55, 0.18, 0.18, 0.0)])
)
fire.material = _make_additive()
add_child(fire)
print('click to switch the breeze on and off, the smoke leans further than the flame')
func _unhandled_input(event: InputEvent) -> void:
if not (event is InputEventMouseButton and event.pressed):
return
windy = not windy
var push: float = BREEZE if windy else 0.0
fire.gravity = Vector2(push, FIRE_RISE)
smoke.gravity = Vector2(push * 1.6, SMOKE_RISE)
func _add_brazier(base: Vector2) -> void:
var size: Vector2 = Vector2(170, 28)
var brazier: Polygon2D = Polygon2D.new()
brazier.polygon = PackedVector2Array([-size * 0.5, Vector2(size.x, -size.y) * 0.5, size * 0.5, Vector2(-size.x, size.y) * 0.5])
brazier.color = Color('#2a2f3d')
brazier.position = base + Vector2(0, 14)
add_child(brazier)
func _make_growth_curve() -> Curve:
var curve: Curve = Curve.new()
curve.add_point(Vector2(0.0, 0.25))
curve.add_point(Vector2(1.0, 1.0))
return curve
func _make_shrink_curve() -> Curve:
var curve: Curve = Curve.new()
curve.add_point(Vector2(0.0, 1.0))
curve.add_point(Vector2(1.0, 0.15))
return curve
func _make_additive() -> CanvasItemMaterial:
var material: CanvasItemMaterial = CanvasItemMaterial.new()
material.blend_mode = CanvasItemMaterial.BLEND_MODE_ADD
return material
func _make_ramp(offsets: PackedFloat32Array, colors: PackedColorArray) -> Gradient:
var ramp: Gradient = Gradient.new()
ramp.offsets = offsets
ramp.colors = colors
return ramp
func _make_dot() -> GradientTexture2D:
var gradient: Gradient = Gradient.new()
gradient.set_color(0, Color(1, 1, 1, 1))
gradient.set_color(1, Color(1, 1, 1, 0))
var dot: GradientTexture2D = GradientTexture2D.new()
dot.gradient = gradient
dot.fill = GradientTexture2D.FILL_RADIAL
dot.fill_from = Vector2(0.5, 0.5)
dot.fill_to = Vector2(1.0, 0.5)
dot.width = 32
dot.height = 32
return dot
func _add_background() -> void:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
# ColorRect defaults to MOUSE_FILTER_STOP and would eat the click before _unhandled_input
background.mouse_filter = Control.MOUSE_FILTER_IGNORE
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)