world = new World(Campaign::level(dirname(__DIR__) . "/assets/maps/$level.json", $level), $skill, null, 3); return $this->world; } /** Puts the player in the middle of cell ($col, $row) of the level text, looking at $degrees. */ protected function placePlayer(int $col, int $row, float $degrees): Mobj { $mo = $this->world->player->mo; [$x, $y] = $this->cell($col, $row); $mo->x = $mo->px = $x; $mo->y = $mo->py = $y; $this->world->link($mo); $mo->z = $mo->floorz = $mo->sector->floor; $mo->angle = deg2rad($degrees); return $mo; } /** @return array{0: float, 1: float} the centre of a cell of the level text */ protected function cell(int $col, int $row): array { $rows = count($this->world->level->data['map']); return [$col * 64 + 32, ($rows - $row) * 64 - 32]; } protected function tics(int $tics, array $cmd = []): void { for ($i = 0; $i < $tics; $i++) { $this->world->tic($cmd + ['forward' => 0, 'side' => 0, 'turn' => 0.0, 'fire' => false, 'use' => false, 'weapon' => null]); } } /** Removes every monster (a quiet level to test a mechanic). */ protected function noMonsters(): void { foreach ($this->world->mobjs as $mo) { if ($mo->is(\App\Game\Info::COUNTKILL)) { $this->world->remove($mo); } } } }