tilesetName = RomSprites::SHEET; $this->direction = mt_rand(0, 7); } public function setLevel(Level $level): void { parent::setLevel($level); if ($this->objectType === 0x3A) { $block = (int)$level->getTile($this->tileX, $this->tileY) - 0x3C; $this->orientation = $block >= 0 && $block < 4 ? $block : null; } } protected function tick(array $player): void { if ($this->objectType === 0x3A) { if ($this->orientation === null) return; $this->counter = ($this->counter + 1) & 0xFF; if (($this->counter & 0x40) || ($this->counter & 0x0F)) return; [$vx, $vy, $ox, $oy, $sideX, $sideY] = self::FIXED[$this->orientation]; $dx = (int)floor((self::heroX($player) - $this->x) / 256); $dy = (int)floor((self::heroY($player) - $this->y) / 256); if ($dx === $sideX && $dy === $sideY) { $this->fire($vx, $vy, $ox, $oy); } return; } if (($this->frames & 0x3F) === 0) { $this->direction = ($this->direction + 1) & 7; } if (++$this->counter >= 0x1A) { $this->counter = 0; [$vx, $vy, $ox, $oy] = self::ROTATING[$this->direction]; $this->fire($vx, $vy, $ox, $oy); } } /** _b5c2: a bullet $0D at the object + offset (8x16 sprite), SFX $01. */ private function fire(int $vx, int $vy, int $ox, int $oy): void { $shot = new Projectile($this->sdl, $this->x + $ox + 4, $this->y + $oy + 8, $vx / 256 * 60, $vy / 256 * 60, false, RomSprites::skyTile(0x06), RomSprites::SHEET); // _6ac1: not stopped by the scenery, removed once off the screen; tiles $06 / $08 every other frame $shot->wallGrace = INF; $shot->frames2 = [RomSprites::skyTile(0x06), RomSprites::skyTile(0x08)]; $this->spawns[] = $shot; $this->sounds[] = 0x01; } public function render(float $cameraX, float $cameraY): void { if ($this->objectType !== 0x37) return; foreach (self::BARREL[$this->direction] as [$dx, $dy, $tile]) { $this->blit(RomSprites::skyTile($tile), $this->x + $dx, $this->y + $dy + 1, $cameraX, $cameraY); } } }