Add water checks in BFS
Also refactor the BFS logic to generalise the next tiles to go after the tile checksscene_man
parent
7af75b8366
commit
a080b5ee0a
|
@ -150,6 +150,7 @@ typedef enum _WaterRunnerState
|
||||||
|
|
||||||
typedef struct _CWaterRunner {
|
typedef struct _CWaterRunner {
|
||||||
BFSTileMap_t bfs_tilemap;
|
BFSTileMap_t bfs_tilemap;
|
||||||
|
int32_t start_height;
|
||||||
int32_t current_tile;
|
int32_t current_tile;
|
||||||
int32_t target_tile;
|
int32_t target_tile;
|
||||||
struct sc_queue_32 bfs_queue;
|
struct sc_queue_32 bfs_queue;
|
||||||
|
|
|
@ -15,7 +15,6 @@ typedef struct Tile {
|
||||||
SolidType_t solid;
|
SolidType_t solid;
|
||||||
uint8_t def;
|
uint8_t def;
|
||||||
unsigned int water_level;
|
unsigned int water_level;
|
||||||
unsigned int max_water_level;
|
|
||||||
struct sc_map_64v entities_set;
|
struct sc_map_64v entities_set;
|
||||||
Vector2 offset;
|
Vector2 offset;
|
||||||
Vector2 size;
|
Vector2 size;
|
||||||
|
@ -28,6 +27,7 @@ typedef struct TileGrid
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int n_tiles;
|
unsigned int n_tiles;
|
||||||
unsigned int tile_size;
|
unsigned int tile_size;
|
||||||
|
unsigned int max_water_level;
|
||||||
Tile_t* tiles;
|
Tile_t* tiles;
|
||||||
}TileGrid_t;
|
}TileGrid_t;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ Entity_t* create_water_runner(EntityManager_t* ent_manager, int32_t width, int32
|
||||||
p_crunner->visited = calloc(total, sizeof(bool));
|
p_crunner->visited = calloc(total, sizeof(bool));
|
||||||
|
|
||||||
p_crunner->current_tile = start_tile;
|
p_crunner->current_tile = start_tile;
|
||||||
|
p_crunner->start_height = start_tile / width;
|
||||||
p_crunner->target_tile = total;
|
p_crunner->target_tile = total;
|
||||||
|
|
||||||
CTransform_t* p_ct = add_component(p_filler, CTRANSFORM_COMP_T);
|
CTransform_t* p_ct = add_component(p_filler, CTRANSFORM_COMP_T);
|
||||||
|
@ -99,6 +100,9 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
}
|
}
|
||||||
memset(p_crunner->visited, 0, p_crunner->bfs_tilemap.len * sizeof(bool));
|
memset(p_crunner->visited, 0, p_crunner->bfs_tilemap.len * sizeof(bool));
|
||||||
int32_t lowest_tile = p_crunner->current_tile;
|
int32_t lowest_tile = p_crunner->current_tile;
|
||||||
|
p_crunner->visited[p_crunner->current_tile] = true;
|
||||||
|
p_crunner->bfs_tilemap.tilemap[p_crunner->current_tile].reachable = true;
|
||||||
|
|
||||||
sc_queue_add_last(&p_crunner->bfs_queue, p_crunner->current_tile);
|
sc_queue_add_last(&p_crunner->bfs_queue, p_crunner->current_tile);
|
||||||
while (!sc_queue_empty(&p_crunner->bfs_queue))
|
while (!sc_queue_empty(&p_crunner->bfs_queue))
|
||||||
{
|
{
|
||||||
|
@ -112,52 +116,60 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
lowest_tile = curr_idx;
|
lowest_tile = curr_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_crunner->visited[curr_idx] = true;
|
//p_crunner->visited[curr_idx] = true;
|
||||||
p_crunner->bfs_tilemap.tilemap[curr_idx].reachable = true;
|
p_crunner->bfs_tilemap.tilemap[curr_idx].reachable = true;
|
||||||
// Possible optimisation to avoid repeated BFS, dunno how possible
|
// Possible optimisation to avoid repeated BFS, dunno how possible
|
||||||
|
|
||||||
unsigned int next = curr_idx + p_crunner->bfs_tilemap.width;
|
|
||||||
if (next >= p_crunner->bfs_tilemap.len) continue;
|
|
||||||
|
|
||||||
|
bool to_go[4] = {false, false, false, false};
|
||||||
|
Tile_t* curr_tile = tilemap.tiles + curr_idx;
|
||||||
|
unsigned int next = curr_idx + p_crunner->bfs_tilemap.width;
|
||||||
Tile_t* next_tile = tilemap.tiles + next;
|
Tile_t* next_tile = tilemap.tiles + next;
|
||||||
if (
|
if (next < p_crunner->bfs_tilemap.len)
|
||||||
next_tile->solid != SOLID
|
|
||||||
&& next_tile->water_level < next_tile->max_water_level
|
|
||||||
&& !p_crunner->visited[next]
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
sc_queue_add_last(&p_crunner->bfs_queue, next);
|
to_go[0] = next_tile->solid != SOLID;
|
||||||
p_crunner->bfs_tilemap.tilemap[next].from = curr_idx;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (
|
||||||
|
next_tile->solid == SOLID
|
||||||
|
|| next_tile->water_level == tilemap.max_water_level
|
||||||
|
|| curr_tile->water_level == tilemap.max_water_level
|
||||||
|
)
|
||||||
{
|
{
|
||||||
next = curr_idx - 1;
|
next = curr_idx - 1;
|
||||||
if (next % p_crunner->bfs_tilemap.width != 0)
|
if (next % p_crunner->bfs_tilemap.width != 0)
|
||||||
{
|
{
|
||||||
next_tile = tilemap.tiles + next;
|
next_tile = tilemap.tiles + next;
|
||||||
if (
|
to_go[1] = next_tile->solid != SOLID;
|
||||||
next_tile->solid != SOLID
|
|
||||||
&& next_tile->water_level < next_tile->max_water_level
|
|
||||||
&& !p_crunner->visited[next]
|
|
||||||
)
|
|
||||||
{
|
|
||||||
sc_queue_add_last(&p_crunner->bfs_queue, next);
|
|
||||||
p_crunner->bfs_tilemap.tilemap[next].from = curr_idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
next = curr_idx + 1;
|
next = curr_idx + 1;
|
||||||
if (next % p_crunner->bfs_tilemap.width != 0)
|
if (next % p_crunner->bfs_tilemap.width != 0)
|
||||||
{
|
{
|
||||||
next_tile = tilemap.tiles + next;
|
next_tile = tilemap.tiles + next;
|
||||||
if (
|
to_go[2] = next_tile->solid != SOLID;
|
||||||
next_tile->solid != SOLID
|
}
|
||||||
&& next_tile->water_level < next_tile->max_water_level
|
}
|
||||||
&& !p_crunner->visited[next]
|
|
||||||
)
|
if (curr_tile->water_level == tilemap.max_water_level)
|
||||||
|
{
|
||||||
|
next = curr_idx - p_crunner->bfs_tilemap.width;
|
||||||
|
if (next >= 0 && next / p_crunner->bfs_tilemap.width >= p_crunner->start_height)
|
||||||
|
{
|
||||||
|
next_tile = tilemap.tiles + next;
|
||||||
|
to_go[3] = next_tile->solid != SOLID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8_t offsets[4] = {p_crunner->bfs_tilemap.width, -1, 1, -p_crunner->bfs_tilemap.width};
|
||||||
|
for (uint8_t i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
next = curr_idx + offsets[i];
|
||||||
|
if (to_go[i] && !p_crunner->visited[next])
|
||||||
{
|
{
|
||||||
sc_queue_add_last(&p_crunner->bfs_queue, next);
|
sc_queue_add_last(&p_crunner->bfs_queue, next);
|
||||||
p_crunner->bfs_tilemap.tilemap[next].from = curr_idx;
|
p_crunner->bfs_tilemap.tilemap[next].from = curr_idx;
|
||||||
}
|
p_crunner->visited[next] = true;
|
||||||
|
p_crunner->bfs_tilemap.tilemap[next].reachable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
water_test.c
28
water_test.c
|
@ -24,6 +24,8 @@ static GameEngine_t engine =
|
||||||
.assets = {0}
|
.assets = {0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool water_toggle = false;
|
||||||
|
|
||||||
static void level_scene_render_func(Scene_t* scene)
|
static void level_scene_render_func(Scene_t* scene)
|
||||||
{
|
{
|
||||||
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
|
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
|
||||||
|
@ -146,7 +148,7 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
draw_rec.y = 0;
|
draw_rec.y = 0;
|
||||||
draw_rec.height *= -1;
|
draw_rec.height *= -1;
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(LIGHTGRAY);
|
ClearBackground( water_toggle? ColorAlpha(BLUE, 0.2) : LIGHTGRAY);
|
||||||
DrawTextureRec(
|
DrawTextureRec(
|
||||||
data->game_viewport.texture,
|
data->game_viewport.texture,
|
||||||
draw_rec,
|
draw_rec,
|
||||||
|
@ -209,11 +211,29 @@ static void toggle_block_system(Scene_t* scene)
|
||||||
if (tile_idx >= MAX_N_TILES) return;
|
if (tile_idx >= MAX_N_TILES) return;
|
||||||
if (tile_idx == last_tile_idx) return;
|
if (tile_idx == last_tile_idx) return;
|
||||||
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
|
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
|
||||||
|
{
|
||||||
|
if (!water_toggle)
|
||||||
{
|
{
|
||||||
TileType_t new_type = EMPTY_TILE;
|
TileType_t new_type = EMPTY_TILE;
|
||||||
new_type = (tilemap.tiles[tile_idx].tile_type == SOLID_TILE)? EMPTY_TILE : SOLID_TILE;
|
new_type = (tilemap.tiles[tile_idx].tile_type == SOLID_TILE)? EMPTY_TILE : SOLID_TILE;
|
||||||
if (new_type == SOLID_TILE) tilemap.tiles[tile_idx].water_level = 0;
|
if (new_type == SOLID_TILE) tilemap.tiles[tile_idx].water_level = 0;
|
||||||
change_a_tile(&tilemap, tile_idx, new_type);
|
change_a_tile(&tilemap, tile_idx, new_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tilemap.tiles[tile_idx].tile_type != SOLID_TILE)
|
||||||
|
{
|
||||||
|
if (tilemap.tiles[tile_idx].water_level > 0)
|
||||||
|
{
|
||||||
|
tilemap.tiles[tile_idx].water_level = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tilemap.tiles[tile_idx].water_level = tilemap.max_water_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
last_tile_idx = tile_idx;
|
last_tile_idx = tile_idx;
|
||||||
CWaterRunner_t* p_crunner;
|
CWaterRunner_t* p_crunner;
|
||||||
sc_map_foreach_value(&scene->ent_manager.component_map[CWATERRUNNER_T], p_crunner)
|
sc_map_foreach_value(&scene->ent_manager.component_map[CWATERRUNNER_T], p_crunner)
|
||||||
|
@ -284,6 +304,9 @@ static void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
|
||||||
case ACTION_RIGHT:
|
case ACTION_RIGHT:
|
||||||
p_playerstate->player_dir.x = (pressed)? 1 : 0;
|
p_playerstate->player_dir.x = (pressed)? 1 : 0;
|
||||||
break;
|
break;
|
||||||
|
case ACTION_METAL_TOGGLE:
|
||||||
|
if (!pressed) water_toggle = !water_toggle;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -331,6 +354,7 @@ int main(void)
|
||||||
scene.data.tilemap.width = DEFAULT_MAP_WIDTH;
|
scene.data.tilemap.width = DEFAULT_MAP_WIDTH;
|
||||||
scene.data.tilemap.height = DEFAULT_MAP_HEIGHT;
|
scene.data.tilemap.height = DEFAULT_MAP_HEIGHT;
|
||||||
scene.data.tilemap.tile_size = TILE_SIZE;
|
scene.data.tilemap.tile_size = TILE_SIZE;
|
||||||
|
scene.data.tilemap.max_water_level = 1;
|
||||||
scene.data.tilemap.n_tiles = scene.data.tilemap.width * scene.data.tilemap.height;
|
scene.data.tilemap.n_tiles = scene.data.tilemap.width * scene.data.tilemap.height;
|
||||||
assert(scene.data.tilemap.n_tiles <= MAX_N_TILES);
|
assert(scene.data.tilemap.n_tiles <= MAX_N_TILES);
|
||||||
scene.data.tilemap.tiles = all_tiles;
|
scene.data.tilemap.tiles = all_tiles;
|
||||||
|
@ -340,7 +364,6 @@ int main(void)
|
||||||
all_tiles[i].solid = NOT_SOLID;
|
all_tiles[i].solid = NOT_SOLID;
|
||||||
all_tiles[i].tile_type = EMPTY_TILE;
|
all_tiles[i].tile_type = EMPTY_TILE;
|
||||||
all_tiles[i].moveable = true;
|
all_tiles[i].moveable = true;
|
||||||
all_tiles[i].max_water_level = 1;
|
|
||||||
sc_map_init_64v(&all_tiles[i].entities_set, 16, 0);
|
sc_map_init_64v(&all_tiles[i].entities_set, 16, 0);
|
||||||
all_tiles[i].size = (Vector2){TILE_SIZE, TILE_SIZE};
|
all_tiles[i].size = (Vector2){TILE_SIZE, TILE_SIZE};
|
||||||
}
|
}
|
||||||
|
@ -373,6 +396,7 @@ int main(void)
|
||||||
sc_map_put_64(&scene.scene.action_map, KEY_DOWN, ACTION_DOWN);
|
sc_map_put_64(&scene.scene.action_map, KEY_DOWN, ACTION_DOWN);
|
||||||
sc_map_put_64(&scene.scene.action_map, KEY_LEFT, ACTION_LEFT);
|
sc_map_put_64(&scene.scene.action_map, KEY_LEFT, ACTION_LEFT);
|
||||||
sc_map_put_64(&scene.scene.action_map, KEY_RIGHT, ACTION_RIGHT);
|
sc_map_put_64(&scene.scene.action_map, KEY_RIGHT, ACTION_RIGHT);
|
||||||
|
sc_map_put_64(&scene.scene.action_map, KEY_P, ACTION_METAL_TOGGLE);
|
||||||
|
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
|
|
Loading…
Reference in New Issue