t('TURNS {n}', ['n' => (int)floor($this->time / self::PERIOD)]); } protected function build(): void { $this->lastTick = -1; $this->glowTop = 0.0; } protected function tick(float $dt): void { // an arm is at the top (or the bottom) every PERIOD / (2 ARMS) seconds $n = (int)floor($this->time / self::PERIOD * self::ARMS * 2); if ($n > $this->lastTick) { $this->lastTick = $n; $this->glowTop = 1.0; $this->play(Scale::freq(Scale::WHOLE_TONE, 2 + [0, 3, 1, 4, 2, 5, 3, 6][$n % 8] + ($n % 2) * 6, 60), 'bell', 0.9, 0.22, 0.0); $this->pulse = 0.8; $this->tint = Gfx::hsv($n * 0.05); } $this->glowTop = max(0.0, $this->glowTop - $dt * 3); } protected function drawWorld(Renderer $r): void { $cx = 135.0; $cy = 262.0; $turn = $this->time / self::PERIOD; for ($arm = 0; $arm < self::ARMS; $arm++) { for ($j = 0; $j < self::DOTS; $j++) { $u = ($j + 1) / self::DOTS; // 0..1 along the arm $rad = 8 + 128 * $u ** 0.9; $a = $turn * 2 * M_PI + $arm * 2 * M_PI / self::ARMS + $u * 4.4; $size = 1.1 + 4.6 * $u * (0.55 + 0.45 * sin(2 * M_PI * (3 * $u - 2 * $turn))); $hue = $arm / self::ARMS + $u * 0.35 + $turn * 0.25; $x = $cx + cos($a) * $rad; $y = $cy + sin($a) * $rad; Gfx::disc($r, $x, $y, $size, Gfx::hsv($hue, 0.55, 0.65 + 0.35 * $u)); } } Gfx::glow($r, $cx, $cy, 5 + 4 * $this->glowTop, [255, 255, 255], 0.9); Gfx::disc($r, $cx, $cy, 3.4, [255, 255, 255]); } }