Temblor de pantalla

Trauma que decae con el tiempo, muestreado de FastNoiseLite hacia el offset y la rotación de la cámara. Una explosión dispara cada 1,2 segundos y el slider la escala.

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

Clases de Godot usadas

Camera2DFastNoiseLiteHSlider

El código

scripts/main.gd
extends Node

const MAX_OFFSET: float = 44.0
const MAX_ROLL: float = 0.07
const DECAY: float = 0.6

var camera: Camera2D
var noise: FastNoiseLite
var flash: Polygon2D
var bar: ColorRect
var readout: Label
var trauma: float = 0.0
var intensity: float = 1.0
var elapsed: float = 0.0


func _ready() -> void:
	_add_background()

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

	noise = FastNoiseLite.new()
	noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
	noise.frequency = 0.5

	_add_city(view)

	flash = _make_disc(78.0, Color('#fc7f7f'))
	flash.position = Vector2(view.x * 0.5, view.y * 0.62)
	add_child(flash)

	camera = Camera2D.new()
	camera.position = view * 0.5
	# ignore_rotation defaults to true and would drop the roll
	camera.ignore_rotation = false
	add_child(camera)
	camera.make_current()

	_add_hud(view)

	var timer: Timer = Timer.new()
	timer.wait_time = 1.2
	timer.timeout.connect(_burst)
	add_child(timer)
	timer.start()
	_burst()

	print('a blast fires every 1.2s, click or press space for one now, the slider scales it')


func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.pressed:
		_burst()
	elif event is InputEventKey and event.pressed and (event as InputEventKey).keycode == KEY_SPACE:
		_burst()


func _process(delta: float) -> void:
	elapsed += delta
	trauma = maxf(trauma - DECAY * delta, 0.0)

	var shake: float = trauma * trauma * intensity

	camera.offset = Vector2(noise.get_noise_2d(0.0, elapsed * 30.0), noise.get_noise_2d(500.0, elapsed * 30.0)) * MAX_OFFSET * shake
	camera.rotation = noise.get_noise_2d(1000.0, elapsed * 30.0) * MAX_ROLL * shake

	flash.scale = Vector2.ONE * (0.2 + trauma * 0.9)
	flash.modulate.a = trauma * 0.75
	bar.size.x = 260.0 * minf(trauma, 1.0)
	readout.text = 'trauma %.2f      intensity %.2f' % [trauma, intensity]


func _burst() -> void:
	trauma = 1.0


func _on_intensity(value: float) -> void:
	intensity = value


func _add_city(view: Vector2) -> void:
	var ground: Polygon2D = Polygon2D.new()
	ground.polygon = PackedVector2Array([Vector2(-600, view.y * 0.62), Vector2(view.x + 600, view.y * 0.62), Vector2(view.x + 600, view.y + 600), Vector2(-600, view.y + 600)])
	ground.color = Color('#2a2f3d')
	add_child(ground)

	var rng: RandomNumberGenerator = RandomNumberGenerator.new()
	rng.seed = 3

	for i in 11:
		var width: float = rng.randf_range(60, 110)
		var height: float = rng.randf_range(120, 300)

		var tower: Polygon2D = Polygon2D.new()
		tower.polygon = PackedVector2Array([Vector2(0, -height), Vector2(width, -height), Vector2(width, 0), Vector2(0, 0)])
		tower.color = Color('#8da5f3').lerp(Color('#12141a'), rng.randf_range(0.3, 0.65))
		tower.position = Vector2(60 + i * 110, view.y * 0.62)
		add_child(tower)


func _make_disc(radius: float, color: Color) -> Polygon2D:
	var points: PackedVector2Array = PackedVector2Array()

	for i in 32:
		points.append(Vector2(cos(TAU * i / 32.0), sin(TAU * i / 32.0)) * radius)

	var disc: Polygon2D = Polygon2D.new()
	disc.polygon = points
	disc.color = color

	return disc


func _add_hud(view: Vector2) -> void:
	var hud: CanvasLayer = CanvasLayer.new()
	add_child(hud)

	var frame: Panel = Panel.new()
	var style: StyleBoxFlat = StyleBoxFlat.new()
	style.bg_color = Color(0, 0, 0, 0)
	style.border_color = Color('#8eef97')
	style.set_border_width_all(3)
	frame.add_theme_stylebox_override('panel', style)
	frame.position = Vector2(20, 20)
	frame.size = view - Vector2(40, 40)
	hud.add_child(frame)

	var slider: HSlider = HSlider.new()
	slider.min_value = 0.0
	slider.max_value = 2.0
	slider.step = 0.05
	slider.value = intensity
	slider.position = Vector2(48, view.y - 90)
	slider.size = Vector2(260, 24)
	slider.value_changed.connect(_on_intensity)
	hud.add_child(slider)

	var track: ColorRect = ColorRect.new()
	track.color = Color('#2a2f3d')
	track.position = Vector2(48, view.y - 140)
	track.size = Vector2(260, 14)
	hud.add_child(track)

	bar = ColorRect.new()
	bar.color = Color('#fc7f7f')
	bar.position = track.position
	bar.size = Vector2(0, 14)
	hud.add_child(bar)

	readout = Label.new()
	readout.add_theme_font_size_override('font_size', 20)
	readout.add_theme_color_override('font_color', Color('#f3d48d'))
	readout.position = Vector2(48, view.y - 180)
	hud.add_child(readout)

	var note: Label = Label.new()
	note.text = 'the green frame is a CanvasLayer, it never shakes'
	note.add_theme_font_size_override('font_size', 20)
	note.add_theme_color_override('font_color', Color('#8eef97'))
	note.position = Vector2(48, 44)
	hud.add_child(note)


func _add_background() -> void:
	var layer: CanvasLayer = CanvasLayer.new()
	layer.layer = -1
	add_child(layer)

	var background: ColorRect = ColorRect.new()
	background.color = Color('#12141a')
	layer.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 Cámara