Мне кажется, удачно получилось у 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. Всё. Больше не буду топы создавать. Я понял, что вы устали… Но правда, неплохо получилось же?!

