diff --git a/src/main.cpp b/src/main.cpp index d885ab3..261e08b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -202,6 +202,7 @@ struct Map { char name[64]; Uint8 *static_collision_grid; + Uint8 *water_collision_grid; R_Texture texture; R_Buffer placeables_buffer; @@ -467,6 +468,22 @@ static R_Texture create_texture(const char *path) { return result; } +static Uint32 get_corner_info(Map *world, Sint32 tile_pos_x, Sint32 tile_pos_y) { + if (tile_pos_x < 0 || tile_pos_x >= world->size.x || tile_pos_y < 0 || tile_pos_y >= world->size.y) + return 0; + + return tile_infos[world->tiles[tile_pos_y * world->size.x + tile_pos_x]].corner_info; +} + +static Uint32 find_matching_tile(Uint32 corner_info) { + for (Uint32 i = 0; i < SDL_arraysize(tile_infos); i++) { + if (corner_info == tile_infos[i].corner_info) + return i; + } + + return 0; +} + static void recalculate_static_collision_grid(Map *world) { if (world->static_collision_grid) SDL_free(world->static_collision_grid); world->static_collision_grid = (Uint8 *)SDL_calloc((world->size.x - 2) * (world->size.y - 2), sizeof(*world->static_collision_grid)); @@ -477,6 +494,23 @@ static void recalculate_static_collision_grid(Map *world) { } } +static void recalculate_water_collision_grid(Map *world) { + if (world->water_collision_grid) SDL_free(world->water_collision_grid); + world->water_collision_grid = (Uint8 *)SDL_calloc((world->size.x - 2) * (world->size.y - 2), sizeof(*world->water_collision_grid)); + + for (Sint32 y = 0; y < world->size.y - 2; y++){ + for (Sint32 x = 0; x < world->size.x - 2; x++) { + Uint32 grid_corner_info = + (get_corner_info(world, x + 0, y + 0) & (0xff << 16)) | + (get_corner_info(world, x + 1, y + 0) & (0xff << 24)) | + (get_corner_info(world, x + 0, y + 1) & (0xff << 8)) | + (get_corner_info(world, x + 1, y + 1) & (0xff << 0)); + + world->water_collision_grid[y * (world->size.x - 2) + x] = grid_corner_info == ((TILEKIND_WATER << 24) | (TILEKIND_WATER << 16) | (TILEKIND_WATER << 8) | (TILEKIND_WATER << 0)); + } + } +} + static bool save_worlds_list() { const char *path = ASSETS_PATH "maps/worlds.h"; @@ -693,6 +727,7 @@ static bool load_map(const char *name, Map *result) { } recalculate_static_collision_grid(result); + recalculate_water_collision_grid(result); SDL_Log("Loaded map file."); return true; @@ -774,6 +809,8 @@ static void change_map_size(Map *map, char direction, int amount) { player.position = clamp(player.position, i32vec2(0, 0), map->size - 2); map->texture = renderer_texture_create(R_TEXTURE_FORMAT_R16_UINT, R_TEXTURE_USAGE_SAMPLED, false, map->size.x, map->size.y, map->tiles, "map_texture"); + recalculate_static_collision_grid(map); + recalculate_water_collision_grid(map); } static void blit(char *dst, Sint32 dst_pitch, Sint32 dst_x, Sint32 dst_y, char *src, Sint32 src_pitch, Sint32 width, Sint32 height, int components = 4) { @@ -1033,28 +1070,12 @@ static bool imgui_time_picker(const char *label, int time[3]) { return result; } -static Uint32 get_corner_info(Sint32 tile_pos_x, Sint32 tile_pos_y) { - if (tile_pos_x < 0 || tile_pos_x >= current_map->size.x || tile_pos_y < 0 || tile_pos_y >= current_map->size.y) - return 0; - - return tile_infos[current_map->tiles[tile_pos_y * current_map->size.x + tile_pos_x]].corner_info; -} - -static Uint32 find_matching_tile(Uint32 corner_info) { - for (Uint32 i = 0; i < SDL_arraysize(tile_infos); i++) { - if (corner_info == tile_infos[i].corner_info) - return i; - } - - return 0; -} - static void change_map_tile(Sint32 pos_x, Sint32 pos_y, TileKind kind) { const Uint32 INFO_NONE = ((TILEKIND_NONE << 24) | (TILEKIND_NONE << 16) | (TILEKIND_NONE << 8) | TILEKIND_NONE); const Uint32 INFO_ERROR = ((TILEKIND_ERROR << 24) | (TILEKIND_ERROR << 16) | (TILEKIND_ERROR << 8) | TILEKIND_ERROR); const Uint32 INFO_MASKS[4] = { 0x0000ff00, 0x000000ff, 0xff000000, 0x00ff0000 }; - Uint32 corner_infos[4] = { get_corner_info(pos_x + 0, pos_y + 1), get_corner_info(pos_x + 1, pos_y + 1), get_corner_info(pos_x + 1, pos_y + 0), get_corner_info(pos_x + 0, pos_y + 0) }; + Uint32 corner_infos[4] = { get_corner_info(current_map, pos_x + 0, pos_y + 1), get_corner_info(current_map, pos_x + 1, pos_y + 1), get_corner_info(current_map, pos_x + 1, pos_y + 0), get_corner_info(current_map, pos_x + 0, pos_y + 0) }; for (int i = 0; i < 4; i++) { Uint32 replace_mask = INFO_MASKS[i]; @@ -1077,6 +1098,7 @@ static void change_map_tile(Sint32 pos_x, Sint32 pos_y, TileKind kind) { current_map->tiles[(pos_y + 0) * current_map->size.x + pos_x + 0] = find_matching_tile(corner_infos[3]); renderer_texture_update(current_map->texture, 0, 0, current_map->size.x, current_map->size.y, current_map->tiles, current_map->size.x * sizeof(Uint16)); + recalculate_water_collision_grid(current_map); } static void SameLineOrWrap(const ImVec2& size) { @@ -1332,6 +1354,7 @@ static void process_event_editor(SDL_Event event) { } renderer_texture_update(current_map->texture, 0, 0, current_map->size.x, current_map->size.y, current_map->tiles, current_map->size.x * sizeof(Uint16)); + recalculate_water_collision_grid(current_map); } dragging_tile_change = false; @@ -1763,6 +1786,9 @@ static bool try_queued_move() { if (current_map->static_collision_grid[target_position.y * (current_map->size.x - 2) + target_position.x] == 1) return false; + if (current_map->water_collision_grid[target_position.y * (current_map->size.x - 2) + target_position.x] == 1) + return false; + player.target_position = target_position; player.is_moving = true; return true;