Files
zombie-game/app/Game/Room.php
T
2026-09-07 20:37:40 +02:00

137 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Game;
final class Room
{
public const STATE_LOBBY = 'lobby';
public const STATE_PLAYING = 'playing';
public const STATE_OVER = 'over';
public float $width = 1920.0;
public float $height = 1080.0;
public EntityList $entities;
/** @var array<string, Player> playerId => Player */
public array $players = [];
public string $state = self::STATE_LOBBY;
/** Player id of the room's host (the first player to join). */
public string $hostId = '';
public float $elapsed = 0.0;
public float $nextBossScore = 50.0;
public int $bossCount = 0;
public float $bossCooldown = 0.0;
public float $spawnTimer = 0.0;
public float $pickupTimer = 8.0;
/** @var array<int, array<string, mixed>> Queue of one-shot event descriptors for clients. */
public array $events = [];
public int $seq = 0;
public function __construct(
public readonly string $id,
public readonly int $maxPlayers = 8,
) {
$this->entities = new EntityList;
}
public function addPlayer(Player $player): void
{
$this->players[$player->id] = $player;
$this->entities->append($player);
}
public function removePlayer(Player $player): void
{
unset($this->players[$player->id]);
$this->entities->remove($player);
}
/** Reset round state so the room can be played again (host-initiated). */
public function reset(): void
{
$this->state = self::STATE_LOBBY;
$this->elapsed = 0.0;
$this->nextBossScore = 50.0;
$this->bossCount = 0;
$this->bossCooldown = 0.0;
$this->spawnTimer = 0.0;
$this->pickupTimer = 8.0;
$this->events = [];
$this->seq++;
foreach ($this->entities->copy() as $entity) {
if ($entity instanceof Player) {
continue;
}
$this->entities->remove($entity);
}
foreach ($this->players as $player) {
$player->resetForRound();
}
}
/** @return array<int, Player> */
public function alivePlayers(): array
{
$alive = [];
foreach ($this->players as $player) {
if (! $player->dead) {
$alive[] = $player;
}
}
return $alive;
}
public function highestScore(): int
{
$best = 0;
foreach ($this->players as $player) {
$best = max($best, $player->score);
}
return $best;
}
public function hasBoss(): bool
{
foreach ($this->entities as $entity) {
if ($entity instanceof Entities\Boss) {
return true;
}
}
return false;
}
public function pushEvent(string $kind, array $data = []): void
{
$this->events[] = ['k' => $kind, 'x' => $data['x'] ?? 0.0, 'y' => $data['y'] ?? 0.0, 'd' => $data];
}
public function flushEvents(): array
{
$events = $this->events;
$this->events = [];
return $events;
}
}