Entrar
PT
games/doom-jumphp / src / Game / Hud.php · commit 8e1cb9f
<?phpnamespace App\Game;use App\Engine\Art;/** The status bar (st_stuff.c): 320 x 32 palette pixels, redrawn each frame from the player's state. */final class Hud{    public const HEIGHT = 32;    public function __construct(private Art $art)    {    }    public function bar(World $world): string    {        $p = $world->player;        $hud = $this->art->hud;        $bar = $hud['STBAR']['px'];        $w = Weapons::LIST[$p->weapon];        if ($w['ammo'] !== null) {            $this->big($bar, 50, 5, (string)$p->ammo[$w['ammo']]);        }        $this->big($bar, 110, 5, $p->health . '%');        $this->big($bar, 246, 5, $p->armor . '%');        // owned weapons 2..5: yellow when owned        foreach ([2, 3, 4, 5] as $k => $n) {            $tone = !empty($p->weapons[$n]) ? 'Y' : 'G';            $this->blit($bar, $hud["S$tone$n"], 123 + ($k % 2) * 16, 7 + intdiv($k, 2) * 12);        }        // the helmet: cracks with damage, red visor when just hurt        $level = $p->health >= 80 ? 0 : ($p->health >= 60 ? 1 : ($p->health >= 40 ? 2 : ($p->health >= 20 ? 3 : 4)));        $face = $hud['FACE' . $level . ($p->damagecount > 0 || $p->dead ? 'H' : '')];        $this->blit($bar, $face, 155, 3);        // keys        foreach (['red' => 'R', 'blue' => 'B', 'yellow' => 'Y'] as $k => $c) {            if (!empty($p->keys[$k])) {                $this->blit($bar, $hud["KEY$c"], 253, 5 + ['R' => 0, 'B' => 8, 'Y' => 16][$c]);            }        }        // stock of each ammunition        foreach (['bullets', 'shells', 'cells'] as $i => $a) {            $this->small($bar, 314, 5 + $i * 8, $p->ammo[$a] . '/' . Player::AMMO_MAX[$a]);        }        return $bar;    }    /** Big red digits, right-aligned at $right. */    private function big(string &$bar, int $right, int $y, string $text): void    {        $x = $right - strlen($text) * 14;        foreach (str_split($text) as $ch) {            $pic = $this->art->hud['BIG' . $ch] ?? null;            if ($pic !== null) {                $this->blit($bar, $pic, $x, $y);            }            $x += 14;        }    }    private function small(string &$bar, int $right, int $y, string $text): void    {        $x = $right - strlen($text) * 4;        foreach (str_split($text) as $ch) {            if ($ch === '/') {                $bar[($y + 4) * 320 + $x] = chr(8);                $bar[($y + 2) * 320 + $x + 1] = chr(8);                $bar[$y * 320 + $x + 2] = chr(8);            } elseif (isset($this->art->hud['SY' . $ch])) {                $this->blit($bar, $this->art->hud['SY' . $ch], $x, $y);            }            $x += 4;        }    }    private function blit(string &$bar, array $pic, int $x, int $y): void    {        $w = $pic['w'];        for ($j = 0; $j < $pic['h']; $j++) {            $row = substr($pic['px'], $j * $w, $w);            $o = ($y + $j) * 320 + $x;            for ($i = 0; $i < $w; $i++) {                if ($row[$i] !== "\xFF") {                    $bar[$o + $i] = $row[$i];                }            }        }    }}