Skip to content

Instantly share code, notes, and snippets.

@RedactedProfile
Created June 23, 2020 11:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RedactedProfile/949cda9cfc1d7b798d03004c5c83ba2a to your computer and use it in GitHub Desktop.
Save RedactedProfile/949cda9cfc1d7b798d03004c5c83ba2a to your computer and use it in GitHub Desktop.
3DSage Make Your Own Raycaster Game source
#include <stdio.h>
#include <stdlib.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include <math.h>
#define PI 3.1415926535
#define PI6 PI*2
#define PI2 PI/2
#define PI3 3*PI2
#define DR 0.0174533 // one degree in radians
float px, py, pdx, pdy, pa; // player position
void drawPlayer() {
glColor3f(1, 1, 0);
glPointSize(8);
glBegin(GL_POINTS);
glVertex2i(px, py);
glEnd();
glLineWidth(3);
glBegin(GL_LINES);
glVertex2i(px, py);
glVertex2i(px + pdx * 5, py + pdy * 5);
glEnd();
}
int mapX = 8, mapY = 8, mapS = 64;
int map[] =
{
1,1,1,1,1,1,1,1,
1,0,1,0,0,0,1,1,
1,0,0,0,0,1,0,1,
1,0,0,0,1,1,0,1,
1,0,0,0,1,0,0,1,
1,0,1,0,0,0,0,1,
1,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,
};
void drawMap2D() {
int x, y, xo, yo;
for (y = 0; y < mapY; y++) {
for (x = 0; x < mapX; x++) {
// 1 = white
// 0 = black
if (map[y * mapX + x] == 1) {
glColor3f(1, 1, 1);
}
else {
glColor3f(0, 0, 0);
}
xo = x * mapS;
yo = y * mapS;
// draw
glBegin(GL_QUADS);
glVertex2i(xo +1, yo +1);
glVertex2i(xo + 1, yo + mapS - 1);
glVertex2i(xo + mapS - 1, yo + mapS - 1);
glVertex2i(xo + mapS - 1, yo + 1);
glEnd();
}
}
}
float dist(float ax, float ay, float bx, float by, float ang) {
return ( sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay) ) );
}
void drawRays2D() {
int r, mx, my, mp, dof;
float rx, ry, ra, xo, yo, disT;
// set ray's angle to the player's angle
ra = pa - DR * 30;
if (ra < 0) {
ra += PI6; }
if (ra > PI6) {
ra -= PI6; }
for (r = 0; r < 60; r++) {
// Check Horizontal Grid Lines
dof = 0;
float disH = 1000000, hx = px, hy = py;
float aTan = -1 / tan(ra); // negative inverse of tangent
// are we looking up
if (ra > PI) {
// find out the ray's first hit position
// round the ray's y position to the nearest 64th value
ry = (((int)py >> 6) << 6) - 0.001;
// ray x value is the distance between the player and the ray's y position, multiplied by inverse of tan and player's x position
rx = (py - ry) * aTan + px;
// we need the next x and y offset
yo = -64;
xo = -yo * aTan;
}
// are we looking down
if (ra < PI) {
// find out the ray's first hit position
// round the ray's y position to the nearest 64th value
ry = (((int)py >> 6) << 6) + 64;
// ray x value is the distance between the player and the ray's y position, multiplied by inverse of tan and player's x position
rx = (py - ry) * aTan + px;
// we need the next x and y offset
yo = 64;
xo = -yo * aTan;
}
// looking straight left or right
if (ra == 0 || ra == PI) {
rx = px;
ry = py;
dof = 8;
}
// depth of field check to 8 maximum
while (dof < 8) {
// find the quadrant in the map array
mx = (int)(rx) >> 6;
my = (int)(ry) >> 6;
mp = my * mapX + mx;
// if the map position is less than the array size, then we can check it inside the map
if (mp > 0 && mp < mapX * mapY && map[mp] == 1) { // hit wall
// save the ray's coordiantes
hx = rx;
hy = ry;
// calc distance from player
disH = dist(px, py, hx, hy, ra);
dof = 8;
} else {
// if we didn't hit a wall, check the next horizontal line (add the x and y offset)
rx += xo;
ry += yo;
dof += 1; // next line
}
}
// Check Vertical Grid Lines
dof = 0;
float disV = 1000000, vx = px, vy = py;
float nTan = -tan(ra); // negative inverse of tangent
// are we looking left
if (ra > PI2 && ra < PI3) {
// find out the ray's first hit position
// round the ray's y position to the nearest 64th value
rx = (((int)px >> 6) << 6) - 0.001;
// ray x value is the distance between the player and the ray's y position, multiplied by inverse of tan and player's x position
ry = (px - rx) * nTan + py;
// we need the next x and y offset
xo = -64;
yo = -xo * nTan;
}
// are we looking right
if (ra < PI2 || ra > PI3) {
// find out the ray's first hit position
// round the ray's y position to the nearest 64th value
rx = (((int)px >> 6) << 6) + 64;
// ray x value is the distance between the player and the ray's y position, multiplied by inverse of tan and player's x position
ry = (px - rx) * nTan + py;
// we need the next x and y offset
xo = 64;
yo = -xo * nTan;
}
// looking straight up or down
if (ra == 0 || ra == PI) {
rx = px;
ry = py;
dof = 8;
}
// depth of field check to 8 maximum
while (dof < 8) {
// find the quadrant in the map array
mx = (int)(rx) >> 6;
my = (int)(ry) >> 6;
mp = my * mapX + mx;
// if the map position is less than the array size, then we can check it inside the map
if (mp > 0 && mp < mapX * mapY && map[mp] == 1) { // hit wall
// save the ray's coordiantes
vx = rx;
vy = ry;
// calc distance from player
disV = dist(px, py, vx, vy, ra);
dof = 8;
}
else {
// if we didn't hit a wall, check the next horizontal line (add the x and y offset)
rx += xo;
ry += yo;
dof += 1; // next line
}
}
// vertical wall hit
if (disV < disH) {
rx = vx;
ry = vy;
disT = disV;
glColor3f(0.9, 0, 0);
}
// horizontal wall hit
else {
rx = hx;
ry = hy;
disT = disH;
glColor3f(0.7, 0, 0);
}
glLineWidth(3);
glBegin(GL_LINES);
glVertex2i(px, py);
glVertex2i(rx, ry);
glEnd();
////// 3D Wall Time
// fix fish eye by finding the distance between the player angle and the ray angle
float ca = pa - ra;
if (ca < 0) {
ca += PI6; }
if (ca > PI6) {
ca -= PI6; }
disT = disT * cos(ca); // multiply ray distance by cos of the new angle
// cap the line height
float lineH = (mapS * 320) / disT;
if (lineH > 320) {
lineH = 320; }
// correct the line offsets
float lineO = 160 - lineH / 2;
// Draw the lines
glLineWidth(8);
glBegin(GL_LINES);
glVertex2i(r * 8 + 530, lineO);
glVertex2i(r * 8 + 530, lineH + lineO);
glEnd();
// spread the fan
ra += DR;
if (ra < 0) {
ra += PI6;
}
if (ra > PI6) {
ra -= PI6;
}
}
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
drawMap2D();
drawRays2D();
drawPlayer();
glutSwapBuffers();
}
void updatePlayerDelta() {
pdx = cos(pa) * 5;
pdy = sin(pa) * 5;
}
void buttons(unsigned char key, int x, int y) {
switch (key)
{
case 'a':
pa -= 0.1;
if (pa < 0) {
pa += PI * 2; }
updatePlayerDelta();
break;
case 'd':
pa += 0.1;
if (pa > (2 * PI)) {
pa -= 2 * PI; }
updatePlayerDelta();
break;
case 'w':
px += pdx;
py += pdy;
break;
case 's':
px -= pdx;
py -= pdy;
break;
default: break;
}
glutPostRedisplay();
}
void init() {
glClearColor(0.3, 0.3, 0.3, 0);
gluOrtho2D(0, 1024, 512, 0);
px = 300; py = 300;
updatePlayerDelta();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1012, 512);
glutInitWindowPosition(0, 0);
glutCreateWindow("Test");
init();
glutDisplayFunc(display);
glutKeyboardFunc(buttons);
glutMainLoop();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment