start($level); } private function start(int $level): void { $this->level = $level % Levels::count(); $def = Levels::get($this->level); $this->world = LevelBuilder::build($def); $this->view?->release(); $this->view = new WorldView($this->engine, $this->art, $this->world, $def['theme']); $this->auto = new Autoplay($this->world, $def['solution']); $this->camX = max(0, $this->world->hatch[0] - 240); $this->acc = 0; $this->end = 0; } public function update(float $dt): void { $this->acc = min(0.3, $this->acc + $dt * 1.5); while ($this->acc >= 1 / World::TICKS_PER_SECOND) { $this->acc -= 1 / World::TICKS_PER_SECOND; if (!$this->world->isOver()) { $this->world->step(); $this->auto->step(); } } $this->view->consume(false); $this->view->update($dt); $lead = null; foreach ($this->world->lumis as $l) { if ($l->alive && !$l->is(Lumi::STOP) && ($lead === null || $l->x > $lead->x)) { $lead = $l; } } $target = max(0, min($this->world->terrain->width - WorldView::VIEW_W, ($lead->x ?? $this->world->hatch[0]) - 240)); $this->camX += ($target - $this->camX) * min(1, $dt * 2); if ($this->world->isOver() && ($this->end += $dt) > 1.5) { $this->start($this->level + 1); } } public function render(Renderer $r): void { $this->view->render($r, $this->camX); } public function release(): void { $this->view?->release(); $this->view = null; } }