Tremblement d'écran

Un trauma qui décroît avec le temps, échantillonné depuis FastNoiseLite vers l'offset et la rotation de la caméra. Une explosion part toutes les 1,2 seconde et le curseur la dose.

L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.

Classes Godot utilisées

Camera2DFastNoiseLiteHSlider

Le code

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)

Plus d'exemples de Caméra