#include "world.h" #include "townengine/game_api.h" #include #include #include #include static void update_tiles(struct world *world) { for (size_t row = 0; row < world->tilemap_height; ++row) { for (size_t col = 0; col < world->tilemap_width; ++col) { world->tiles[(row * world->tilemap_width) + col] = (struct tile) { .rect = (t_rect) { .x = (int)col * world->tile_size, .y = (int)row * world->tile_size, .w = world->tile_size, .h = world->tile_size, }, .type = world->tilemap[row][col], }; } } } static t_vec2 to_grid_location(struct world *world, float x, float y) { return (t_vec2) { .x = (int)floor(x / (float)world->tile_size), .y = (int)floor(y / (float)world->tile_size), }; } static void drawdef_debug(struct world *world) { if (!ctx.debug) return; for (size_t i = 0; i < world->tilemap_height * world->tilemap_width; ++i) { if (world->tiles[i].type == TILE_TYPE_VOID) continue; push_rectangle(to_frect(world->tiles[i].rect), (t_color) { 255, 0, 255, 128 }); } } struct world *world_create(void) { struct world *world = cmalloc(sizeof *world); *world = (struct world) { .tiles = NULL, .tile_size = 42, .tilemap_width = 20, .tilemap_height = 12, .gravity = 1, }; /* create the tilemap */ /* it simply stores what's in each tile as a 2d array */ /* on its own, it's entirely unrelated to drawing or logic */ world->tilemap = cmalloc(sizeof *world->tilemap * world->tilemap_height); for (size_t i = 0; i < world->tilemap_height; ++i) { world->tilemap[i] = cmalloc(sizeof **world->tilemap * world->tilemap_width); for (size_t j = 0; j < world->tilemap_width; ++j) { world->tilemap[i][j] = TILE_TYPE_VOID; } } for (size_t i = 0; i < 12; ++i) { world->tilemap[world->tilemap_height-2][2+i] = TILE_TYPE_SOLID; } world->tilemap[world->tilemap_height-3][8] = TILE_TYPE_SOLID; world->tilemap[world->tilemap_height-4][8] = TILE_TYPE_SOLID; world->tilemap[world->tilemap_height-5][10] = TILE_TYPE_SOLID; world->tilemap[world->tilemap_height-6][10] = TILE_TYPE_SOLID; for (size_t i = 0; i < 7; ++i) { world->tilemap[world->tilemap_height-6][12+i] = TILE_TYPE_SOLID; } /* the tiles array contains data meant to be used by other logic */ /* most importantly, it is used to draw the tiles */ const size_t tile_count = world->tilemap_height * world->tilemap_width; world->tiles = cmalloc(sizeof *world->tiles * tile_count); update_tiles(world); return world; } void world_destroy(struct world *world) { free(world->tiles); for (size_t i = 0; i < world->tilemap_height; ++i) { free(world->tilemap[i]); } free(world->tilemap); free(world); } void world_drawdef(struct world *world) { for (size_t i = 0; i < world->tilemap_height * world->tilemap_width; ++i) { if (world->tiles[i].type == TILE_TYPE_VOID) continue; m_sprite("/assets/white.png", to_frect(world->tiles[i].rect)); } drawdef_debug(world); } bool world_find_intersect_frect(struct world *world, t_frect rect, t_frect *intersection) { bool is_intersecting = false; const size_t tile_count = world->tilemap_height * world->tilemap_width; for (size_t i = 0; i < tile_count; ++i) { if (world->tiles[i].type == TILE_TYPE_VOID) continue; t_frect tile_frect = { .x = (float)(world->tiles[i].rect.x), .y = (float)(world->tiles[i].rect.y), .w = (float)(world->tiles[i].rect.w), .h = (float)(world->tiles[i].rect.h), }; if (intersection == NULL) { t_frect temp; is_intersecting = intersect_frect(&rect, &tile_frect, &temp); } else { is_intersecting = intersect_frect(&rect, &tile_frect, intersection); } if (is_intersecting) break; } return is_intersecting; } bool world_find_intersect_rect(struct world *world, t_rect rect, t_rect *intersection) { bool is_intersecting = false; const size_t tile_count = world->tilemap_height * world->tilemap_width; for (size_t i = 0; i < tile_count; ++i) { if (world->tiles[i].type == TILE_TYPE_VOID) continue; t_rect *tile_rect = &world->tiles[i].rect; if (intersection == NULL) { t_rect temp; is_intersecting = intersect_rect(&rect, tile_rect, &temp); } else { is_intersecting = intersect_rect(&rect, tile_rect, intersection); } if (is_intersecting) break; } return is_intersecting; } bool world_is_tile_at(struct world *world, float x, float y) { t_vec2 position_in_grid = to_grid_location(world, x, y); return world->tilemap[position_in_grid.y][position_in_grid.x] != TILE_TYPE_VOID; } void world_place_tile(struct world *world, float x, float y) { t_vec2 position_in_grid = to_grid_location(world, x, y); world->tilemap[position_in_grid.y][position_in_grid.x] = TILE_TYPE_SOLID; update_tiles(world); } void world_remove_tile(struct world *world, float x, float y) { t_vec2 position_in_grid = to_grid_location(world, x, y); world->tilemap[position_in_grid.y][position_in_grid.x] = TILE_TYPE_VOID; update_tiles(world); }