Inloggen
NL
games/doom-jumphp / src / Game / HdView.php · commit 8e1cb9f
<?phpnamespace App\Game;use App\Engine\Map\Level;/** What the HD renderer needs from the world: the things to draw and the lights of the moment. */final class HdView{    /** Light colours of things (r, g, b 0..1, radius). */    private const GLOW = [        'lamp' => [1.0, 0.85, 0.5, 300], 'column' => [0.3, 0.9, 1.0, 240], 'orb' => [0.3, 0.5, 1.0, 220],        'redkey' => [1.0, 0.2, 0.15, 110], 'bluekey' => [0.2, 0.4, 1.0, 110], 'yellowkey' => [1.0, 0.9, 0.2, 110],        'acidball' => [0.35, 1.0, 0.25, 260], 'plasma' => [0.3, 0.55, 1.0, 300], 'ionball' => [0.3, 0.95, 1.0, 300],        'barrel' => [0.25, 0.9, 0.25, 90], 'vial' => [0.2, 0.5, 1.0, 80], 'cells' => [0.2, 0.8, 1.0, 70],    ];    /** @return array<int, array> [x, y, z, angle, sprite, frame, bright, light 0..1] */    public static function things(World $w, float $alpha, float $ex, float $ey, float $angle): array    {        $out = [];        $fx = cos($angle);        $fy = sin($angle);        foreach ($w->mobjs as $mo) {            if ($mo === $w->player->mo || !$mo->visible || $mo->sprite === '') {                continue;            }            $x = $mo->px + ($mo->x - $mo->px) * $alpha;            $y = $mo->py + ($mo->y - $mo->py) * $alpha;            $dx = $x - $ex;            $dy = $y - $ey;            if ($dx * $fx + $dy * $fy < -64 || $dx * $dx + $dy * $dy > 3000 * 3000) {                continue;            }            $out[] = [$x, $y, $mo->pz + ($mo->z - $mo->pz) * $alpha, $mo->angle, $mo->sprite, $mo->frame, $mo->bright,                ($mo->sector === null ? 160 : $mo->sector->light) / 255];        }        return $out;    }    /** The 8 lights that matter most here: [x, y, z, radius, r, g, b]. */    public static function lights(World $w, float $ex, float $ey, float $ez, float $angle): array    {        $p = $w->player;        $all = [];        if ($p->flashTics > 0) {            $k = $p->weapon === 5 ? [0.4, 1.0, 1.1] : [1.5, 1.1, 0.6];            $all[] = [$ex + cos($angle) * 24, $ey + sin($angle) * 24, $ez - 6, 480, ...$k];        }        foreach ($w->mobjs as $mo) {            $g = self::GLOW[$mo->type] ?? null;            if ($g === null && $mo->bright) {                // explosions, muzzle flashes of the monsters, sparks                $g = match (true) {                    $mo->type === 'puff' => [0.8, 0.6, 0.3, 80],                    $mo->type === 'barrel' => [1.4, 0.8, 0.35, 380],                    default => [0.9, 0.55, 0.25, 200],                };            }            if ($g === null || $mo->removed) {                continue;            }            $all[] = [$mo->x, $mo->y, $mo->z + max(8, $mo->height * 0.7), $g[3], $g[0], $g[1], $g[2]];        }        usort($all, fn ($a, $b) => (hypot($a[0] - $ex, $a[1] - $ey) - $a[3]) <=> (hypot($b[0] - $ex, $b[1] - $ey) - $b[3]));        return array_slice($all, 0, 8);    }    /** Lights of a level without a world (the title screen): its lamps and columns. */    public static function levelLights(Level $level, float $ex, float $ey): array    {        $all = [];        foreach ($level->things as $t) {            $g = self::GLOW[$t['type']] ?? null;            if ($g !== null) {                $z = $level->sectorAt($t['x'], $t['y'])->floor + 50;                $all[] = [$t['x'], $t['y'], $z, $g[3], $g[0], $g[1], $g[2]];            }        }        usort($all, fn ($a, $b) => hypot($a[0] - $ex, $a[1] - $ey) <=> hypot($b[0] - $ex, $b[1] - $ey));        return array_slice($all, 0, 8);    }}