Confeti

Dos cañones disparando tiras de papel con gravedad y giro. Un color_initial_ramp constante le da a cada trozo un color plano de la paleta.

El editor de arriba está ejecutando este proyecto. Cambia una línea y se recarga.

Clases de Godot usadas

CPUParticles2DGradientImageTexture

El código

scripts/main.gd
extends Node

const FIRE_INTERVAL: float = 1.1

var cannons: Array[CPUParticles2D] = []
var next_cannon: int = 0


func _ready() -> void:
	_add_background()

	var view: Vector2 = get_viewport().get_visible_rect().size

	cannons.append(_add_cannon(Vector2(130, view.y - 70), Vector2(0.85, -1.0)))
	cannons.append(_add_cannon(Vector2(view.x - 130, view.y - 70), Vector2(-0.85, -1.0)))

	var timer: Timer = Timer.new()
	timer.wait_time = FIRE_INTERVAL
	timer.timeout.connect(_fire_next)
	add_child(timer)
	timer.start()

	_fire_next()

	print('click to set both cannons off at once, they take turns on their own')


func _unhandled_input(event: InputEvent) -> void:
	if not (event is InputEventMouseButton and event.pressed):
		return

	for cannon in cannons:
		cannon.restart()


func _fire_next() -> void:
	cannons[next_cannon].restart()
	next_cannon = (next_cannon + 1) % cannons.size()


func _add_cannon(at: Vector2, aim: Vector2) -> CPUParticles2D:
	_add_nozzle(at, aim)

	var cannon: CPUParticles2D = CPUParticles2D.new()
	cannon.position = at
	cannon.texture = _make_bar(11, 16)
	cannon.local_coords = false
	cannon.emitting = false
	cannon.one_shot = true
	cannon.explosiveness = 1.0
	cannon.amount = 170
	cannon.lifetime = 2.4
	cannon.direction = aim
	cannon.spread = 24.0
	cannon.initial_velocity_min = 620.0
	cannon.initial_velocity_max = 1180.0
	cannon.gravity = Vector2(0, 760)
	cannon.damping_min = 20.0
	cannon.damping_max = 80.0
	cannon.angle_min = -180.0
	cannon.angle_max = 180.0
	cannon.angular_velocity_min = -640.0
	cannon.angular_velocity_max = 640.0
	cannon.scale_amount_min = 0.7
	cannon.scale_amount_max = 1.25
	cannon.color_initial_ramp = _make_palette()
	cannon.color_ramp = _make_fade()
	add_child(cannon)

	return cannon


func _add_nozzle(at: Vector2, aim: Vector2) -> void:
	var size: Vector2 = Vector2(64, 26)

	var nozzle: Polygon2D = Polygon2D.new()
	nozzle.polygon = PackedVector2Array([Vector2(-size.x, -size.y * 0.35), Vector2(0, -size.y * 0.5), Vector2(0, size.y * 0.5), Vector2(-size.x, size.y * 0.35)])
	nozzle.color = Color('#2a2f3d')
	nozzle.position = at
	nozzle.rotation = aim.angle()
	add_child(nozzle)


func _make_palette() -> Gradient:
	var palette: Gradient = Gradient.new()
	# linear interpolation would blend the picks into mud instead of handing out flat colors
	palette.interpolation_mode = Gradient.GRADIENT_INTERPOLATE_CONSTANT
	palette.offsets = PackedFloat32Array([0.0, 0.2, 0.4, 0.6, 0.8])
	palette.colors = PackedColorArray([Color('#8da5f3'), Color('#8eef97'), Color('#f3d48d'), Color('#fc7f7f'), Color('#e6e9f2')])

	return palette


func _make_fade() -> Gradient:
	var fade: Gradient = Gradient.new()
	fade.offsets = PackedFloat32Array([0.0, 0.75, 1.0])
	fade.colors = PackedColorArray([Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)])

	return fade


func _make_bar(bar_width: int, bar_height: int) -> ImageTexture:
	var image: Image = Image.create(bar_width, bar_height, false, Image.FORMAT_RGBA8)
	image.fill(Color.WHITE)

	return ImageTexture.create_from_image(image)


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)

Más ejemplos de Partículas