add water collision
buildbot/windows Build done.
buildbot/linux Build done.

This commit is contained in:
Sven Balzer
2026-08-07 20:02:30 +02:00
parent 3f9f154939
commit 3a8adac185
+43 -17
View File
@@ -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;