Конвертирован нейронной сетью из кода C. Алгоритм рабочий. <?php session_start(); // Размеры карты и параметры define('MAP_WIDTH', 16); define('MAP_HEIGHT', 16); define('SCREEN_WIDTH', 60); define('SCREEN_HEIGHT', 24); define('FOV', M_PI / 3.0); define('MAX_DEPTH', 16.0); // Карта $worldMap = [ [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1], [1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,1], [1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] ]; // Инициализация или получение состояния игрока if (!isset($_SESSION['playerX'])) { $_SESSION['playerX'] = 3.0; $_SESSION['playerY'] = 3.0; $_SESSION['playerAngle'] = 0.0; } // Обработка команд if ($_SERVER['REQUEST_METHOD'] === 'POST') { $command = $_POST['command'] ?? ''; $playerX = &$_SESSION['playerX']; $playerY = &$_SESSION['playerY']; $playerAngle = &$_SESSION['playerAngle']; $newX = $playerX; $newY = $playerY; switch ($command) { case 'W': case 'w': $newX = $playerX + cos($playerAngle) * 0.2; $newY = $playerY + sin($playerAngle) * 0.2; if ($worldMap[(int)$newY][(int)$newX] === 0) { $playerX = $newX; $playerY = $newY; } break; case 'S': case 's': $newX = $playerX - cos($playerAngle) * 0.2; $newY = $playerY - sin($playerAngle) * 0.2; if ($worldMap[(int)$newY][(int)$newX] === 0) { $playerX = $newX; $playerY = $newY; } break; case 'A': case 'a': $playerAngle -= 0.1; break; case 'D': case 'd': $playerAngle += 0.1; break; } } // Функция рисования function draw() { global $worldMap, $_SESSION; $playerX = $_SESSION['playerX']; $playerY = $_SESSION['playerY']; $playerAngle = $_SESSION['playerAngle']; for ($y = 0; $y < SCREEN_HEIGHT; $y++) { for ($x = 0; $x < SCREEN_WIDTH; $x++) { $rayAngle = ($playerAngle - FOV / 2) + (($x / SCREEN_WIDTH) * FOV); $distanceToWall = 0.0; $hit = false; while (!$hit && $distanceToWall < MAX_DEPTH) { $distanceToWall += 0.1; $rayX = (int)($playerX + cos($rayAngle) * $distanceToWall); $rayY = (int)($playerY + sin($rayAngle) * $distanceToWall); if ($rayX < 0 || $rayX >= MAP_WIDTH || $rayY < 0 || $rayY >= MAP_HEIGHT) { $hit = true; $distanceToWall = MAX_DEPTH; } else { if ($worldMap[$rayY][$rayX] == 1) { $hit = true; } } } $angleDiff = $rayAngle - $playerAngle; if ($angleDiff > M_PI) $angleDiff -= 2 * M_PI; if ($angleDiff < -M_PI) $angleDiff += 2 * M_PI; $ceiling = (int)((SCREEN_HEIGHT / 2.0) - SCREEN_HEIGHT / $distanceToWall); $floor = SCREEN_HEIGHT - $ceiling; if ($y < $ceiling) { $output .= " "; } elseif ($y > $ceiling && $y <= $floor) { if ($distanceToWall <= MAX_DEPTH / 4.0) { $output .= "#"; } elseif ($distanceToWall < MAX_DEPTH / 2.0) { $output .= "+"; } else { $output .= "."; } } else { $output .= " "; } } $output .= "\n"; } return $output; } ?> <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <title>3D Raycasting</title> </head> <body style="font-family: monospace; white-space: pre;"> <h2>3D Raycasting на PHP</h2> <pre> <?php echo draw(); ?> </pre> <form method="post"> <button name="command" value="W">Вперед (W)</button> <button name="command" value="S">Назад (S)</button> <button name="command" value="A">Поворот налево (A)</button> <button name="command" value="D">Поворот направо (D)</button> <button type="submit" name="command" value="exit">Выход</button> </form> </body> </html>