LINUX.ORG.RU

Нейронные сети. Последний тест. Сеть написала 3d Raycasting с ascii

 


1

1

Мне кажется, удачно получилось у deepai.org написать 3D Raycasting с библиотекой ncurses. Можно двигаться стрелками. Стены символами отрисованы. Во всяком случае у меня работает:

Компиляция и запуск

gcc -o raycast raycast.c -lncurses -ltinfo  -lm; ./raycast
/*Модель 3D Raycasting на C89 с библиотекой ncurses. Написана нейронной сетью.
Стены с помощью символов
Компиляция и запуск gcc -o ray14 ray14.c -lncurses -ltinfo  -lm; ./ ray14
*/
#include <ncurses.h>
#include <math.h>
#include <stdlib.h>

#define MAP_WIDTH 16
#define MAP_HEIGHT 16
#define FOV (M_PI / 3.0) // 60 градусов
#define MAX_DEPTH 16

// Карта: 0 - пусто, 1 - стена
int worldMap[MAP_HEIGHT][MAP_WIDTH] = {
    {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,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1},
    {1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1},
    {1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1},
    {1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1},
    {1,0,0,0,0,1,1,1,1,1,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}
};

double playerX = 3.0, playerY = 3.0; // Начальные координаты игрока
double playerAngle = 0.0;

void draw(int width, int height) {
    for (int x = 0; x < width; x++) {
        // Вычисляем угол для каждого луча
        double rayAngle = (playerAngle - FOV / 2.0) + ((double)x / (double)width) * FOV;
        double distanceToWall = 0;
        int hit = 0;

        double eyeX = cos(rayAngle);
        double eyeY = sin(rayAngle);

        while (!hit && distanceToWall < MAX_DEPTH) {
            distanceToWall += 0.1;
            int testX = (int)(playerX + eyeX * distanceToWall);
            int testY = (int)(playerY + eyeY * distanceToWall);

            // Проверка выхода за границы
            if (testX < 0 || testX >= MAP_WIDTH || testY < 0 || testY >= MAP_HEIGHT) {
                hit = 1;
                distanceToWall = MAX_DEPTH;
            } else {
                if (worldMap[testY][testX] == 1) {
                    hit = 1;
                }
            }
        }

        // Рассчитаем высоту стен
        int ceiling = (int)((double)(height / 2.0) - height / distanceToWall);
        int floor = height - ceiling;

        for (int y = 0; y < height; y++) {
            if (y < ceiling) {
                mvaddch(y, x, ' ');
            } else if (y > ceiling && y <= floor) {
                // Можно добавить тень
                if (distanceToWall <= MAX_DEPTH / 4.0) {
                    mvaddch(y, x, '#'); // Ближе - темнее
                } else if (distanceToWall < MAX_DEPTH / 2.0) {
                    mvaddch(y, x, '+');
                } else {
                    mvaddch(y, x, '.');
                }
            } else {
                mvaddch(y, x, ' ');
            }
        }
    }
    refresh();
}

int main() {
    initscr();
    noecho();
    curs_set(FALSE);
    keypad(stdscr, TRUE);
    nodelay(stdscr, TRUE); // Не блокировать getch

    int width, height;
    getmaxyx(stdscr, height, width);

    while (1) {
        // Обработка ввода
        int ch = getch();
        if (ch == 'q') break; // Выход
        if (ch == KEY_UP) {
            // Вперёд
            double newX = playerX + cos(playerAngle) * 0.1;
            double newY = playerY + sin(playerAngle) * 0.1;
            if (worldMap[(int)newY][(int)newX] == 0) {
                playerX = newX;
                playerY = newY;
            }
        }
        if (ch == KEY_DOWN) {
            // Назад
            double newX = playerX - cos(playerAngle) * 0.1;
            double newY = playerY - sin(playerAngle) * 0.1;
            if (worldMap[(int)newY][(int)newX] == 0) {
                playerX = newX;
                playerY = newY;
            }
        }
        if (ch == KEY_LEFT) {
            playerAngle -= 0.1;
        }
        if (ch == KEY_RIGHT) {
            playerAngle += 0.1;
        }

        draw(width, height);
    }

    endwin();
    return 0;
}

P.S. Всё. Больше не буду топы создавать. Я понял, что вы устали… Но правда, неплохо получилось же?!



Последнее исправление: AnonymUser (всего исправлений: 1)

Рейкастер написать это задача для обучающегося программированию.

a1ba ★★★★
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария