From 359372237899e935e8285fcfaaa96b26feb98f46 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Sat, 17 Aug 2024 06:06:02 -0400 Subject: [PATCH] New maze generation --- haloo3d | 2 +- maze.c | 163 ++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 107 insertions(+), 58 deletions(-) diff --git a/haloo3d b/haloo3d index d7b2d93..fbcc3e9 160000 --- a/haloo3d +++ b/haloo3d @@ -1 +1 @@ -Subproject commit d7b2d938cd5b53a65c5bdd78f62c1a7160c576e6 +Subproject commit fbcc3e9103e7f84390827dc1a63151f2ad72d158 diff --git a/maze.c b/maze.c index a2e968c..5bd9002 100644 --- a/maze.c +++ b/maze.c @@ -13,14 +13,12 @@ #include -// Performance options -// #define SECPERFRAME (1.0 / TARGETFPS) - -#define WIDTH 320 -#define HEIGHT 200 -#define SWIDTH WIDTH * 3 -#define SHEIGHT HEIGHT * 3 +#define WIDTH 640 +#define HEIGHT 400 #define ASPECT ((float)WIDTH / HEIGHT) +#define SCREENSCALE 2 +#define SWIDTH (WIDTH * SCREENSCALE) +#define SHEIGHT (HEIGHT * SCREENSCALE) #define NEARCLIP 0.01 #define FARCLIP 100.0 #define LIGHTANG -MPI / 4.0 @@ -30,79 +28,120 @@ #define MAZESIZE 31 #define HSCALE 2.0 -// Generate a (square) maze -void gen_maze(haloo3d_obj *mazewalls, int size) { - uint8_t *mazevisit; +// #define MAZESQUARE ((MAZESIZE + 1) * (MAZESIZE + 1)) +// Maze grows down and to the right. +#define MAZESOUTH 1 +#define MAZEEAST 2 +#define MAZEVISIT 4 + +#define STACKPUSH(s, t, v) s[t++] = v; + +int maze_visited(uint8_t *maze, int x, int y, int size) { + return (maze[x + y * size] & MAZEVISIT) > 0; +} + +int maze_connected(uint8_t *maze, int x, int y, int size, struct vec2i move) { + if (move.x == 1) { + return (maze[x + y * size] & MAZEEAST) == 0; + } else if (move.x == -1) { + return (x > 0) && ((maze[x - 1 + y * size] & MAZEEAST) == 0); + } else if (move.y == 1) { + return (maze[x + y * size] & MAZESOUTH) == 0; + } else if (move.y == -1) { + return (y > 0) && ((maze[x + (y - 1) * size] & MAZESOUTH) == 0); + } + return 0; +} + +// Generate a (square) maze. Utilize one bit of the maze (#2) to +// indicate whether it is visited +void maze_generate(uint8_t *maze, int size) { + const int mazesquare = (size) * (size); + for (int i = 0; i < mazesquare; i++) { + maze[i] = MAZESOUTH | MAZEEAST; + } int *mazestack; - mallocordie(mazevisit, sizeof(uint8_t) * size * size); - mallocordie(mazestack, sizeof(int) * size * size); - memset(mazevisit, 0, size * size); + mallocordie(mazestack, sizeof(int) * mazesquare); for (int i = 0; i < size * size; i++) { mazestack[i] = -1; } - // Push current cell onto stack, mark as visited int x = size / 2; int y = size / 2; - mazevisit[x + y * size] = 1; - mazestack[0] = x + y * size; - int mazetop = 1; + int mazetop = 0; + STACKPUSH(mazestack, mazetop, x + y * size); + maze[x + y * size] |= MAZEVISIT; struct vec2i visitable[4]; - int visitmax = 0; + int visittop = 0; // Now let's make a maze! while (mazetop) { mazetop--; - visitmax = 0; + visittop = 0; x = mazestack[mazetop] % size; y = mazestack[mazetop] / size; - if (x > 0 && !mazevisit[x - 1 + y * size]) { - visitable[visitmax].x = -1; - visitable[visitmax++].y = 0; + if (x > 0 && !maze_visited(maze, x - 1, y, size)) { + visitable[visittop].x = -1; + visitable[visittop++].y = 0; } - if (x < size - 1 && !mazevisit[x + 1 + y * size]) { - visitable[visitmax].x = 1; - visitable[visitmax++].y = 0; + if (x < size - 1 && !maze_visited(maze, x + 1, y, size)) { + visitable[visittop].x = 1; + visitable[visittop++].y = 0; } - if (y > 0 && !mazevisit[x + (y - 1) * size]) { - visitable[visitmax].x = 0; - visitable[visitmax++].y = -1; + if (y > 0 && !maze_visited(maze, x, y - 1, size)) { + visitable[visittop].x = 0; + visitable[visittop++].y = -1; } - if (y < size - 1 && !mazevisit[x + (y + 1) * size]) { - visitable[visitmax].x = 0; - visitable[visitmax++].y = 1; + if (y < size - 1 && !maze_visited(maze, x, y + 1, size)) { + visitable[visittop].x = 0; + visitable[visittop++].y = 1; } // You can generate a random location! - if (visitmax) { - mazetop++; // mazestack already has our location - struct vec2i movedir = visitable[rand() % visitmax]; - int facebase = 4 * (x + y * size); - // Faces are... somewhere. - haloo3d_vertexi *face; // This is actually 6 vertices, the quad - // Only y == -21 moves in the direction of facebase - if (movedir.y == 1) { - facebase += 4 * size; // backwards? - } else if (movedir.x == -1) { - facebase += 2; - } else if (movedir.x == 1) { - facebase += 6; - } - face = mazewalls->faces[facebase]; - for (int i = 0; i < 6; i++) { - face[i].posi = 0; // this should make the triangles degenerate - } + if (visittop) { + // Readd ourselves, we're moving + STACKPUSH(mazestack, mazetop, x + y * size); + struct vec2i movedir = visitable[rand() % visittop]; int nx = x + movedir.x; int ny = y + movedir.y; + // Trust that the visitable array is always valid + if (movedir.x == 1) { // Tear down east wall + maze[x + y * size] &= ~MAZEEAST; + } else if (movedir.x == -1) { // Move left and tear down east wall + maze[(x - 1) + y * size] &= ~MAZEEAST; + } else if (movedir.y == 1) { // tear down south wall + maze[x + y * size] &= ~MAZESOUTH; + } else if (movedir.y == -1) { // move up and tear down south wall + maze[x + (y - 1) * size] &= ~MAZESOUTH; + } // Push onto stack and set visited - mazestack[mazetop++] = nx + ny * size; - mazevisit[nx + ny * size] = 1; + STACKPUSH(mazestack, mazetop, nx + ny * size); + maze[nx + ny * size] |= MAZEVISIT; } } - free(mazevisit); free(mazestack); } +void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) { + // Simple: for each cell, we check if south or east is a wall. If so, + // generate it. Also, generate walls for the north and west global wall + struct vec2i dir; + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + dir.x = 1; + dir.y = 0; + if (!maze_connected(maze, x, y, size, dir)) { + haloo3d_gen_grid_quad(obj, x, y, dir); + } + dir.x = 0; + dir.y = 1; + if (!maze_connected(maze, x, y, size, dir)) { + haloo3d_gen_grid_quad(obj, x, y, dir); + } + } + } +} + int main() { // int argc, char **argv) { // Store all the values users can change at the beginning @@ -127,7 +166,6 @@ int main() { // int argc, char **argv) { haloo3d_easyrender render; haloo3d_easyrender_init(&render, WIDTH, HEIGHT); render.camera.pos.y = 0.5; - // render.trifunc = H3D_EASYRENDER_FASTFUNC; eprintf("Initialized renderer\n"); haloo3d_debugconsole_set(&dc, "render/fps.i", &fps); @@ -137,6 +175,8 @@ int main() { // int argc, char **argv) { haloo3d_debugconsole_set(&dc, "render/ditherend.f", &ditherend); haloo3d_debugconsole_set(&dc, "render/sky.u16x", &sky); haloo3d_debugconsole_set(&dc, "render/fasttris.i", &sky); + haloo3d_debugconsole_set(&dc, "camera/pos_y.f", &render.camera.pos.y); + haloo3d_debugconsole_set(&dc, "camera/pitch.f", &render.camera.pitch); render.tprint.fb = &screen; @@ -153,8 +193,14 @@ int main() { // int argc, char **argv) { haloo3d_fb *wallt = haloo3d_easystore_addtex(&storage, "walls"); haloo3d_gen_plane(flooro, MAZESIZE); haloo3d_gen_plane(ceilo, MAZESIZE); - haloo3d_gen_grid(wallo, MAZESIZE); - gen_maze(wallo, MAZESIZE); + haloo3d_gen_grid(wallo, MAZESIZE, 0); + + // no generic maze generator, we just do it raw. Each cell has a byte which + // indicates if the wall to the NORTH (#0 bit) and the wall to the WEST (#1 + // bit) are solid. Because of this, we need one additional row and column + uint8_t maze[MAZESIZE * MAZESIZE]; + maze_generate(maze, MAZESIZE); + maze_wall_generate(maze, MAZESIZE, wallo); uint16_t cols[4] = {0xFD93, 0xFB83, 0xFEEE, 0xFDDD}; haloo3d_fb_init_tex(floort, 64, 64); @@ -212,8 +258,11 @@ int main() { // int argc, char **argv) { unigi_graphics_init(); unigi_window_create(res, "maze.exe"); // render.printbuf); - // render.camera.pos.y = 5; - // render.camera.pitch = 2.2; + render.camera.pos.y = 5; + render.camera.pitch = 2.2; + ceili->pos.y = -10; + + haloo3d_debugconsole_set(&dc, "obj/ceil/pos_y.f", &ceili->pos.y); // ----------------------------------- // Actual rendering