Sign in
EN
games/satisfying-bounce / src / Scene / DotRippleScene.php · commit 8bdd6e4
<?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);    }}