summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common.h49
-rw-r--r--src/main.c97
-rw-r--r--src/player.c3
-rw-r--r--src/player.h14
-rw-r--r--src/sector.c150
-rw-r--r--src/sector.h28
6 files changed, 341 insertions, 0 deletions
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..d9a222f
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,49 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stdint.h> // for size_t
+
+typedef unsigned int uint;
+
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#define clamp(x, l, h) (min(max((x), (l)), (h)))
+#define cross(x1, y1, x2, y2) ((x1)*(y2) - (x2)*(y1))
+
+struct xy {
+ float x, y;
+};
+
+struct xyz {
+ float x, y, z;
+};
+
+#define COLOR_WHITE 0xFFFFFF
+#define COLOR_BLACK 0x000000
+#define COLOR_RED 0xFF0000
+#define COLOR_GREEN 0x00FF00
+#define COLOR_BLUE 0x0000FF
+#define COLOR_LIGHTWHITE 0xF5F5F5FF
+#define color(col) (((col)>>16) & 0xFF), (((col)>>8) & 0xFF), ((col) & 0xFF)
+
+// macro wrapper for the sdl logging system
+#include <SDL2/SDL.h>
+#define LOG_APPLICATION SDL_LOG_CATEGORY_APPLICATION
+#define LOG_ERROR SDL_LOG_CATEGORY_ERROR
+#define LOG_ASSERT SDL_LOG_CATEGORY_ASSERT
+#define LOG_SYSTEM SDL_LOG_CATEGORY_SYSTEM
+#define LOG_AUDIO SDL_LOG_CATEGORY_AUDIO
+#define LOG_VIDEO SDL_LOG_CATEGORY_VIDEO
+#define LOG_RENDER SDL_LOG_CATEGORY_RENDER
+#define LOG_INPUT SDL_LOG_CATEGORY_INPUT
+#define LOG_TEST SDL_LOG_CATEGORY_TEST
+#define LOG_CUSTOM SDL_LOG_CATEGORY_CUSTOM
+
+#define log(f, ...) SDL_Log(f, ##__VA_ARGS__)
+#define log_critical(c, f, ...) SDL_LogCritical(c, f, ##__VA_ARGS__)
+#define log_error(c, f, ...) SDL_LogError(c, f, ##__VA_ARGS__)
+#define log_warn(c, f, ...) SDL_LogWarn(c, f, ##__VA_ARGS__)
+#define log_info(c, f, ...) SDL_LogInfo(c, f, ##__VA_ARGS__)
+#define log_debug(c, f, ...) SDL_LogDebug(c, f, ##__VA_ARGS__)
+#define log_verbose(c, f, ...) SDL_LogVerbose(c, f, ##__VA_ARGS__)
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..8b5aa40
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <SDL2/SDL.h>
+#include "sector.h"
+#include "common.h"
+
+int SW = 1200;
+int SH = 800;
+char *name = "Thingy";
+
+SDL_Surface *surface = NULL;
+
+void vline(int x, int y1, int y2, uint32_t col)
+{
+ y1 = clamp(y1, 0, SH-1);
+ y2 = clamp(y2, 0, SH-1);
+
+ uint32_t *pixels = (uint32_t*)surface->pixels;
+ for(int y = min(y1, y2); y <= max(y1, y2); y++) {
+ pixels[y * SW + x] = SDL_MapRGB(surface->format, color(col));
+ }
+}
+
+int main(void)
+{
+ // set logging priority
+#ifdef DEBUG
+ SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
+#else
+ SDL_LogSetAllPriority(SDL_LOG_PRIORITY_ERROR);
+#endif
+
+ map_t m;
+ if(map_load(&m, "files/map_clear.txt"))
+ return 1;
+ map_print(&m);
+ map_unload(&m);
+
+ return 0;
+
+ // ----------------- START SDL ----------------- //
+ int ret = 1;
+ SDL_Window *window = NULL;
+
+ if(SDL_Init(SDL_INIT_VIDEO) != 0) {
+ log_critical(LOG_VIDEO, "SDL_Init: %s", SDL_GetError());
+ goto exit;
+ }
+
+ window = SDL_CreateWindow(name,
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ SW, SH, 0);
+ if(window == NULL) {
+ log_critical(LOG_VIDEO, "SDL_CreateWindow: %s", SDL_GetError());
+ goto exit;
+ }
+
+ surface = SDL_GetWindowSurface(window);
+ if(surface == NULL) {
+ log_critical(LOG_VIDEO, "SDL_GetWindowSurface %s", SDL_GetError());
+ goto exit;
+ }
+ // --------------------------------------------- //
+
+
+ bool quit = false;
+ while(!quit) {
+ // ----------------- GAME LOOP ----------------- //
+ for(int i = 0; i < SW; i++)
+ vline(i, 0, SH-1, COLOR_LIGHTWHITE);
+ // --------------------------------------------- //
+
+ SDL_Event event;
+ while(SDL_PollEvent(&event)) {
+ // ----------------- EVENTS ----------------- //
+ switch(event.type) {
+ case SDL_QUIT:
+ quit = true;
+ break;
+ default:
+ log_debug(LOG_APPLICATION, "event: %d", event.type);
+ break;
+ }
+ // ------------------------------------------ //
+ }
+
+ if(SDL_UpdateWindowSurface(window) != 0) {
+ log_error(LOG_VIDEO, "SDL_UpdateWindowSurface: %s", SDL_GetError());
+ }
+ }
+
+ ret = 0;
+exit:
+ if(window != NULL) SDL_DestroyWindow(window);
+ SDL_Quit();
+ return ret;
+}
diff --git a/src/player.c b/src/player.c
new file mode 100644
index 0000000..4490f93
--- /dev/null
+++ b/src/player.c
@@ -0,0 +1,3 @@
+#include "player.h"
+
+// TODO: Implement the functions that manipulate a player
diff --git a/src/player.h b/src/player.h
new file mode 100644
index 0000000..91a9d5e
--- /dev/null
+++ b/src/player.h
@@ -0,0 +1,14 @@
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include "common.h"
+
+typedef struct player {
+ struct xyz pos, velocity; // vectors for the player
+ float angle, anglesin, anglecos, yaw; // angle, and its sine and cosine
+ uint sector; // the sector that the player is in
+} player_t;
+
+// TODO: Add functions to manipulate a player
+
+#endif
diff --git a/src/sector.c b/src/sector.c
new file mode 100644
index 0000000..3374995
--- /dev/null
+++ b/src/sector.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "sector.h"
+
+#define VERTS_CAP 512
+#define SECTS_CAP 512
+#define NUMS_CAP 512
+
+int map_load(map_t *map, char *filename)
+{
+ int ret = 1;
+
+ FILE *fp = fopen(filename, "rb");
+ if(!fp) {
+ log_critical(LOG_SYSTEM, "fopen (%s): %s\n", filename, strerror(errno));
+ return ret;
+ }
+
+ // temp structures
+ struct xy vertices[VERTS_CAP];
+ size_t verts = 0;
+ struct sector sectors[SECTS_CAP];
+ size_t sects = 0;
+ player_t player = {0};
+
+ char line[512], *ptr;
+ int offset = 0;
+ while(fgets(line, sizeof(line), fp) != NULL)
+ {
+ char word[256] = {0};
+ if(sscanf(ptr = line, "%s %n", word, &offset) != 1) word[0] = '\0';
+
+ switch(word[0])
+ {
+ case 'v':; // vertex
+ struct xy vert;
+ sscanf(ptr += offset, "%f %n", &vert.x, &offset);
+
+ while(sscanf(ptr += offset, "%f %n", &vert.y, &offset) != EOF) {
+ if(verts >= VERTS_CAP) {
+ log_critical(LOG_APPLICATION, "VERTS_CAP of %d reached", VERTS_CAP);
+ goto exit;
+ }
+ vertices[verts++] = vert;
+ }
+ break;
+ case 's': // sector
+ if(sects >= SECTS_CAP) {
+ log_critical(LOG_APPLICATION, "SECTS_CAP of %d reached", SECTS_CAP);
+ goto exit;
+ }
+
+ sscanf(ptr += offset, "%f %f %n", &sectors[sects].floor, &sectors[sects].ceil, &offset);
+
+ int numbers[NUMS_CAP];
+ size_t nums = 0;
+ while(sscanf(ptr += offset, "%s %n", word, &offset) != EOF) {
+ if(nums >= NUMS_CAP) {
+ log_critical(LOG_APPLICATION, "NUMS_CAP of %d reached", NUMS_CAP);
+ goto exit;
+ }
+
+ numbers[nums++] = (word[0] == 'x') ? -1 : atoi(word);
+ }
+
+ size_t nverts = nums/2;
+ // populate vertices
+ sectors[sects].vertices = malloc((nverts + 1) * sizeof(*sectors[sects].vertices));
+ for(size_t i = 0; i < nverts; i++)
+ sectors[sects].vertices[i+1] = numbers[i];
+ sectors[sects].vertices[0] = sectors[sects].vertices[nverts]; // need to form a loop
+
+ // populate neighbors
+ sectors[sects].neighbors = malloc(nverts * sizeof(*sectors[sects].neighbors));
+ for(size_t i = 0; i < nverts; i++)
+ sectors[sects].neighbors[i] = numbers[nverts + i];
+
+ sectors[sects++].nverts = nverts;
+ break;
+ case 'p': // player
+ sscanf(ptr += offset, "%f %f %f %d %n", &player.pos.x, &player.pos.y, &player.angle, (int *)&player.sector, &offset);
+ break;
+ }
+ }
+
+ map->sectors = malloc(sects * sizeof(*sectors));
+ map->nsects = sects;
+ memcpy(map->sectors, sectors, sects * sizeof(*sectors));
+
+ map->vertices = malloc(verts * sizeof(*vertices));
+ map->nverts = verts;
+ memcpy(map->vertices, vertices, verts * sizeof(*vertices));
+
+ map->player = player;
+
+ ret = 0;
+exit:
+ fclose(fp);
+ return ret;
+}
+
+void map_unload(map_t *map)
+{
+ for(size_t i = 0; i < map->nsects; i++) {
+ free(map->sectors[i].vertices);
+ free(map->sectors[i].neighbors);
+ }
+
+ free(map->sectors);
+ free(map->vertices);
+}
+
+int map_save(map_t *map, char *filename)
+{
+ FILE *fp = fopen(filename, "wb");
+ if(!fp) {
+ log_error(LOG_SYSTEM, "fopen (%s): %s\n", filename, strerror(errno));
+ return 1;
+ }
+
+ (void)map;
+
+ // something something
+
+ return 0;
+}
+
+void map_print(map_t *map)
+{
+ log("%ld %ld", map->nverts, map->nsects);
+ for(size_t i = 0; i < map->nverts; i++) {
+ printf("v %ld {%.1f %.1f}\n", i, map->vertices[i].x, map->vertices[i].y);
+ }
+
+ for(size_t i = 0; i < map->nsects; i++)
+ {
+ printf("s %ld %.1f %.1f ", i, map->sectors[i].floor, map->sectors[i].ceil);
+
+ for(size_t j = 0; j < map->sectors[i].nverts + 1; j++)
+ printf("%d ", map->sectors[i].vertices[j]);
+ printf(" ");
+
+ for(size_t j = 0; j < map->sectors[i].nverts; j++)
+ printf("%d ", map->sectors[i].neighbors[j]);
+ printf("\n");
+ }
+
+ printf("p %.1f %.1f %.1f %d", map->player.pos.x, map->player.pos.y, map->player.angle, map->player.sector);
+}
diff --git a/src/sector.h b/src/sector.h
new file mode 100644
index 0000000..20050f7
--- /dev/null
+++ b/src/sector.h
@@ -0,0 +1,28 @@
+#ifndef SECTOR_H
+#define SECTOR_H
+
+#include "common.h"
+#include "player.h"
+
+struct sector {
+ float floor, ceil; // floor and ceiling heights
+ uint *vertices; // index of each vertex (vertices[nverts])
+ uint *neighbors; // index of each neighboring sector (neighbors[nverts])
+ size_t nverts; // number of vertices defining the sector
+};
+
+typedef struct {
+ struct sector *sectors; // all the sectors in the map
+ size_t nsects; // sectors[nsects]
+ struct xy *vertices; // all vertices in the map
+ size_t nverts; // vertices[nverts]
+ player_t player; // the player (should be an array in the future)
+} map_t;
+
+int map_load(map_t *map, char *filename);
+void map_unload(map_t *map);
+
+void map_print(map_t *map);
+int map_save(map_t *map, char *filename);
+
+#endif