<?phpnamespace App\Scene;use App\Audio\Scale;use App\Render\Gfx;use JumPHP\Renderer\Renderer;/** * A grid of dots whose size ripples outwards from the middle, like a lens bulging towards you: the flat grid looks deep, and the dots seem to * stream away from the centre. A soft bell of the Lydian scale for each wave that leaves the middle. One wave a second, 4 seconds loop with no seam. */final class DotRippleScene extends VideoScene{ public const SECONDS = 24.0; protected const LOOPS = true; public const PERIOD = 4.0; private const COLS = 11; private const ROWS = 19; private const GAP = 23.0; private int $lastWave = -1; protected function melodyNotes(): string { return 'C4'; } protected function headingText(): string { return 'NONE OF THE DOTS MOVE'; } protected function hookText(): string { return 'WHY DOES IT LOOK 3D?'; } protected function captionText(): string { return $this->t('WAVES {n}', ['n' => max(0, $this->lastWave)]); } protected function build(): void { $this->lastWave = -1; } protected function tick(float $dt): void { $n = (int)floor($this->time / self::PERIOD * 4); if ($n > $this->lastWave) { $this->lastWave = $n; $this->play(Scale::freq(Scale::LYDIAN, 7 + [0, 2, 4, 1][$n % 4] + ($n % 8 > 3 ? 1 : 0), 60), 'bell', 1.2, 0.26, 0.0); $this->pulse = 0.9; $this->tint = Gfx::hsv($n * 0.13 + 0.5); if ($n % 4 === 0) { $this->pad([Scale::freq(Scale::LYDIAN, 0, 48), Scale::freq(Scale::LYDIAN, 4, 48)], 4.0, 0.055); } } } protected function drawWorld(Renderer $r): void { $t = $this->time / self::PERIOD; $ox = 135 - (self::COLS - 1) * self::GAP / 2; $oy = 262 - (self::ROWS - 1) * self::GAP / 2; for ($j = 0; $j < self::ROWS; $j++) { for ($i = 0; $i < self::COLS; $i++) { $dx = ($i - (self::COLS - 1) / 2) * self::GAP; $dy = ($j - (self::ROWS - 1) / 2) * self::GAP; $d = sqrt($dx * $dx + $dy * $dy); $wave = sin(2 * M_PI * ($d / 92.0 - 4 * $t)); $size = 5.6 * (0.55 + 0.45 * $wave) + 0.6; $hue = 0.55 + $d / 700 + 0.25 * $wave * 0.5 + $t * 0.0; $rgb = Gfx::hsv($hue + 0.1 * floor(4 * $t) * 0, 0.5, 0.75 + 0.25 * (0.5 + 0.5 * $wave)); Gfx::disc($r, 135 + $dx * (1 + 0.06 * $wave), 262 + $dy * (1 + 0.06 * $wave), $size, $rgb); } } Gfx::glow($r, 135, 262, 3, [255, 255, 255], 0.6); }}