За последние 24 часа нас посетили 276335 программистов и 5996 роботов. Сейчас ищут 3680 программистов ...

3D Raycasting на PHP.

Тема в разделе "PHP для профи", создана пользователем dcc0, 9 июл 2026.

Метки:
  1. dcc0

    dcc0 Активный пользователь

    С нами с:
    27 июн 2014
    Сообщения:
    220
    Симпатии:
    4
    Конвертирован нейронной сетью из кода 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>