Rename some variables for clarity; add variables for game size.
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
+109
-104
@@ -7,14 +7,18 @@
|
||||
#define PI3 3 * PI / 2
|
||||
#define DR 0.0174533f // One degree in radians
|
||||
|
||||
#define gameHeight 160
|
||||
#define gameWidth 320
|
||||
#define aspectRatio 3.2
|
||||
|
||||
// 0° => 0 radians (RIGHT)
|
||||
// 90° => π/2 radians (TOP)
|
||||
// 180° => π radians (LEFT)
|
||||
// 270° => 3π/2 radians (BOTTOM)
|
||||
// 360° => 2π radians (RIGHT)
|
||||
|
||||
// * Player position (px, py), delta (pdx, pdy), and angle (pa)
|
||||
float px, py, pdx, pdy, pa;
|
||||
// * Player position (playerX, playerY), delta (pdx, pdy), and angle (pa)
|
||||
float playerX, playerY, pdx, pdy, playerAngle;
|
||||
|
||||
// * Draw the player on the screen
|
||||
void drawPlayer()
|
||||
@@ -23,14 +27,14 @@ void drawPlayer()
|
||||
glColor3f(1, 1, 0);
|
||||
glPointSize(8);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex2i(px, py);
|
||||
glVertex2i(playerX, playerY);
|
||||
glEnd();
|
||||
|
||||
// Draws the player direction
|
||||
glLineWidth(3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(px, py);
|
||||
glVertex2i(px + pdx * 5, py + pdy * 5);
|
||||
glVertex2i(playerX, playerY);
|
||||
glVertex2i(playerX + pdx * 5, playerY + pdy * 5);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
@@ -59,8 +63,8 @@ void drawMap2D()
|
||||
{
|
||||
for (x = 0; x < mapX; x++)
|
||||
{
|
||||
// Check if it's a wall (e.g., 1)
|
||||
if (map[y * mapX + x] == 1)
|
||||
// Check if it's a wall
|
||||
if (map[y * mapX + x] > 0)
|
||||
{
|
||||
// Color walls (white)
|
||||
glColor3f(1, 1, 1);
|
||||
@@ -96,10 +100,10 @@ float dist(float ax, float ay, float bx, float by, float ang)
|
||||
// * The actual raycaster
|
||||
void drawRays3D()
|
||||
{
|
||||
int r, mx, my, mp, dof;
|
||||
int r, mx, my, mapPoint, dof;
|
||||
|
||||
// Ray x, y, angle
|
||||
float rx, ry, ra;
|
||||
float rayX, rayY, rayAngle;
|
||||
|
||||
float xo, yo;
|
||||
|
||||
@@ -108,16 +112,16 @@ void drawRays3D()
|
||||
|
||||
// Let's initialize the ray angle n degrees from the player's facing position
|
||||
// ra = ray angle; pa = player angle; DR = degree radian; n = degrees to use
|
||||
ra = pa - DR * 30;
|
||||
rayAngle = playerAngle - DR * 30;
|
||||
|
||||
// Make sure to limit the next angle
|
||||
if (ra < 0)
|
||||
if (rayAngle < 0)
|
||||
{
|
||||
ra += 2 * PI;
|
||||
rayAngle += 2 * PI;
|
||||
}
|
||||
if (ra > 2 * PI)
|
||||
if (rayAngle > 2 * PI)
|
||||
{
|
||||
ra -= 2 * PI;
|
||||
rayAngle -= 2 * PI;
|
||||
}
|
||||
|
||||
// * Cast n rays
|
||||
@@ -129,25 +133,25 @@ void drawRays3D()
|
||||
// We need to get the shortest ray cast in either the vertical or horizontal
|
||||
// distance. So, we'll set a default that's way higher than we'll ever
|
||||
// calculate, and save the horizontal ray's X and Y position.
|
||||
float disH = 1000000, hx = px, hy = py;
|
||||
float distanceHor = 1000000, hx = playerX, hy = playerY;
|
||||
|
||||
// Negative inverse of tangent
|
||||
float aTan = -1.0f / tanf(ra);
|
||||
float aTan = -1.0f / tanf(rayAngle);
|
||||
|
||||
// Check if the ray is looking up or down.
|
||||
// If it's less than π (e.g., 180°), we're looking down.
|
||||
|
||||
// ? Looking up (ray angle > π)
|
||||
if (ra > PI)
|
||||
if (rayAngle > PI)
|
||||
{
|
||||
// Round the ray's Y position to the nearest 64th value.
|
||||
// We can do this by bit-shifting down by 6, then bit-shifting back up by
|
||||
// 6. Then, we subtract a small amount for accuracy.
|
||||
ry = (((int)py >> 6) << 6) - 0.0001f;
|
||||
rayY = (((int)playerY >> 6) << 6) - 0.0001f;
|
||||
|
||||
// The ray's X value is the distance between the player and the ray's Y
|
||||
// position, times the inverse of tangent, plus the player's X position.
|
||||
rx = (py - ry) * aTan + px;
|
||||
rayX = (playerY - rayY) * aTan + playerX;
|
||||
|
||||
// Now that we have the ray's first grid intersection position, we need
|
||||
// the next X and Y offset for the second grid intersection point.
|
||||
@@ -156,13 +160,13 @@ void drawRays3D()
|
||||
}
|
||||
|
||||
// ? Looking down
|
||||
if (ra < PI)
|
||||
if (rayAngle < PI)
|
||||
{
|
||||
// This is almost exactly the same as looking up, but we add one grid
|
||||
// unit, instead of subtracting a tiny amount.
|
||||
ry = (((int)py >> 6) << 6) + 64;
|
||||
rayY = (((int)playerY >> 6) << 6) + 64;
|
||||
|
||||
rx = (py - ry) * aTan + px;
|
||||
rayX = (playerY - rayY) * aTan + playerX;
|
||||
|
||||
// This is almost exactly the same as looking up, but we add instead of
|
||||
// subtract.
|
||||
@@ -171,11 +175,11 @@ void drawRays3D()
|
||||
}
|
||||
|
||||
// ? Looking straight left or right
|
||||
if (ra == 0.0f || ra == PI)
|
||||
if (rayAngle == 0.0f || rayAngle == PI)
|
||||
{
|
||||
// It's impossible to ever hit a horizontal line
|
||||
rx = px;
|
||||
ry = py;
|
||||
rayX = playerX;
|
||||
rayY = playerY;
|
||||
}
|
||||
|
||||
int mv = 0, mh = 0;
|
||||
@@ -188,23 +192,23 @@ void drawRays3D()
|
||||
// to know where that is in the map array.
|
||||
// Let's take the ray hit position (rx,ry) and divide it by 64 (bit-shift
|
||||
// 6 places), and use that to find the position in the map's array.
|
||||
mx = (int)(rx) >> 6;
|
||||
my = (int)(ry) >> 6;
|
||||
mp = my * mapX + mx;
|
||||
mx = (int)(rayX) >> 6;
|
||||
my = (int)(rayY) >> 6;
|
||||
mapPoint = my * mapX + mx;
|
||||
|
||||
// If the map position is less than the array's size, then we can check it
|
||||
// inside the map. If the value is 1, there's a wall. If we hit a wall,
|
||||
// we're done!
|
||||
if (mp > 0 && mp < mapX * mapY && map[mp] > 0)
|
||||
if (mapPoint > 0 && mapPoint < mapX * mapY && map[mapPoint] > 0)
|
||||
{
|
||||
// We hit a wall!
|
||||
|
||||
mh = map[mp];
|
||||
mh = map[mapPoint];
|
||||
|
||||
// Save the values and calculate the distance from the player
|
||||
hx = rx;
|
||||
hy = ry;
|
||||
disH = dist(px, py, hx, hy, ra);
|
||||
hx = rayX;
|
||||
hy = rayY;
|
||||
distanceHor = dist(playerX, playerY, hx, hy, rayAngle);
|
||||
|
||||
dof = 8; // Break the loop - no need to calculate more.
|
||||
}
|
||||
@@ -212,42 +216,42 @@ void drawRays3D()
|
||||
{
|
||||
// If we didn't hit a wall, we check the next horizontal line by adding
|
||||
// the x and y offset.
|
||||
rx += xo;
|
||||
ry += yo;
|
||||
rayX += xo;
|
||||
rayY += yo;
|
||||
dof += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// * --- Check Vertical Lines ---
|
||||
dof = 0;
|
||||
float disV = 1000000, vx = px, vy = py;
|
||||
float distanceVert = 1000000, vx = playerX, vy = playerY;
|
||||
|
||||
// Negative of tangent
|
||||
float nTan = -tanf(ra);
|
||||
float nTan = -tanf(rayAngle);
|
||||
|
||||
// ? Looking left
|
||||
if (ra > PI2 && ra < PI3)
|
||||
if (rayAngle > PI2 && rayAngle < PI3)
|
||||
{
|
||||
rx = (((int)px >> 6) << 6) - 0.0001f;
|
||||
ry = (px - rx) * nTan + py;
|
||||
rayX = (((int)playerX >> 6) << 6) - 0.0001f;
|
||||
rayY = (playerX - rayX) * nTan + playerY;
|
||||
xo = -64;
|
||||
yo = -xo * nTan;
|
||||
}
|
||||
|
||||
// ? Looking right
|
||||
if (ra < PI2 || ra > PI3)
|
||||
if (rayAngle < PI2 || rayAngle > PI3)
|
||||
{
|
||||
rx = (((int)px >> 6) << 6) + 64;
|
||||
ry = (px - rx) * nTan + py;
|
||||
rayX = (((int)playerX >> 6) << 6) + 64;
|
||||
rayY = (playerX - rayX) * nTan + playerY;
|
||||
xo = 64;
|
||||
yo = -xo * nTan;
|
||||
}
|
||||
|
||||
// ? Looking straight up or down
|
||||
if (ra == 0.0f || ra == PI)
|
||||
if (rayAngle == 0.0f || rayAngle == PI)
|
||||
{
|
||||
rx = px;
|
||||
ry = py;
|
||||
rayX = playerX;
|
||||
rayY = playerY;
|
||||
}
|
||||
|
||||
while (dof < 8)
|
||||
@@ -256,23 +260,23 @@ void drawRays3D()
|
||||
// to know where that is in the map array.
|
||||
// Let's take the ray hit position (rx,ry) and divide it by 64 (bit-shift
|
||||
// 6 places), and use that to find the position in the map's array.
|
||||
mx = (int)(rx) >> 6;
|
||||
my = (int)(ry) >> 6;
|
||||
mp = my * mapX + mx;
|
||||
mx = (int)(rayX) >> 6;
|
||||
my = (int)(rayY) >> 6;
|
||||
mapPoint = my * mapX + mx;
|
||||
|
||||
// If the map position is less than the array's size, then we can check it
|
||||
// inside the map. If the value is 1, there's a wall. If we hit a wall,
|
||||
// we're done!
|
||||
if (mp > 0 && mp < mapX * mapY && map[mp] > 0)
|
||||
if (mapPoint > 0 && mapPoint < mapX * mapY && map[mapPoint] > 0)
|
||||
{
|
||||
// We hit a wall!
|
||||
|
||||
mv = map[mp];
|
||||
mv = map[mapPoint];
|
||||
|
||||
// Save the values and calculate the distance from the player
|
||||
vx = rx;
|
||||
vy = ry;
|
||||
disV = dist(px, py, vx, vy, ra);
|
||||
vx = rayX;
|
||||
vy = rayY;
|
||||
distanceVert = dist(playerX, playerY, vx, vy, rayAngle);
|
||||
|
||||
dof = 8; // Break the loop - no need to calculate more.
|
||||
}
|
||||
@@ -280,8 +284,8 @@ void drawRays3D()
|
||||
{
|
||||
// If we didn't hit a wall, we check the next horizontal line by adding
|
||||
// the x and y offset.
|
||||
rx += xo;
|
||||
ry += yo;
|
||||
rayX += xo;
|
||||
rayY += yo;
|
||||
dof += 1;
|
||||
}
|
||||
}
|
||||
@@ -290,11 +294,11 @@ void drawRays3D()
|
||||
// This is what actually determines our ray that hits a wall!
|
||||
|
||||
// Vertical wall hit
|
||||
if (disV < disH)
|
||||
if (distanceVert < distanceHor)
|
||||
{
|
||||
rx = vx;
|
||||
ry = vy;
|
||||
disT = disV;
|
||||
rayX = vx;
|
||||
rayY = vy;
|
||||
disT = distanceVert;
|
||||
// Vertical walls are drawn a little brighter than horizontal walls
|
||||
glColor3f(0.9, 0, 0);
|
||||
|
||||
@@ -305,11 +309,11 @@ void drawRays3D()
|
||||
}
|
||||
|
||||
// Horizontal wall hit
|
||||
if (disH < disV)
|
||||
if (distanceHor < distanceVert)
|
||||
{
|
||||
rx = hx;
|
||||
ry = hy;
|
||||
disT = disH;
|
||||
rayX = hx;
|
||||
rayY = hy;
|
||||
disT = distanceHor;
|
||||
// Horizontal walls are drawn a little darker than vertical walls
|
||||
glColor3f(0.7, 0, 0);
|
||||
|
||||
@@ -322,59 +326,59 @@ void drawRays3D()
|
||||
// * Draw the ray
|
||||
glLineWidth(3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(px, py);
|
||||
glVertex2i(rx, ry);
|
||||
glVertex2i(playerX, playerY);
|
||||
glVertex2i(rayX, rayY);
|
||||
glEnd();
|
||||
|
||||
// * --- Draw 3D Walls ---
|
||||
|
||||
// Correct the fish-eye effect
|
||||
float ca = pa - ra;
|
||||
if (ra < 0)
|
||||
float correctedAngle = playerAngle - rayAngle;
|
||||
if (rayAngle < 0)
|
||||
{
|
||||
ra += 2 * PI;
|
||||
rayAngle += 2 * PI;
|
||||
}
|
||||
if (ra > 2 * PI)
|
||||
if (rayAngle > 2 * PI)
|
||||
{
|
||||
ra -= 2 * PI;
|
||||
rayAngle -= 2 * PI;
|
||||
}
|
||||
|
||||
disT = disT * cos(ca);
|
||||
disT = disT * cos(correctedAngle);
|
||||
|
||||
// The window will be 320x160 px
|
||||
// The window will be 320x160 px (windowW x windowH)
|
||||
// The formula for each line height will be the cube size (64) times our
|
||||
// screen height (320), divided by the ray distance (disT).
|
||||
// screen height, divided by the ray distance (disT).
|
||||
// The further away, the larger the distance and the shorter the final line
|
||||
// height will be.
|
||||
float lineH = (mapS * 320) / disT;
|
||||
float lineHeight = (mapS * gameWidth) / disT;
|
||||
|
||||
// We need to offset the line to the middle of the screen
|
||||
// That's the full window height, minus half the line height
|
||||
float lineO = 160 - lineH / 2;
|
||||
float lineOffset = gameHeight - lineHeight / 2;
|
||||
|
||||
// Let's make sure the line doesn't exceed our vertical space, so we cap it
|
||||
if (lineH > 320)
|
||||
if (lineHeight > gameWidth)
|
||||
{
|
||||
lineH = 320;
|
||||
lineHeight = gameWidth;
|
||||
}
|
||||
|
||||
// * Draw the "wall" line
|
||||
glLineWidth(8);
|
||||
glBegin(GL_LINES);
|
||||
// Draw the line every 8th pixel, and shift the viewport to the right by 530
|
||||
glVertex2i(r * 8 + 530, lineO);
|
||||
glVertex2i(r * 8 + 530, lineH + lineO);
|
||||
glVertex2i(r * 8 + gameWidth + 210, lineOffset);
|
||||
glVertex2i(r * 8 + gameWidth + 210, lineHeight + lineOffset);
|
||||
glEnd();
|
||||
|
||||
// * Increase the ray angle to draw the next ray
|
||||
ra += DR;
|
||||
if (ra < 0)
|
||||
rayAngle += DR;
|
||||
if (rayAngle < 0)
|
||||
{
|
||||
ra += 2 * PI;
|
||||
rayAngle += 2 * PI;
|
||||
}
|
||||
if (ra > 2 * PI)
|
||||
if (rayAngle > 2 * PI)
|
||||
{
|
||||
ra -= 2 * PI;
|
||||
rayAngle -= 2 * PI;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -401,32 +405,32 @@ void buttons(unsigned char key, int x, int y)
|
||||
// 0° -> 360° ≈ 0 -> ~6.28
|
||||
|
||||
// Change player angle slightly (using radians)
|
||||
pa -= 0.1;
|
||||
playerAngle -= 0.1;
|
||||
|
||||
// If player angle drops below 0, let's reset back to 2π
|
||||
if (pa < 0)
|
||||
if (playerAngle < 0)
|
||||
{
|
||||
pa += 2 * PI;
|
||||
playerAngle += 2 * PI;
|
||||
}
|
||||
|
||||
// The values returned from sin() and cos() are very small, so we'll just
|
||||
// artificialy inflate them by multilying by 5. This is our actual movement.
|
||||
pdx = cos(pa) * 5.0f;
|
||||
pdy = sin(pa) * 5.0f;
|
||||
pdx = cos(playerAngle) * 5.0f;
|
||||
pdy = sin(playerAngle) * 5.0f;
|
||||
}
|
||||
|
||||
// ? Move right
|
||||
if (key == 'd')
|
||||
{
|
||||
pa += 0.1;
|
||||
playerAngle += 0.1;
|
||||
|
||||
if (pa > 2 * PI)
|
||||
if (playerAngle > 2 * PI)
|
||||
{
|
||||
pa -= 2 * PI;
|
||||
playerAngle -= 2 * PI;
|
||||
}
|
||||
|
||||
pdx = cos(pa) * 5.0f;
|
||||
pdy = sin(pa) * 5.0f;
|
||||
pdx = cos(playerAngle) * 5.0f;
|
||||
pdy = sin(playerAngle) * 5.0f;
|
||||
}
|
||||
|
||||
// ? Move forward
|
||||
@@ -434,15 +438,15 @@ void buttons(unsigned char key, int x, int y)
|
||||
{
|
||||
// We change the X and Y values based on our delta, which is calculated
|
||||
// during our rotation.
|
||||
px += pdx;
|
||||
py += pdy;
|
||||
playerX += pdx;
|
||||
playerY += pdy;
|
||||
}
|
||||
|
||||
// ? Move backwards
|
||||
if (key == 's')
|
||||
{
|
||||
px -= pdx;
|
||||
py -= pdy;
|
||||
playerX -= pdx;
|
||||
playerY -= pdy;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
@@ -453,15 +457,16 @@ void init()
|
||||
glClearColor(0.3, 0.3, 0.3, 0);
|
||||
|
||||
// Sets the window to be 2D at a given size
|
||||
gluOrtho2D(0, 1024, 512, 0);
|
||||
// gluOrtho2D(0, 1024, 512, 0);
|
||||
gluOrtho2D(0, gameWidth * aspectRatio, gameHeight * aspectRatio, 0);
|
||||
|
||||
// Set the initial player location
|
||||
px = 300;
|
||||
py = 300;
|
||||
playerX = 300;
|
||||
playerY = 300;
|
||||
|
||||
// Calculate the initial player deltaX and deltaY
|
||||
pdx = cos(pa) * 5.0f;
|
||||
pdy = sin(pa) * 5.0f;
|
||||
pdx = cos(playerAngle) * 5.0f;
|
||||
pdy = sin(playerAngle) * 5.0f;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
Reference in New Issue
Block a user