NL

SONIC PHP

door davidnurdin · Platformers
5,0 (1)
▶ Spelen 💬 Reacties van spelers Broncode 🕘 Versies Bewerken GitHub
. / src / Entities / Objects / Flipper.php · commit a20d00e
<?phpnamespace App\Entities\Objects;use App\Gfx\Gfx;/** * Flipper (object $4C, doObjectCode_platform_flipper, special stages): a pinball flipper pointing left, raised * while button 2 is held ($11: 0 at rest, 1-3 swinging, 4-5 up, one step a frame). Sonic coming down on it * (box of the state) is put on its surface (_9aaf: Y = flipper + table[(Sonic X + 12) & 31]); faster than * 3 px a frame he bounces back at half speed. At rest / up he stands and slides (X speed -4 / +$1A per frame); * hit while it swings up he is thrown by the tables _99fe (X) and _9a3e (Y). */class Flipper extends Mechanism{    // Sonic's top relative to the flipper, by (Sonic X + 12) & 31: at rest (_999e), swinging (_99be), up (_99de)    private const SURFACE = [        [-1, -1, -2, -2, -2, -3, -3, -3, -4, -4, -4, -4, -5, -5, -5, -5, -6, -6, -6, -6, -6, -7, -7, -7, -7, -7, -7, -6, -6, -5, -4, -2],        [-22, -22, -22, -10, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -3, -3, -3, -3, -2, -2, -1, 0, 2, 4],        [-22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -18, -19, -20, -20, -20, -19, -18, -17, -16, -14, -13, -12, -11, -9, -8, -7, -6, -5, -3, -1],    ];    // launch while swinging, 1/256 px per frame    private const LAUNCH_X = [-2048, -2048, -1792, -1536, -1280, -1024, -800, -640, -576, -512, -448, -384, -320, -256, -224, -192,        -160, -128, -96, -64, -32, -24, -22, -20, -18, -16, -14, -12, -10, -8, -4, -2];    private const LAUNCH_Y = [-1024, -1024, -1024, -1280, -1536, -1792, -2048, -2304, -2560, -2688, -2816, -2880, -2944, -3008, -3072, -3072,        -3072, -3072, -3008, -2944, -2880, -2816, -2560, -2304, -1792, -1536, -1024, -896, -768, -576, -256, -256];    // collision box offsets (TEMP6) of each state: x, y    private const BOX = [[0x0C, 0x14], [0x0F, 0x08], [0x1A, 0x02]];    private int $step = 0;    private int $previous = 0;    private bool $held = false;    /** Sonic's X speed while he stands on it (px/frame): the slide adds up frame after frame. */    private ?float $slide = null;    /** What happens to Sonic this frame: [sonic top Y, vx px/frame or null (unchanged), vy px/frame, add vx] */    public ?array $push = null;    public function __construct(Gfx $sdl, int $tileX, int $tileY)    {        parent::__construct($sdl, 0x4C, 'Flipper', $tileX * 32, $tileY * 32, 0x1E, 0x16);        $this->tilesetName = RomSprites::SHEET;    }    public function setButton(bool $held): void    {        $this->held = $held;    }    private function state(): int    {        return $this->step < 1 ? 0 : ($this->step < 4 ? 1 : 2);    }    /** @param array $player collision rect; ['vx', 'vy'] in px/frame */    protected function tick(array $player): void    {        if ($this->held) {            $this->previous = $this->step;            if ($this->step < 5) $this->step++;        } elseif ($this->step > 0) {            $this->step--;        }        $state = $this->state();        [$ox, $oy] = self::BOX[$state];        $sx = self::heroX($player);        $sy = self::heroY($player);        if (!($sx <= $this->x + 0x1E && $this->x + $ox <= $sx + 24 && $sy <= $this->y + 0x16 && $this->y + $oy <= $sy + 32)) {            $this->slide = null;            return;        }        $vx = $player['vx'];        $vy = $player['vy'];        // _9aaf: only coming down        if ($vy < 0) {            $this->slide = null;            return;        }        $index = ((int)floor($sx) + 12 - (int)$this->x) & 31;        $top = $this->y + self::SURFACE[$state][$index];        if ($vy >= 3 || $state === 1) {            $this->slide = null;        }        if ($vy >= 3) {            // too fast: bounces back at half speed            $this->push = [$top, $vx, -$vy / 2];            return;        }        if ($state === 1) {            // thrown while it swings up            if ($this->previous < $this->step) {                $this->push = [$top, $vx + self::LAUNCH_X[$index] / 256, self::LAUNCH_Y[$index] / 256 - $vy];            } else {                $this->push = [$top, $vx, $vy];            }            return;        }        // stands on it and slides down (the air drag of the Player would eat these 1/256 px steps)        $this->slide = ($this->slide ?? $vx) + ($state === 0 ? -4 : 0x1A) / 256;        $this->push = [$top, $this->slide, 0];    }    public function render(float $cameraX, float $cameraY): void    {        $this->blit(RomSprites::FLIPPER[$this->state()], $this->x, $this->y + 1, $cameraX, $cameraY);    }}