Compare commits
5 Commits
62c74fe545
...
478dea2d9c
Author | SHA1 | Date |
---|---|---|
|
478dea2d9c | |
|
7d00d348f6 | |
|
ec8f8b6a36 | |
|
0a76826c27 | |
|
4a09550c0b |
|
@ -39,4 +39,5 @@
|
||||||
#define GROUND_Y_FRICTION 1.0
|
#define GROUND_Y_FRICTION 1.0
|
||||||
|
|
||||||
#define MAX_WATER_LEVEL 4
|
#define MAX_WATER_LEVEL 4
|
||||||
|
#define WATER_BBOX_STEP (TILE_SIZE / MAX_WATER_LEVEL)
|
||||||
#endif // __CONSTANTS_H
|
#endif // __CONSTANTS_H
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "scene_impl.h"
|
#include "scene_impl.h"
|
||||||
#include "game_systems.h"
|
#include "game_systems.h"
|
||||||
|
#include "water_flow.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "ent_impl.h"
|
#include "ent_impl.h"
|
||||||
#include "mempool.h"
|
#include "mempool.h"
|
||||||
|
@ -16,6 +17,7 @@ enum EntitySpawnSelection {
|
||||||
TOGGLE_LADDER,
|
TOGGLE_LADDER,
|
||||||
TOGGLE_SPIKE,
|
TOGGLE_SPIKE,
|
||||||
TOGGLE_WATER,
|
TOGGLE_WATER,
|
||||||
|
TOGGLE_AIR_POCKET,
|
||||||
SPAWN_CRATE,
|
SPAWN_CRATE,
|
||||||
SPAWN_CRATE_ARROW_L,
|
SPAWN_CRATE_ARROW_L,
|
||||||
SPAWN_CRATE_ARROW_R,
|
SPAWN_CRATE_ARROW_R,
|
||||||
|
@ -23,9 +25,10 @@ enum EntitySpawnSelection {
|
||||||
SPAWN_CRATE_ARROW_D,
|
SPAWN_CRATE_ARROW_D,
|
||||||
SPAWN_CRATE_BOMB,
|
SPAWN_CRATE_BOMB,
|
||||||
SPAWN_BOULDER,
|
SPAWN_BOULDER,
|
||||||
|
SPAWN_WATER_RUNNER,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SPAWN_TYPE 12
|
#define MAX_SPAWN_TYPE 14
|
||||||
static unsigned int current_spawn_selection = 0;
|
static unsigned int current_spawn_selection = 0;
|
||||||
static bool metal_toggle = false;
|
static bool metal_toggle = false;
|
||||||
|
|
||||||
|
@ -49,21 +52,6 @@ static inline unsigned int get_tile_idx(int x, int y, const TileGrid_t* tilemap)
|
||||||
return MAX_N_TILES;
|
return MAX_N_TILES;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* get_spawn_selection_string(enum EntitySpawnSelection sel)
|
|
||||||
{
|
|
||||||
switch(sel)
|
|
||||||
{
|
|
||||||
case TOGGLE_TILE: return "solid tile";
|
|
||||||
case TOGGLE_ONEWAY: return "wooden tile";
|
|
||||||
case TOGGLE_LADDER: return "ladder";
|
|
||||||
case TOGGLE_SPIKE: return "spike";
|
|
||||||
case TOGGLE_WATER: return "water";
|
|
||||||
case SPAWN_CRATE: return "crate";
|
|
||||||
case SPAWN_BOULDER: return "boulder";
|
|
||||||
default: return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -112,11 +100,20 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tilemap.tiles[i].water_level > 0)
|
// Draw water tile
|
||||||
|
uint32_t water_height = tilemap.tiles[i].water_level * WATER_BBOX_STEP;
|
||||||
|
// Draw water tile
|
||||||
|
Color water_colour = ColorAlpha(BLUE, 0.5);
|
||||||
|
DrawRectangle(
|
||||||
|
x,
|
||||||
|
y + (TILE_SIZE - water_height),
|
||||||
|
TILE_SIZE,
|
||||||
|
water_height,
|
||||||
|
water_colour
|
||||||
|
);
|
||||||
|
if (tilemap.tiles[i].max_water_level < MAX_WATER_LEVEL)
|
||||||
{
|
{
|
||||||
// Draw water tile
|
DrawRectangleLinesEx((Rectangle){x, y, TILE_SIZE, TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5));
|
||||||
Color water_colour = ColorAlpha(BLUE, 0.5);
|
|
||||||
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, water_colour);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +240,14 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc_map_foreach_value(&scene->ent_manager.entities_map[DYNMEM_ENT_TAG], p_ent)
|
||||||
|
{
|
||||||
|
CWaterRunner_t* p_runner = get_component(p_ent, CWATERRUNNER_T);
|
||||||
|
|
||||||
|
unsigned int x = ((p_runner->current_tile) % tilemap.width) * tilemap.tile_size;
|
||||||
|
unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size;
|
||||||
|
DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6));
|
||||||
|
}
|
||||||
for (size_t i = 0; i < tilemap.n_tiles; ++i)
|
for (size_t i = 0; i < tilemap.n_tiles; ++i)
|
||||||
{
|
{
|
||||||
int x = (i % tilemap.width) * TILE_SIZE;
|
int x = (i % tilemap.width) * TILE_SIZE;
|
||||||
|
@ -290,9 +295,9 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
Vector2 draw_pos = {data->game_rec.x, data->game_rec.y + data->game_rec.height + SELECTION_GAP};
|
Vector2 draw_pos = {data->game_rec.x, data->game_rec.y + data->game_rec.height + SELECTION_GAP};
|
||||||
const Color crate_colour = metal_toggle ? GRAY : BROWN;
|
const Color crate_colour = metal_toggle ? GRAY : BROWN;
|
||||||
const Color draw_colour[MAX_SPAWN_TYPE] = {
|
const Color draw_colour[MAX_SPAWN_TYPE] = {
|
||||||
BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5),
|
BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5), ColorAlpha(RAYWHITE, 0.5),
|
||||||
crate_colour, crate_colour, crate_colour, crate_colour, crate_colour, crate_colour,
|
crate_colour, crate_colour, crate_colour, crate_colour, crate_colour, crate_colour,
|
||||||
ColorAlpha(RAYWHITE, 0.5)
|
ColorAlpha(RAYWHITE, 0.5), ColorAlpha(RAYWHITE, 0.5)
|
||||||
};
|
};
|
||||||
for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i)
|
for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i)
|
||||||
{
|
{
|
||||||
|
@ -347,6 +352,12 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
case SPAWN_CRATE_BOMB:
|
case SPAWN_CRATE_BOMB:
|
||||||
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, BLACK);
|
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, BLACK);
|
||||||
break;
|
break;
|
||||||
|
case SPAWN_WATER_RUNNER:
|
||||||
|
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, ColorAlpha(BLUE, 0.2));
|
||||||
|
break;
|
||||||
|
case TOGGLE_AIR_POCKET:
|
||||||
|
DrawRectangleLinesEx((Rectangle){draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
draw_pos.x += SELECTION_TILE_SIZE;
|
draw_pos.x += SELECTION_TILE_SIZE;
|
||||||
|
@ -406,6 +417,12 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
case SPAWN_CRATE_BOMB:
|
case SPAWN_CRATE_BOMB:
|
||||||
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, BLACK);
|
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, BLACK);
|
||||||
break;
|
break;
|
||||||
|
case SPAWN_WATER_RUNNER:
|
||||||
|
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, ColorAlpha(BLUE, 0.2));
|
||||||
|
break;
|
||||||
|
case TOGGLE_AIR_POCKET:
|
||||||
|
DrawRectangleLinesEx((Rectangle){draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For DEBUG
|
// For DEBUG
|
||||||
|
@ -431,8 +448,8 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
sprintf(buffer, "Ladder: %u", p_pstate->ladder_state);
|
sprintf(buffer, "Ladder: %u", p_pstate->ladder_state);
|
||||||
DrawText(buffer, gui_x, 150, 12, BLACK);
|
DrawText(buffer, gui_x, 150, 12, BLACK);
|
||||||
}
|
}
|
||||||
sprintf(buffer, "Spawn Entity: %s", get_spawn_selection_string(current_spawn_selection));
|
//sprintf(buffer, "Spawn Entity: %s", get_spawn_selection_string(current_spawn_selection));
|
||||||
DrawText(buffer, gui_x, 240, 12, BLACK);
|
//DrawText(buffer, gui_x, 240, 12, BLACK);
|
||||||
sprintf(buffer, "Number of Entities: %u", sc_map_size_64v(&scene->ent_manager.entities));
|
sprintf(buffer, "Number of Entities: %u", sc_map_size_64v(&scene->ent_manager.entities));
|
||||||
DrawText(buffer, gui_x, 270, 12, BLACK);
|
DrawText(buffer, gui_x, 270, 12, BLACK);
|
||||||
sprintf(buffer, "FPS: %u", GetFPS());
|
sprintf(buffer, "FPS: %u", GetFPS());
|
||||||
|
@ -473,6 +490,11 @@ static void toggle_block_system(Scene_t* scene)
|
||||||
Vector2 raw_mouse_pos = {GetMouseX(), GetMouseY()};
|
Vector2 raw_mouse_pos = {GetMouseX(), GetMouseY()};
|
||||||
raw_mouse_pos = Vector2Subtract(raw_mouse_pos, (Vector2){data->game_rec.x, data->game_rec.y});
|
raw_mouse_pos = Vector2Subtract(raw_mouse_pos, (Vector2){data->game_rec.x, data->game_rec.y});
|
||||||
|
|
||||||
|
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
|
||||||
|
{
|
||||||
|
last_tile_idx = MAX_N_TILES;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
raw_mouse_pos.x < data->game_rec.width
|
raw_mouse_pos.x < data->game_rec.width
|
||||||
&& raw_mouse_pos.y < data->game_rec.height
|
&& raw_mouse_pos.y < data->game_rec.height
|
||||||
|
@ -482,60 +504,85 @@ static void toggle_block_system(Scene_t* scene)
|
||||||
unsigned int tile_idx = get_tile_idx(mouse_pos.x, mouse_pos.y, &tilemap);
|
unsigned int tile_idx = get_tile_idx(mouse_pos.x, mouse_pos.y, &tilemap);
|
||||||
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))
|
||||||
{
|
{
|
||||||
enum EntitySpawnSelection sel = (enum EntitySpawnSelection)current_spawn_selection;
|
enum EntitySpawnSelection sel = (enum EntitySpawnSelection)current_spawn_selection;
|
||||||
TileType_t new_type = EMPTY_TILE;
|
TileType_t new_type = EMPTY_TILE;
|
||||||
switch (sel)
|
switch (sel)
|
||||||
{
|
{
|
||||||
case TOGGLE_TILE:
|
case TOGGLE_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;
|
||||||
break;
|
break;
|
||||||
case TOGGLE_ONEWAY:
|
case TOGGLE_ONEWAY:
|
||||||
new_type = (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE)? EMPTY_TILE : ONEWAY_TILE;
|
new_type = (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE)? EMPTY_TILE : ONEWAY_TILE;
|
||||||
break;
|
break;
|
||||||
case TOGGLE_LADDER:
|
case TOGGLE_LADDER:
|
||||||
new_type = (tilemap.tiles[tile_idx].tile_type == LADDER)? EMPTY_TILE : LADDER;
|
new_type = (tilemap.tiles[tile_idx].tile_type == LADDER)? EMPTY_TILE : LADDER;
|
||||||
break;
|
break;
|
||||||
case TOGGLE_SPIKE:
|
case TOGGLE_SPIKE:
|
||||||
new_type = (tilemap.tiles[tile_idx].tile_type == SPIKES)? EMPTY_TILE : SPIKES;
|
new_type = (tilemap.tiles[tile_idx].tile_type == SPIKES)? EMPTY_TILE : SPIKES;
|
||||||
break;
|
break;
|
||||||
case TOGGLE_WATER:
|
case TOGGLE_WATER:
|
||||||
new_type = tilemap.tiles[tile_idx].tile_type;
|
new_type = tilemap.tiles[tile_idx].tile_type;
|
||||||
if (tilemap.tiles[tile_idx].water_level == 0)
|
if (tilemap.tiles[tile_idx].water_level < MAX_WATER_LEVEL)
|
||||||
|
{
|
||||||
|
tilemap.tiles[tile_idx].water_level++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOGGLE_AIR_POCKET:
|
||||||
|
new_type = tilemap.tiles[tile_idx].tile_type;
|
||||||
|
if (tilemap.tiles[tile_idx].max_water_level < MAX_WATER_LEVEL)
|
||||||
|
{
|
||||||
|
tilemap.tiles[tile_idx].max_water_level = MAX_WATER_LEVEL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tilemap.tiles[tile_idx].max_water_level = 0;
|
||||||
|
tilemap.tiles[tile_idx].water_level = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPAWN_CRATE:
|
||||||
|
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_EMPTY);
|
||||||
|
break;
|
||||||
|
case SPAWN_BOULDER:
|
||||||
|
spawn_boulder(scene, tile_idx);
|
||||||
|
break;
|
||||||
|
case SPAWN_CRATE_ARROW_L:
|
||||||
|
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_LEFT_ARROW);
|
||||||
|
break;
|
||||||
|
case SPAWN_CRATE_ARROW_R:
|
||||||
|
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_RIGHT_ARROW);
|
||||||
|
break;
|
||||||
|
case SPAWN_CRATE_ARROW_U:
|
||||||
|
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_UP_ARROW);
|
||||||
|
break;
|
||||||
|
case SPAWN_CRATE_ARROW_D:
|
||||||
|
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_DOWN_ARROW);
|
||||||
|
break;
|
||||||
|
case SPAWN_CRATE_BOMB:
|
||||||
|
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_BOMB);
|
||||||
|
break;
|
||||||
|
case SPAWN_WATER_RUNNER:
|
||||||
{
|
{
|
||||||
tilemap.tiles[tile_idx].water_level = MAX_WATER_LEVEL;
|
Entity_t* p_ent = create_water_runner(&scene->ent_manager, DEFAULT_MAP_WIDTH, DEFAULT_MAP_HEIGHT, tile_idx);
|
||||||
|
if (p_ent != NULL)
|
||||||
|
{
|
||||||
|
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
|
||||||
|
p_ct->position.x = (tile_idx % tilemap.width) * tilemap.tile_size;
|
||||||
|
p_ct->position.y = (tile_idx / tilemap.width) * tilemap.tile_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
tilemap.tiles[tile_idx].water_level = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPAWN_CRATE:
|
|
||||||
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_EMPTY);
|
|
||||||
break;
|
|
||||||
case SPAWN_BOULDER:
|
|
||||||
spawn_boulder(scene, tile_idx);
|
|
||||||
break;
|
|
||||||
case SPAWN_CRATE_ARROW_L:
|
|
||||||
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_LEFT_ARROW);
|
|
||||||
break;
|
|
||||||
case SPAWN_CRATE_ARROW_R:
|
|
||||||
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_RIGHT_ARROW);
|
|
||||||
break;
|
|
||||||
case SPAWN_CRATE_ARROW_U:
|
|
||||||
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_UP_ARROW);
|
|
||||||
break;
|
|
||||||
case SPAWN_CRATE_ARROW_D:
|
|
||||||
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_DOWN_ARROW);
|
|
||||||
break;
|
|
||||||
case SPAWN_CRATE_BOMB:
|
|
||||||
spawn_crate(scene, tile_idx, metal_toggle, CONTAINER_BOMB);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
change_a_tile(&tilemap, tile_idx, new_type);
|
change_a_tile(&tilemap, tile_idx, new_type);
|
||||||
last_tile_idx = tile_idx;
|
last_tile_idx = tile_idx;
|
||||||
|
CWaterRunner_t* p_crunner;
|
||||||
|
sc_map_foreach_value(&scene->ent_manager.component_map[CWATERRUNNER_T], p_crunner)
|
||||||
|
{
|
||||||
|
p_crunner->state = BFS_RESET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON))
|
else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON))
|
||||||
{
|
{
|
||||||
|
@ -558,7 +605,16 @@ static void toggle_block_system(Scene_t* scene)
|
||||||
unsigned int tile_idx = p_tilecoord->tiles[i];
|
unsigned int tile_idx = p_tilecoord->tiles[i];
|
||||||
sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), m_id);
|
sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), m_id);
|
||||||
}
|
}
|
||||||
remove_entity(&scene->ent_manager, m_id);
|
//remove_entity(&scene->ent_manager, m_id);
|
||||||
|
CWaterRunner_t* p_crunner = get_component(ent, CWATERRUNNER_T);
|
||||||
|
if (p_crunner == NULL)
|
||||||
|
{
|
||||||
|
remove_entity(&scene->ent_manager, m_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free_water_runner(ent, &scene->ent_manager);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -666,6 +722,7 @@ void init_level_scene(LevelScene_t* scene)
|
||||||
sc_array_add(&scene->scene.systems, &camera_update_system);
|
sc_array_add(&scene->scene.systems, &camera_update_system);
|
||||||
sc_array_add(&scene->scene.systems, &player_dir_reset_system);
|
sc_array_add(&scene->scene.systems, &player_dir_reset_system);
|
||||||
sc_array_add(&scene->scene.systems, &player_respawn_system);
|
sc_array_add(&scene->scene.systems, &player_respawn_system);
|
||||||
|
sc_array_add(&scene->scene.systems, &update_water_runner_system);
|
||||||
sc_array_add(&scene->scene.systems, &toggle_block_system);
|
sc_array_add(&scene->scene.systems, &toggle_block_system);
|
||||||
|
|
||||||
// This avoid graphical glitch, not essential
|
// This avoid graphical glitch, not essential
|
||||||
|
@ -693,6 +750,7 @@ void init_level_scene(LevelScene_t* scene)
|
||||||
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 = 4;
|
||||||
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};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ typedef struct Tile {
|
||||||
unsigned int tile_type;
|
unsigned int tile_type;
|
||||||
SolidType_t solid;
|
SolidType_t solid;
|
||||||
uint8_t def;
|
uint8_t def;
|
||||||
unsigned int water_level;
|
uint8_t water_level;
|
||||||
|
uint8_t max_water_level;
|
||||||
struct sc_map_64v entities_set;
|
struct sc_map_64v entities_set;
|
||||||
Vector2 offset;
|
Vector2 offset;
|
||||||
Vector2 size;
|
Vector2 size;
|
||||||
|
@ -27,7 +28,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;
|
//unsigned int max_water_level;
|
||||||
Tile_t* tiles;
|
Tile_t* tiles;
|
||||||
}TileGrid_t;
|
}TileGrid_t;
|
||||||
|
|
||||||
|
|
|
@ -869,27 +869,35 @@ void global_external_forces_system(Scene_t* scene)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 half_size = {0, 0};
|
|
||||||
if (p_bbox != NULL)
|
|
||||||
{
|
|
||||||
half_size = p_bbox->half_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(p_mstate->ground_state & 1))
|
if (!(p_mstate->ground_state & 1))
|
||||||
{
|
{
|
||||||
// Only apply upthrust if center is in water
|
// Only apply upthrust if center is in water
|
||||||
// If need more accuracy, need to find area of overlap
|
// If need more accuracy, need to find area of overlap
|
||||||
if (p_mstate->water_state & 1)
|
if (p_mstate->water_state & 1)
|
||||||
{
|
{
|
||||||
|
Vector2 player_center = (Vector2){
|
||||||
|
.x = p_ctransform->position.x + p_bbox->half_size.x,
|
||||||
|
.y = p_ctransform->position.y + p_bbox->half_size.y,
|
||||||
|
};
|
||||||
unsigned int tile_idx = get_tile_idx(
|
unsigned int tile_idx = get_tile_idx(
|
||||||
p_ctransform->position.x + half_size.x,
|
player_center.x,
|
||||||
p_ctransform->position.y + half_size.y,
|
player_center.y,
|
||||||
data->tilemap.width
|
data->tilemap.width
|
||||||
);
|
);
|
||||||
|
|
||||||
if (data->tilemap.tiles[tile_idx].water_level > 0)
|
if (data->tilemap.tiles[tile_idx].water_level > 0)
|
||||||
{
|
{
|
||||||
p_ctransform->accel = Vector2Add(p_ctransform->accel, UPTHRUST);
|
uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP;
|
||||||
|
Rectangle box = {
|
||||||
|
.x = (tile_idx % data->tilemap.width) * data->tilemap.tile_size,
|
||||||
|
.y = (tile_idx / data->tilemap.width + 1) * data->tilemap.tile_size - water_height,
|
||||||
|
.width = data->tilemap.tile_size,
|
||||||
|
.height = water_height,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (point_in_AABB(player_center, box))
|
||||||
|
{
|
||||||
|
p_ctransform->accel = Vector2Add(p_ctransform->accel, UPTHRUST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY);
|
p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY);
|
||||||
|
@ -1318,12 +1326,27 @@ void state_transition_update_system(Scene_t* scene)
|
||||||
bool in_water = false;
|
bool in_water = false;
|
||||||
if (!(p_mstate->water_state & 1))
|
if (!(p_mstate->water_state & 1))
|
||||||
{
|
{
|
||||||
|
Vector2 player_center = (Vector2){
|
||||||
|
.x = p_ctransform->position.x + p_bbox->half_size.x,
|
||||||
|
.y = p_ctransform->position.y + p_bbox->half_size.y,
|
||||||
|
};
|
||||||
unsigned int tile_idx = get_tile_idx(
|
unsigned int tile_idx = get_tile_idx(
|
||||||
p_ctransform->position.x + p_bbox->half_size.x,
|
player_center.x,
|
||||||
p_ctransform->position.y + p_bbox->half_size.y,
|
player_center.y,
|
||||||
data->tilemap.width
|
data->tilemap.width
|
||||||
);
|
);
|
||||||
in_water = (data->tilemap.tiles[tile_idx].water_level > 0);
|
if (data->tilemap.tiles[tile_idx].water_level > 0)
|
||||||
|
{
|
||||||
|
uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP;
|
||||||
|
Rectangle box = {
|
||||||
|
.x = (tile_idx % data->tilemap.width) * data->tilemap.tile_size,
|
||||||
|
.y = (tile_idx / data->tilemap.width + 1) * data->tilemap.tile_size - water_height,
|
||||||
|
.width = data->tilemap.tile_size,
|
||||||
|
.height = water_height,
|
||||||
|
};
|
||||||
|
|
||||||
|
in_water = point_in_AABB(player_center, box);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "water_flow.h"
|
#include "water_flow.h"
|
||||||
|
#include "constants.h"
|
||||||
#include "sc/queue/sc_queue.h"
|
#include "sc/queue/sc_queue.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
Entity_t* create_water_runner(EntityManager_t* ent_manager, int32_t width, int32_t height, int32_t start_tile)
|
Entity_t* create_water_runner(EntityManager_t* ent_manager, int32_t width, int32_t height, int32_t start_tile)
|
||||||
|
@ -70,7 +71,7 @@ static void runner_BFS(const TileGrid_t* tilemap, CWaterRunner_t* p_crunner, int
|
||||||
|
|
||||||
if (
|
if (
|
||||||
((curr_height <= init_height && !first_reached) || curr_height > curr_low)
|
((curr_height <= init_height && !first_reached) || curr_height > curr_low)
|
||||||
&& curr_tile->water_level < tilemap->max_water_level
|
&& curr_tile->water_level < curr_tile->max_water_level
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
first_reached = true;
|
first_reached = true;
|
||||||
|
@ -80,37 +81,37 @@ static void runner_BFS(const TileGrid_t* tilemap, CWaterRunner_t* p_crunner, int
|
||||||
|
|
||||||
if (next < p_crunner->bfs_tilemap.len)
|
if (next < p_crunner->bfs_tilemap.len)
|
||||||
{
|
{
|
||||||
to_go[0] = next_tile->solid != SOLID;
|
to_go[0] = (next_tile->solid != SOLID && next_tile->max_water_level == MAX_WATER_LEVEL);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
next_tile->solid == SOLID
|
next_tile->solid == SOLID
|
||||||
|| next_tile->water_level == tilemap->max_water_level
|
|| next_tile->water_level >= next_tile->max_water_level
|
||||||
|| curr_tile->water_level == tilemap->max_water_level
|
|| curr_tile->water_level >= curr_tile->max_water_level
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (curr_idx % p_crunner->bfs_tilemap.width != 0)
|
if (curr_idx % p_crunner->bfs_tilemap.width != 0)
|
||||||
{
|
{
|
||||||
next = curr_idx - 1;
|
next = curr_idx - 1;
|
||||||
next_tile = tilemap->tiles + next;
|
next_tile = tilemap->tiles + next;
|
||||||
to_go[1] = next_tile->solid != SOLID;
|
to_go[1] = (next_tile->solid != SOLID && next_tile->max_water_level == 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;
|
||||||
to_go[2] = next_tile->solid != SOLID;
|
to_go[2] = (next_tile->solid != SOLID && next_tile->max_water_level == MAX_WATER_LEVEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr_tile->water_level == tilemap->max_water_level)
|
if (curr_tile->water_level >= curr_tile->max_water_level)
|
||||||
{
|
{
|
||||||
|
|
||||||
next = curr_idx - p_crunner->bfs_tilemap.width;
|
next = curr_idx - p_crunner->bfs_tilemap.width;
|
||||||
if (next >= 0)
|
if (next >= 0)
|
||||||
{
|
{
|
||||||
next_tile = tilemap->tiles + next;
|
next_tile = tilemap->tiles + next;
|
||||||
to_go[3] = next_tile->solid != SOLID;
|
to_go[3] = (next_tile->solid != SOLID && next_tile->max_water_level == MAX_WATER_LEVEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +167,7 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
{
|
{
|
||||||
// Use previously store tile position
|
// Use previously store tile position
|
||||||
// Clear from those positions
|
// Clear from those positions
|
||||||
unsigned int tile_idx = p_tilecoord->tiles[i];
|
int tile_idx = p_tilecoord->tiles[i];
|
||||||
sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), ent_idx);
|
sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), ent_idx);
|
||||||
}
|
}
|
||||||
free_water_runner(ent, &scene->ent_manager);
|
free_water_runner(ent, &scene->ent_manager);
|
||||||
|
@ -192,8 +193,8 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
runner_BFS(&tilemap, p_crunner, &lowest_tile, p_crunner->current_tile);
|
runner_BFS(&tilemap, p_crunner, &lowest_tile, p_crunner->current_tile);
|
||||||
p_crunner->target_tile = lowest_tile;
|
p_crunner->target_tile = lowest_tile;
|
||||||
// Trace path from lowest_tile
|
// Trace path from lowest_tile
|
||||||
unsigned int prev_idx = lowest_tile;
|
int prev_idx = lowest_tile;
|
||||||
unsigned int curr_idx = p_crunner->bfs_tilemap.tilemap[prev_idx].from;
|
int curr_idx = p_crunner->bfs_tilemap.tilemap[prev_idx].from;
|
||||||
while (p_crunner->bfs_tilemap.tilemap[prev_idx].from >= 0)
|
while (p_crunner->bfs_tilemap.tilemap[prev_idx].from >= 0)
|
||||||
{
|
{
|
||||||
p_crunner->bfs_tilemap.tilemap[curr_idx].to = prev_idx;
|
p_crunner->bfs_tilemap.tilemap[curr_idx].to = prev_idx;
|
||||||
|
@ -227,7 +228,8 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
break;
|
break;
|
||||||
case REACHABILITY_SEARCH:
|
case REACHABILITY_SEARCH:
|
||||||
{
|
{
|
||||||
if (tilemap.tiles[p_crunner->current_tile].water_level == tilemap.max_water_level)
|
Tile_t* curr_tile = tilemap.tiles + p_crunner->current_tile;
|
||||||
|
if (curr_tile->water_level >= curr_tile->max_water_level)
|
||||||
{
|
{
|
||||||
p_crunner->state = BFS_RESET;
|
p_crunner->state = BFS_RESET;
|
||||||
break;
|
break;
|
||||||
|
@ -271,6 +273,7 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
break;
|
break;
|
||||||
case SCANLINE_FILL:
|
case SCANLINE_FILL:
|
||||||
{
|
{
|
||||||
|
// Unsigned usage here is okay
|
||||||
unsigned int start_tile =
|
unsigned int start_tile =
|
||||||
(p_crunner->current_tile / p_crunner->bfs_tilemap.width) * p_crunner->bfs_tilemap.width;
|
(p_crunner->current_tile / p_crunner->bfs_tilemap.width) * p_crunner->bfs_tilemap.width;
|
||||||
//for (size_t i = 0; i < 10; ++i)
|
//for (size_t i = 0; i < 10; ++i)
|
||||||
|
@ -281,11 +284,11 @@ void update_water_runner_system(Scene_t* scene)
|
||||||
p_crunner->bfs_tilemap.tilemap[curr_idx].reachable
|
p_crunner->bfs_tilemap.tilemap[curr_idx].reachable
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (curr_tile->water_level < tilemap.max_water_level)
|
if (curr_tile->water_level < curr_tile->max_water_level)
|
||||||
{
|
{
|
||||||
curr_tile->water_level++;
|
curr_tile->water_level++;
|
||||||
}
|
}
|
||||||
if (curr_tile->water_level != tilemap.max_water_level)
|
if (curr_tile->water_level < curr_tile->max_water_level)
|
||||||
{
|
{
|
||||||
p_crunner->counter++;
|
p_crunner->counter++;
|
||||||
}
|
}
|
||||||
|
|
27
water_test.c
27
water_test.c
|
@ -55,19 +55,16 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, BLACK);
|
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (tilemap.tiles[i].water_level > 0)
|
uint32_t water_height = tilemap.tiles[i].water_level * WATER_BBOX_STEP;
|
||||||
{
|
// Draw water tile
|
||||||
float water_height = tilemap.tiles[i].water_level * 1.0f / tilemap.max_water_level;
|
Color water_colour = ColorAlpha(BLUE, 0.5);
|
||||||
// Draw water tile
|
DrawRectangle(
|
||||||
Color water_colour = ColorAlpha(BLUE, 0.5);
|
x,
|
||||||
DrawRectangle(
|
y + (TILE_SIZE - water_height),
|
||||||
x,
|
TILE_SIZE,
|
||||||
y + (1.0f - water_height) * TILE_SIZE,
|
water_height,
|
||||||
TILE_SIZE,
|
water_colour
|
||||||
water_height * TILE_SIZE,
|
);
|
||||||
water_colour
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
|
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
|
||||||
|
@ -237,7 +234,7 @@ static void toggle_block_system(Scene_t* scene)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tilemap.tiles[tile_idx].water_level = tilemap.max_water_level;
|
tilemap.tiles[tile_idx].water_level = tilemap.tiles[tile_idx].max_water_level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +359,6 @@ 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 = 4;
|
|
||||||
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;
|
||||||
|
@ -372,6 +368,7 @@ 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 = 4;
|
||||||
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};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue