summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorSchark <jordan@schark.online>2024-03-06 02:00:59 -0800
committerSchark <jordan@schark.online>2024-03-06 02:00:59 -0800
commitc356e96932b5d1a23bf41914934cf83e8b535994 (patch)
tree9ee15f23c0ae584443d8af63b473d5c2eee094ba /src/main.c
parentce811be0799bfee8355aa56d3ab566fb5b5dab55 (diff)
downloadgamedev-c356e96932b5d1a23bf41914934cf83e8b535994.tar.gz
gamedev-c356e96932b5d1a23bf41914934cf83e8b535994.zip
Working barebones heightmap renderer
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c285
1 files changed, 0 insertions, 285 deletions
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index cbe13d8..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,285 +0,0 @@
-#include <GL/glew.h> // must come before glfw3
-#include <GLFW/glfw3.h>
-#include <stdio.h>
-#include <math.h>
-
-#include "player.h"
-
-// TODO: move to implicit map definition with level editor in future
-#define MAP_HEIGHT 20
-#define MAP_WIDTH 10
-int world_map[MAP_HEIGHT][MAP_WIDTH] = {
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 2, 2, 2, 0, 0, 0, 0, 1},
- {1, 0, 2, 2, 2, 0, 0, 0, 0, 1},
- {1, 0, 2, 2, 2, 0, 0, 0, 0, 1},
- {1, 0, 2, 2, 2, 0, 0, 0, 0, 1},
- {1, 0, 2, 2, 2, 0, 4, 4, 0, 1},
- {1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
- {1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
- {1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
- {1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
- {1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
- {1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
- {1, 0, 3, 3, 3, 0, 4, 4, 0, 1},
- {1, 0, 3, 3, 3, 0, 0, 0, 0, 1},
- {1, 0, 3, 3, 3, 0, 0, 0, 0, 1},
- {1, 0, 3, 3, 3, 0, 0, 0, 0, 1},
- {1, 0, 3, 3, 3, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
-};
-
-typedef struct {
- unsigned char r, g, b;
-} ColorRGB;
-
-// honest- this function can from chatgpt- cross-reference this with other raycasting guides
-void raycast(Player *player, GLubyte *pixels, int width, int height) {
- int screen_width = width;
- int screen_height = height;
-
- for (int x = 0; x < screen_width; ++x) {
- // Calculate ray position and direction
- double camera_x = 2.0 * x / (double)screen_width - 1; // x-coordinate in camera space
- double ray_dir_x = player->dir_x + player->plane_x * camera_x;
- double ray_dir_y = player->dir_y + player->plane_y * camera_x;
-
- // Which box of the map we're in
- int map_x = (int)player->pos_x;
- int map_y = (int)player->pos_y;
-
- // Length of ray from one x or y-side to next x or y-side
- double delta_dist_x = fabs(1 / ray_dir_x);
- double delta_dist_y = fabs(1 / ray_dir_y);
-
- // Length of ray from current position to next x or y-side
- double side_dist_x;
- double side_dist_y;
-
- // Direction to step in x or y-direction (either +1 or -1)
- int step_x;
- int step_y;
-
- // Was a wall hit?
- int hit = 0;
- // Was the wall hit a wall facing north, east-west, or south?
- int side;
- if (ray_dir_x < 0) {
- step_x = -1;
- side_dist_x = (player->pos_x - map_x) * delta_dist_x;
- } else {
- step_x = 1;
- side_dist_x = (map_x + 1.0 - player->pos_x) * delta_dist_x;
- }
- if (ray_dir_y < 0) {
- step_y = -1;
- side_dist_y = (player->pos_y - map_y) * delta_dist_y;
- } else {
- step_y = 1;
- side_dist_y = (map_y + 1.0 - player->pos_y) * delta_dist_y;
- }
-
- // Perform DDA
- while (hit == 0) {
- // Jump to next map square
- if (side_dist_x < side_dist_y) {
- side_dist_x += delta_dist_x;
- map_x += step_x;
- side = (ray_dir_x > 0) ? 0 : 2;
- } else {
- side_dist_y += delta_dist_y;
- map_y += step_y;
- side = 1;
- }
- // Check if ray has hit a wall
- if (world_map[map_x][map_y] > 0) { hit = 1; }
- }
-
- // calculate distance projected on camera direction
- double perp_wall_dist;
- if (side == 0 || side == 2) { perp_wall_dist = (map_x - player->pos_x + (1 - step_x) / 2) / ray_dir_x; }
- else { perp_wall_dist = (map_y - player->pos_y + (1 - step_y) / 2) / ray_dir_y; }
-
- // fog effect
- float fog_distance = 15.0f;
- float scale_factor = 1.0f - perp_wall_dist / fog_distance;
- if (scale_factor < 0.0f) { scale_factor = 0.0f; }
-
- // calculate height of line on screen
- int line_height = (int)(screen_height / perp_wall_dist);
- //int draw_start = -line_height / 2 + screen_height / 2;
- //if (draw_start < 0) { draw_start = 0; }
- //int draw_end = line_height / 2 + screen_height / 2;
- //if (draw_end >= screen_height) { draw_end = screen_height - 1; }
- int pitch = screen_height / 2 * player->look_angle;
- int start_y = -line_height / 2 + screen_height / 2 + pitch;
- if (start_y < 0) { start_y = 0; }
- int end_y = line_height / 2 + screen_height / 2 + pitch;
- if (end_y >= screen_height) { end_y = screen_height - 1; }
-
-
- // colors :)
- ColorRGB color;
- if (world_map[map_x][map_y] == 1) color = (ColorRGB){.r = 255, .g = 255, .b = 255};
- else if (world_map[map_x][map_y] == 2) color = (ColorRGB){.r = 255, .g = 0, .b = 0};
- else if (world_map[map_x][map_y] == 3) color = (ColorRGB){.r = 0, .g = 255, .b = 0};
- else if (world_map[map_x][map_y] == 4) color = (ColorRGB){.r = 0, .g = 0, .b = 255};
- else color = (ColorRGB){.r = 0, .g = 0, .b = 0};
-
- if (side == 1) {
- color.r /= 2;
- color.g /= 2;
- color.b /= 2;
- } else if (side == 2) {
- color.r /= 4;
- color.g /= 4;
- color.b /= 4;
- }
-
- // scale brightness in accordance with distance (for fog)
- color.r *= scale_factor;
- color.g *= scale_factor;
- color.b *= scale_factor;
-
- int index;
- for (int y = 0; y < screen_height; y++) {
- index = y * screen_width * 3 + x * 3;
- if (y >= start_y && y <= end_y) {
- // draw something
- pixels[index] = color.r;
- pixels[index+1] = color.g;
- pixels[index+2] = color.b;
- } else {
- // fill blank space
- pixels[index] = 0;
- pixels[index+1] = 0;
- pixels[index+2] = 0;
- }
- }
-
- }
-}
-
-int main(int argc, char *argv[]) {
- GLFWwindow* window;
-
- double mouse_x;
- double mouse_y;
-
- // init player
- Player player;
- player.pos_y = 2.0f;
- player.pos_x = 9.0f;
- player.dir_x = 1.0f;
- player.dir_y = 0.0f;
- player.plane_x = 0.20f; // FOV related
- player.plane_y = 0.90f; // FOV related
- player.look_angle = 0.0f;
- player.move_speed = 0.035f;
- player.sensitivity = 0.001f;
-
- // initiate glfw library
- if (!glfwInit()){
- printf("Failed to initiate GLFW.\n");
- return -1;
- }
-
- // create glfw window
- GLFWmonitor* primary = glfwGetPrimaryMonitor();
- const GLFWvidmode* mode = glfwGetVideoMode(primary);
- //window = glfwCreateWindow(800, 600, "raycaster", NULL, NULL);
- window = glfwCreateWindow(mode->width, mode->height, "raycaster", primary, NULL);
- if (!window){
- printf("Failed to create GLFW window.\n");
- glfwTerminate();
- return -1;
- }
-
- // make window current
- glfwMakeContextCurrent(window);
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
-
- // update mouse position
- // glfwGetCursorPos(window, &mouse_x, &mouse_y);
- mouse_x -= mode->width / 2;
- mouse_y -= mode->height / 2;
-
- // setup orthographic projection camera
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0, mode->width, mode->height, 0.0, -1.0, 1.0);
- glMatrixMode(GL_MODELVIEW);
-
- // TODO: move timers into a header
- double last_time = glfwGetTime();
- int nb_frames = 0;
- // TODO: render FPS with freetype or something as opposed to updating title
- char title[200];
-
- // setup pbo for optimized performance
- if (glewInit() != GLEW_OK) {
- printf("Failed to initiate GLEW.\n");
- return -1;
- }
- GLuint pbo = 0;
-
- glGenBuffers(1, &pbo);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
- glBufferData(GL_PIXEL_UNPACK_BUFFER, mode->width * mode->height * 3, 0, GL_STREAM_DRAW);
-
- int index = 0;
- glViewport(0, 0, mode->width, mode->height);
- while (!glfwWindowShouldClose(window)) {
-
- // Stop loop if window isn't focused
- if(!glfwGetWindowAttrib(window, GLFW_FOCUSED)){
- continue;
- }
-
- // timing section
- double current_time = glfwGetTime();
- nb_frames++;
- if (current_time - last_time >= 1.0) {
- sprintf(title, "FPS: %d", nb_frames);
- glfwSetWindowTitle(window, title);
- nb_frames = 0;
- last_time += 1.0;
- }
-
-
- // clear window
- glClear(GL_COLOR_BUFFER_BIT);
- glLoadIdentity();
-
- // main raycast function
- float prev_position[2] = {player.pos_x, player.pos_y};
- move_player(&player, window, &mouse_x, &mouse_y, mode->width, mode->height);
- if (world_map[(int)player.pos_x][(int)player.pos_y] != 0) {
- player.pos_x = prev_position[0];
- player.pos_y = prev_position[1];
- }
- GLubyte* pixels = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
- raycast(&player, pixels, mode->width, mode->height);
-
- // pbo
- glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, mode->width);
- glWindowPos2i(0, 0);
- glDrawPixels(mode->width, mode->height, GL_RGB, GL_UNSIGNED_BYTE, 0);
-
-
- glfwSwapBuffers(window);
- glfwPollEvents();
-
- }
-
- printf("Terminating GLFW...\n");
- glfwTerminate();
- printf("Clearing buffer...\n");
- glDeleteBuffers(1, &pbo);
- return 0;
-
-}