TR
games/open-lemmings / src / View / Particles.php · commit 04e2e2a
<?phpnamespace App\View;use JumPHP\Renderer\Renderer;/** Small squares that fly, fall and fade: dust, sparks, splashes, confetti. Level coordinates. */final class Particles{    private const MAX = 500;    /** @var array<int, array{0:float,1:float,2:float,3:float,4:float,5:float,6:array,7:float,8:float}> x y vx vy life max colour size gravity */    private array $list = [];    public function clear(): void    {        $this->list = [];    }    /** @return array<int, array{0:float,1:float,2:float,3:float,4:float,5:float,6:array,7:float,8:float}> */    public function all(): array    {        return $this->list;    }    public function count(): int    {        return count($this->list);    }    /** @param array<int, array|string> $colors */    public function burst(float $x, float $y, int $count, array $colors, float $speed = 60, float $life = 0.6, float $gravity = 240,                          float $size = 1, float $up = 0.5, float $spread = M_PI): void    {        for ($i = 0; $i < $count && count($this->list) < self::MAX; $i++) {            $a = -M_PI / 2 + (mt_rand(-1000, 1000) / 1000) * $spread;            $v = $speed * (0.35 + mt_rand(0, 650) / 1000);            $c = \JumPHP\Util\Color::of($colors[array_rand($colors)]);            $this->list[] = [$x, $y, cos($a) * $v, sin($a) * $v - $speed * $up * 0.3, $life * (0.6 + mt_rand(0, 400) / 1000), $life,                [$c->r, $c->g, $c->b], $size + (mt_rand(0, 100) < 25 ? 1 : 0), $gravity];        }    }    public function update(float $dt): void    {        foreach ($this->list as $i => &$p) {            $p[4] -= $dt;            if ($p[4] <= 0) {                unset($this->list[$i]);                continue;            }            $p[3] += $p[8] * $dt;            $p[0] += $p[2] * $dt;            $p[1] += $p[3] * $dt;        }        unset($p);    }    public function render(Renderer $r, float $camX, float $camY = 0): void    {        foreach ($this->list as $p) {            $x = $p[0] - $camX;            if ($x < -4 || $x > 484) {                continue;            }            $k = $p[4] / $p[5];            $c = $p[6];            $c[3] = $k > 0.5 ? 255 : (int)(255 * $k * 2);            $s = $p[7];            $r->fillRect($x, $p[1] - $camY, $s, $s, $c);        }    }}