diff options
Diffstat (limited to 'src/world.c')
-rw-r--r-- | src/world.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/world.c b/src/world.c new file mode 100644 index 0000000..a24c7a6 --- /dev/null +++ b/src/world.c @@ -0,0 +1,128 @@ +World g_world = {0}; + +#define expect(X) if (!(X)) { \ + perr("expect failed: "STR(X)); \ + if (fp != NULL) fclose(fp); \ + world_deinit(); \ + exit(EXIT_FAILURE); \ +} + +void +world_init(const char *path, const char *cell_pattern) +{ + assert(path != NULL); + assert(cell_pattern != NULL); + + FILE *fp = fopen(path, "rw"); + expect(fp != NULL); + + int cell_count = 0; + fscanf(fp, "%d[^,\n", &cell_count); + fscanf(fp, "%*c"); + expect(cell_count > 0); + + // skip x and y + fscanf(fp, "%*d[^,\n]"); + fscanf(fp, "%*c"); + fscanf(fp, "%*d[^,\n]"); + fscanf(fp, "%*c"); + + int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN; + rfor (i, 0, cell_count) { + int id = 0, x = 0, y = 0; + fscanf(fp, "%d[^,\n]", &id); + fscanf(fp, "%*c"); + fscanf(fp, "%d[^,\n]", &x); + fscanf(fp, "%*c"); + fscanf(fp, "%d[^,\n]", &y); + fscanf(fp, "%*c"); + + min_x = min(x, min_x); + min_y = min(x, min_y); + max_x = max(x, max_x); + max_y = max(x, max_y); + + Cell *const cell = cell_load(cell_pattern, id, x, y); + expect(cell != NULL); + cell->next = g_world.root_cell; + g_world.root_cell = cell; + } + expect(g_world.root_cell != NULL); + + fclose(fp); + fp = NULL; + + // flatten the cell structure + g_world.width = max_x - min_x + 1; + g_world.height = max_y - min_y + 1; + g_world.cells = alloc(sizeof(Cell*) * g_world.width * g_world.height); + expect(g_world.cells != NULL); + + foreach (cell, g_world.root_cell) { + const int cell_x = cell->x - min_x; + const int cell_y = cell->y - min_y; + g_world.cells[cell_x + cell_y * g_world.width] = cell; + } +} + +void +world_deinit(void) +{ + if (g_world.cells != NULL) { + free(g_world.cells); + g_world.cells = NULL; + } + cell_destroy(g_world.root_cell, true); +} + +void +world_draw(void) +{ + with (cell, g_world.cells[g_world.x + g_world.y * g_world.width]) + cell_draw(cell, 0, 0); +} + +int +world_get(int x, int y) +{ + int wx = g_world.x; + int wy = g_world.y; + + if (x < 0) { + x += cfg.tile_width * cfg.cell_width; + wx -= 1; + } else if (x >= cfg.tile_width * cfg.cell_width) { + x -= cfg.tile_width * cfg.cell_width; + wx += 1; + } + if (y < 0) { + y += cfg.tile_height * cfg.cell_height; + wy -= 1; + } else if (y >= cfg.tile_height * cfg.cell_height) { + y -= cfg.tile_height * cfg.cell_height; + wy += 1; + } + + const int i = x / cfg.tile_width + (y / cfg.tile_height) * cfg.cell_width; + with (cell, g_world.cells[wx + wy * g_world.width]) + return cell->data[i] ? (cell->data[i] - 1) : 0; + return 0; // oob tile +} + +int2 +world_find(int tile) +{ + rfor (y, 0, g_world.height) { + rfor (x, 0, g_world.width) { + Cell *const cell = g_world.cells[x + y * g_world.width]; + if (cell == NULL) + continue; + const int2 spawn = cell_find(cell, tile + 1); + if (spawn.x < 0) + continue; + return I2(x, y); + } + } + + return I2(-1, -1); +} |