Last active
April 6, 2022 20:23
-
-
Save JohnnyonFlame/807ed61988d2efe774dd to your computer and use it in GitHub Desktop.
A small raycasting prototype in C using the pdcurses library.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <curses.h> | |
#include <math.h> | |
float pos[2] = {(6 * 32) + 16.f, (6 * 32) + 16.f}; | |
int dir = 0; | |
int is3d = 1; | |
char dungeon[17][17] = | |
{ | |
"aaaaaaaaaaaaaaaa", | |
"a a a", | |
"a a aaaa a a a", | |
"a a a a", | |
"a aaaaa a", | |
"a a a", | |
"a aaaaaaaa a a", | |
"a aa a", | |
"a a a", | |
"a aaaaaa aaaaa", | |
"a a a", | |
"a a a", | |
"a a a", | |
"a a a", | |
"a a", | |
"aaaaaaaaaaaaaaaa", | |
}; | |
char dungeon_visited[17][17] = {[0 ... 16] = {[0 ... 16] = 0}}; | |
char dir_ch[] = {'>','v','<','^'}; | |
char wall_ch[] = {249, 176, 177, '$', '@', '#', 'T', 'w', 'a', '%', '*', '+', ',', '.', ' '}; | |
inline float f_dist(float *s0, float *s1) | |
{ | |
float dx = s1[0] - s0[0], dy = s1[1] - s0[1]; | |
return (dx*dx + dy*dy); | |
} | |
void grid_snap_x(float *v, float s, float c, float t) | |
{ | |
float snap[2]; | |
snap[0] = (floorf(v[0] / 32.f) * 32.f); | |
snap[0] += ((c > 0) ? 32.01f : -.01f); | |
snap[1] = fabs((snap[0] - v[0]) * t) * ((s>0)?1:-1); | |
snap[1] += v[1]; | |
v[0] = snap[0]; | |
v[1] = snap[1]; | |
} | |
void grid_snap_y(float *v, float s, float c, float t) | |
{ | |
float snap[2]; | |
snap[1] = (floorf(v[1] / 32.f) * 32.f); | |
snap[1] += ((s > 0) ? 32.01f : -.01f); | |
snap[0] = fabs((snap[1] - v[1]) / t) * ((c>0)?1:-1); | |
snap[0] += v[0]; | |
v[0] = snap[0]; | |
v[1] = snap[1]; | |
} | |
void grid_snap(float *v, float s, float c, float t) | |
{ | |
grid_snap_x(&v[0], s, c, t); | |
grid_snap_y(&v[2], s, c, t); | |
} | |
int grid_step_x(float *v, float s, float c, float t) | |
{ | |
v[0] = v[0] + ((c>0) ? 32.f : -32.f); | |
v[1] = v[1] + (((s>0) ? 32.f : -32.f) * t); | |
} | |
int grid_step_y(float *v, float s, float c, float t) | |
{ | |
v[1] = v[1] + ((s>0) ? 32.f : -32.f); | |
v[0] = v[0] + (((c>0) ? 32.f : -32.f) / t); | |
} | |
int pos_move(float *v, float s, int d) | |
{ | |
float npos[2] = {v[0], v[1]}; | |
switch (d) | |
{ | |
case 0: npos[0]+=s; break; | |
case 1: npos[1]+=s; break; | |
case 2: npos[0]-=s; break; | |
case 3: npos[1]-=s; break; | |
default: break; | |
} | |
if (dungeon[(int)floorf(npos[1] / 32.f)][(int)floorf(npos[0] / 32.f)] == ' ') | |
{ | |
v[0] = npos[0]; | |
v[1] = npos[1]; | |
} | |
} | |
int main(int argc, char *argv[]) | |
{ | |
initscr(); | |
curs_set(0); | |
int yaw, i, j, grid; | |
float fov = 60.f / 180.f * M_PI; | |
float fov_step = fov / 80.f; | |
float s, c, t, dx, dy, d; | |
float proj[4]; | |
char ch = 0; | |
do { | |
switch(tolower(ch)) | |
{ | |
case '3': is3d = !is3d; break; | |
case 'd': dir = (dir+1)%4; break; | |
case 'a': dir = (dir+3)%4; break; | |
case 'w': pos_move(pos, 32.f, dir); break; | |
case 's': pos_move(pos, -32.f, dir); break; | |
default: break; | |
} | |
clear(); | |
if (!is3d) | |
{ | |
for (i=0; i<17; i++) | |
{ | |
for (j=0; j<17; j++) | |
{ | |
if (dungeon_visited[i][j]) | |
mvaddch(i, j, dungeon[i][j]); | |
} | |
} | |
} | |
for (yaw=-40; yaw<40;yaw++) | |
{ | |
proj[0] = pos[0]; | |
proj[1] = pos[1]; | |
proj[2] = pos[0]; | |
proj[3] = pos[1]; | |
s = sinf((fov_step*yaw) + ((M_PI)*(dir/2.f))); | |
c = cosf((fov_step*yaw) + ((M_PI)*(dir/2.f))); | |
t = fabs(s/c); | |
grid_snap(proj, s, c, t); | |
for (i=0; i<16; i++) | |
{ | |
float dx, dy; | |
dx = f_dist(pos, &proj[0]); | |
dy = f_dist(pos, &proj[2]); | |
if (dx < dy) | |
{ | |
d = sqrtf(dx) * cosf(fov_step*yaw); | |
grid = 0; | |
} | |
else | |
{ | |
d = sqrtf(dy) * cosf(fov_step*yaw); | |
grid = 2; | |
} | |
int _x = floorf((proj[grid]) / 32.f), | |
_y = floorf((proj[grid+1]) / 32.f); | |
if (((_x>=0)&&(_x<16)) && ((_y>=0)&&(_y<16))) | |
{ | |
if (dungeon[_y][_x] != ' ') | |
{ | |
if (is3d) | |
{ | |
if (grid) | |
attron(A_BOLD); | |
else | |
attroff(A_BOLD); | |
float sz = 32.f / d * 32.f; | |
for (j=-floorf(sz/2.f);j<ceilf(sz/2.f);j++) | |
{ | |
if (((j+12>=0) && (j+12<35))) | |
{ | |
int dd = floorf(d/16.f); | |
mvaddch(j+12, yaw+40, wall_ch[(dd < sizeof(wall_ch)) | |
? dd | |
: sizeof(wall_ch) - 1]); | |
} | |
} | |
attroff(A_BOLD); | |
} | |
else | |
{ | |
attron(A_BOLD); | |
mvaddch(_y, _x, dungeon[_y][_x]); | |
attroff(A_BOLD); | |
} | |
dungeon_visited[_y][_x] = 1; | |
break; | |
} | |
else if (!is3d) | |
mvaddch(_y, _x, '.'); | |
} | |
if (dx < dy) | |
grid_step_x(&proj[0], s, c, t); | |
else | |
grid_step_y(&proj[2], s, c, t); | |
} | |
} | |
if (!is3d) | |
mvaddch(floorf(pos[1]/32.f), floorf(pos[0]/32.f), dir_ch[dir]); | |
} while ((ch = getch()) != 'e'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment