Compare commits
4 Commits
9859854baa
...
fe2bcdf8cd
Author | SHA1 | Date |
---|---|---|
|
fe2bcdf8cd | |
|
7dcff39864 | |
|
e74f523b7f | |
|
b578dd95f7 |
|
@ -17,12 +17,16 @@ enum EntitySpawnSelection {
|
|||
TOGGLE_SPIKE,
|
||||
TOGGLE_WATER,
|
||||
SPAWN_CRATE,
|
||||
SPAWN_METAL_CRATE,
|
||||
SPAWN_CRATE_ARROW_L,
|
||||
SPAWN_CRATE_ARROW_R,
|
||||
SPAWN_CRATE_ARROW_U,
|
||||
SPAWN_CRATE_ARROW_D,
|
||||
SPAWN_BOULDER,
|
||||
};
|
||||
|
||||
#define MAX_SPAWN_TYPE 8
|
||||
#define MAX_SPAWN_TYPE 11
|
||||
static unsigned int current_spawn_selection = 0;
|
||||
static bool metal_toggle = false;
|
||||
|
||||
#define SELECTION_TILE_SIZE 32
|
||||
#define SELECTION_TILE_HALFSIZE (SELECTION_TILE_SIZE >> 1)
|
||||
|
@ -53,8 +57,7 @@ static char* get_spawn_selection_string(enum EntitySpawnSelection sel)
|
|||
case TOGGLE_LADDER: return "ladder";
|
||||
case TOGGLE_SPIKE: return "spike";
|
||||
case TOGGLE_WATER: return "water";
|
||||
case SPAWN_CRATE: return "wooden crate";
|
||||
case SPAWN_METAL_CRATE: return "metal crate";
|
||||
case SPAWN_CRATE: return "crate";
|
||||
case SPAWN_BOULDER: return "boulder";
|
||||
default: return "unknown";
|
||||
}
|
||||
|
@ -138,14 +141,67 @@ static void level_scene_render_func(Scene_t* scene)
|
|||
break;
|
||||
}
|
||||
|
||||
if (p_ent->m_tag == BOULDER_ENT_TAG)
|
||||
if (p_bbox != NULL)
|
||||
{
|
||||
DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, colour);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour);
|
||||
if (p_ent->m_tag == BOULDER_ENT_TAG)
|
||||
{
|
||||
DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, colour);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour);
|
||||
}
|
||||
|
||||
if (p_ent->m_tag == CRATES_ENT_TAG)
|
||||
{
|
||||
CContainer_t* p_container = get_component(p_ent, CCONTAINER_T);
|
||||
if (p_container != NULL)
|
||||
{
|
||||
switch (p_container->item)
|
||||
{
|
||||
case CONTAINER_LEFT_ARROW:
|
||||
DrawLine(
|
||||
p_ct->position.x,
|
||||
p_ct->position.y + p_bbox->half_size.y,
|
||||
p_ct->position.x + p_bbox->half_size.x,
|
||||
p_ct->position.y + p_bbox->half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case CONTAINER_RIGHT_ARROW:
|
||||
DrawLine(
|
||||
p_ct->position.x + p_bbox->half_size.x,
|
||||
p_ct->position.y + p_bbox->half_size.y,
|
||||
p_ct->position.x + p_bbox->size.x,
|
||||
p_ct->position.y + p_bbox->half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case CONTAINER_UP_ARROW:
|
||||
DrawLine(
|
||||
p_ct->position.x + p_bbox->half_size.x,
|
||||
p_ct->position.y,
|
||||
p_ct->position.x + p_bbox->half_size.x,
|
||||
p_ct->position.y + p_bbox->half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case CONTAINER_DOWN_ARROW:
|
||||
DrawLine(
|
||||
p_ct->position.x + p_bbox->half_size.x,
|
||||
p_ct->position.y + p_bbox->half_size.y,
|
||||
p_ct->position.x + p_bbox->half_size.x,
|
||||
p_ct->position.y + p_bbox->size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHurtbox_t* p_hurtbox = get_component(p_ent, CHURTBOX_T);
|
||||
CHitBoxes_t* p_hitbox = get_component(p_ent, CHITBOXES_T);
|
||||
if (p_hitbox != NULL)
|
||||
|
@ -228,22 +284,61 @@ 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};
|
||||
const Color draw_colour[MAX_SPAWN_TYPE] = {BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5), BROWN, GRAY, ColorAlpha(RAYWHITE, 0.5)};
|
||||
const Color crate_colour = metal_toggle ? GRAY : BROWN;
|
||||
const Color draw_colour[MAX_SPAWN_TYPE] = {
|
||||
BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5),
|
||||
crate_colour, crate_colour, crate_colour, crate_colour, crate_colour,
|
||||
ColorAlpha(RAYWHITE, 0.5)
|
||||
};
|
||||
for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i)
|
||||
{
|
||||
if (i != current_spawn_selection)
|
||||
{
|
||||
DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, draw_colour[i]);
|
||||
Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE};
|
||||
switch (i)
|
||||
{
|
||||
case 3:
|
||||
case TOGGLE_SPIKE:
|
||||
DrawRectangle(draw_pos.x, draw_pos.y + SELECTION_TILE_HALFSIZE, SELECTION_TILE_SIZE, SELECTION_TILE_HALFSIZE, RED);
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE};
|
||||
case SPAWN_BOULDER:
|
||||
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GRAY);
|
||||
}
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_L:
|
||||
DrawLine(
|
||||
draw_pos.x,
|
||||
draw_pos.y + half_size.y,
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_R:
|
||||
DrawLine(
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
draw_pos.x + half_size.x * 2,
|
||||
draw_pos.y + half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_U:
|
||||
DrawLine(
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y,
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_D:
|
||||
DrawLine(
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y * 2,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -256,16 +351,50 @@ static void level_scene_render_func(Scene_t* scene)
|
|||
SELECTION_TILE_SIZE + 4, SELECTION_TILE_SIZE + 4, GREEN
|
||||
);
|
||||
DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, draw_colour[current_spawn_selection]);
|
||||
const Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE};
|
||||
switch (current_spawn_selection)
|
||||
{
|
||||
case 3:
|
||||
case TOGGLE_SPIKE:
|
||||
DrawRectangle(draw_pos.x, draw_pos.y + SELECTION_TILE_HALFSIZE, SELECTION_TILE_SIZE, SELECTION_TILE_HALFSIZE, RED);
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
const Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE};
|
||||
case SPAWN_BOULDER:
|
||||
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GRAY);
|
||||
}
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_L:
|
||||
DrawLine(
|
||||
draw_pos.x,
|
||||
draw_pos.y + half_size.y,
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_R:
|
||||
DrawLine(
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
draw_pos.x + half_size.x * 2,
|
||||
draw_pos.y + half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_U:
|
||||
DrawLine(
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y,
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
case SPAWN_CRATE_ARROW_D:
|
||||
DrawLine(
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y,
|
||||
draw_pos.x + half_size.x,
|
||||
draw_pos.y + half_size.y * 2,
|
||||
BLACK
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -305,10 +434,10 @@ static void level_scene_render_func(Scene_t* scene)
|
|||
EndDrawing();
|
||||
}
|
||||
|
||||
static void spawn_crate(Scene_t* scene, unsigned int tile_idx, bool metal)
|
||||
static void spawn_crate(Scene_t* scene, unsigned int tile_idx, bool metal, ContainerItem_t item)
|
||||
{
|
||||
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
|
||||
Entity_t* p_crate = create_crate(&scene->ent_manager, &scene->engine->assets, metal);
|
||||
Entity_t* p_crate = create_crate(&scene->ent_manager, &scene->engine->assets, metal, item);
|
||||
|
||||
CTransform_t* p_ctransform = get_component(p_crate, CTRANSFORM_COMP_T);
|
||||
p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
|
||||
|
@ -346,70 +475,24 @@ static void toggle_block_system(Scene_t* scene)
|
|||
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
|
||||
{
|
||||
enum EntitySpawnSelection sel = (enum EntitySpawnSelection)current_spawn_selection;
|
||||
TileType_t new_type = EMPTY_TILE;
|
||||
switch (sel)
|
||||
{
|
||||
case TOGGLE_TILE:
|
||||
if (tilemap.tiles[tile_idx].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
|
||||
tilemap.tiles[tile_idx].solid = NOT_SOLID;
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = SOLID_TILE;
|
||||
tilemap.tiles[tile_idx].solid = SOLID;
|
||||
}
|
||||
tilemap.tiles[tile_idx].water_level = 0;
|
||||
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;
|
||||
break;
|
||||
case TOGGLE_ONEWAY:
|
||||
if (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE)
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
|
||||
tilemap.tiles[tile_idx].solid = NOT_SOLID;
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = ONEWAY_TILE;
|
||||
tilemap.tiles[tile_idx].solid = ONE_WAY;
|
||||
}
|
||||
new_type = (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE)? EMPTY_TILE : ONEWAY_TILE;
|
||||
break;
|
||||
case TOGGLE_LADDER:
|
||||
if (tilemap.tiles[tile_idx].tile_type == LADDER)
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
|
||||
tilemap.tiles[tile_idx].solid = NOT_SOLID;
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = LADDER;
|
||||
int up_tile = tile_idx - tilemap.width;
|
||||
if (up_tile > 0 && tilemap.tiles[up_tile].tile_type != LADDER)
|
||||
{
|
||||
tilemap.tiles[tile_idx].solid = ONE_WAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].solid = NOT_SOLID;
|
||||
}
|
||||
}
|
||||
int down_tile = tile_idx + tilemap.width;
|
||||
if (down_tile < MAX_N_TILES && tilemap.tiles[down_tile].tile_type == LADDER)
|
||||
{
|
||||
tilemap.tiles[down_tile].solid = (tilemap.tiles[tile_idx].tile_type != LADDER)? ONE_WAY : NOT_SOLID;
|
||||
}
|
||||
new_type = (tilemap.tiles[tile_idx].tile_type == LADDER)? EMPTY_TILE : LADDER;
|
||||
break;
|
||||
case TOGGLE_SPIKE:
|
||||
if (tilemap.tiles[tile_idx].tile_type == SPIKES)
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = SPIKES;
|
||||
}
|
||||
tilemap.tiles[tile_idx].solid = NOT_SOLID;
|
||||
new_type = (tilemap.tiles[tile_idx].tile_type == SPIKES)? EMPTY_TILE : SPIKES;
|
||||
break;
|
||||
case TOGGLE_WATER:
|
||||
new_type = tilemap.tiles[tile_idx].tile_type;
|
||||
if (tilemap.tiles[tile_idx].water_level == 0)
|
||||
{
|
||||
tilemap.tiles[tile_idx].water_level = MAX_WATER_LEVEL;
|
||||
|
@ -420,62 +503,31 @@ static void toggle_block_system(Scene_t* scene)
|
|||
}
|
||||
break;
|
||||
case SPAWN_CRATE:
|
||||
spawn_crate(scene, tile_idx, false);
|
||||
break;
|
||||
case SPAWN_METAL_CRATE:
|
||||
spawn_crate(scene, tile_idx, true);
|
||||
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;
|
||||
}
|
||||
|
||||
if (tilemap.tiles[tile_idx].tile_type == SPIKES)
|
||||
{
|
||||
// Priority: Down, Up, Left, Right
|
||||
if (tile_idx + tilemap.width < MAX_N_TILES && tilemap.tiles[tile_idx + tilemap.width].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap.tiles[tile_idx].offset = (Vector2){0,16};
|
||||
tilemap.tiles[tile_idx].size = (Vector2){32,16};
|
||||
}
|
||||
else if (tile_idx - tilemap.width >= 0 && tilemap.tiles[tile_idx - tilemap.width].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap.tiles[tile_idx].size = (Vector2){32,16};
|
||||
}
|
||||
else if (tile_idx % tilemap.width != 0 && tilemap.tiles[tile_idx - 1].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap.tiles[tile_idx].size = (Vector2){16,32};
|
||||
}
|
||||
else if ((tile_idx + 1) % tilemap.width != 0 && tilemap.tiles[tile_idx + 1].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap.tiles[tile_idx].offset = (Vector2){16,0};
|
||||
tilemap.tiles[tile_idx].size = (Vector2){16,32};
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].offset = (Vector2){0,16};
|
||||
tilemap.tiles[tile_idx].size = (Vector2){32,16};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap.tiles[tile_idx].size = (Vector2){32,32};
|
||||
}
|
||||
change_a_tile(&tilemap, tile_idx, new_type);
|
||||
last_tile_idx = tile_idx;
|
||||
tilemap.tiles[tile_idx].moveable = (
|
||||
tilemap.tiles[tile_idx].tile_type == EMPTY_TILE
|
||||
|| tilemap.tiles[tile_idx].tile_type == SPIKES
|
||||
);
|
||||
}
|
||||
else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON))
|
||||
{
|
||||
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
|
||||
tilemap.tiles[tile_idx].solid = NOT_SOLID;
|
||||
change_a_tile(&tilemap, tile_idx, EMPTY_TILE);
|
||||
tilemap.tiles[tile_idx].water_level = 0;
|
||||
tilemap.tiles[tile_idx].moveable = true;
|
||||
|
||||
Entity_t* ent;
|
||||
unsigned int m_id;
|
||||
|
@ -555,6 +607,9 @@ void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
|
|||
current_spawn_selection--;
|
||||
}
|
||||
break;
|
||||
case ACTION_METAL_TOGGLE:
|
||||
if (!pressed) metal_toggle = !metal_toggle;
|
||||
break;
|
||||
case ACTION_EXIT:
|
||||
if(scene->engine != NULL)
|
||||
{
|
||||
|
@ -591,6 +646,7 @@ void init_level_scene(LevelScene_t* scene)
|
|||
sc_array_add(&scene->scene.systems, &spike_collision_system);
|
||||
sc_array_add(&scene->scene.systems, &state_transition_update_system);
|
||||
sc_array_add(&scene->scene.systems, &player_ground_air_transition_system);
|
||||
sc_array_add(&scene->scene.systems, &container_destroy_system);
|
||||
sc_array_add(&scene->scene.systems, &sprite_animation_system);
|
||||
sc_array_add(&scene->scene.systems, &camera_update_system);
|
||||
sc_array_add(&scene->scene.systems, &player_dir_reset_system);
|
||||
|
@ -607,6 +663,7 @@ void init_level_scene(LevelScene_t* scene)
|
|||
sc_map_put_64(&scene->scene.action_map, KEY_SPACE, ACTION_JUMP);
|
||||
sc_map_put_64(&scene->scene.action_map, KEY_O, ACTION_PREV_SPAWN);
|
||||
sc_map_put_64(&scene->scene.action_map, KEY_P, ACTION_NEXT_SPAWN);
|
||||
sc_map_put_64(&scene->scene.action_map, KEY_M, ACTION_METAL_TOGGLE);
|
||||
sc_map_put_64(&scene->scene.action_map, KEY_Q, ACTION_EXIT);
|
||||
|
||||
scene->data.tilemap.width = DEFAULT_MAP_WIDTH;
|
||||
|
@ -615,7 +672,7 @@ void init_level_scene(LevelScene_t* scene)
|
|||
assert(scene->data.tilemap.n_tiles <= MAX_N_TILES);
|
||||
scene->data.tilemap.tiles = all_tiles;
|
||||
memset(scene->data.tile_sprites, 0, sizeof(scene->data.tile_sprites));
|
||||
for (size_t i = 0; i < MAX_N_TILES;i++)
|
||||
for (size_t i = 0; i < scene->data.tilemap.n_tiles;i++)
|
||||
{
|
||||
all_tiles[i].solid = NOT_SOLID;
|
||||
all_tiles[i].tile_type = EMPTY_TILE;
|
||||
|
@ -626,9 +683,7 @@ void init_level_scene(LevelScene_t* scene)
|
|||
for (size_t i = 0; i < scene->data.tilemap.width; ++i)
|
||||
{
|
||||
unsigned int tile_idx = (scene->data.tilemap.height - 1) * scene->data.tilemap.width + i;
|
||||
all_tiles[tile_idx].solid = SOLID; // for testing
|
||||
all_tiles[tile_idx].tile_type = SOLID_TILE; // for testing
|
||||
all_tiles[tile_idx].moveable = false;
|
||||
change_a_tile(&scene->data.tilemap, tile_idx, SOLID_TILE);
|
||||
}
|
||||
|
||||
create_player(&scene->scene.ent_manager, &scene->scene.engine->assets);
|
||||
|
@ -638,7 +693,7 @@ void init_level_scene(LevelScene_t* scene)
|
|||
void free_level_scene(LevelScene_t* scene)
|
||||
{
|
||||
free_scene(&scene->scene);
|
||||
for (size_t i = 0; i < MAX_N_TILES;i++)
|
||||
for (size_t i = 0; i < scene->data.tilemap.n_tiles;i++)
|
||||
{
|
||||
all_tiles[i].solid = 0;
|
||||
sc_map_term_64v(&all_tiles[i].entities_set);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "sc/map/sc_map.h"
|
||||
#include "sc/queue/sc_queue.h"
|
||||
|
||||
#define N_TAGS 5
|
||||
#define N_TAGS 8
|
||||
#define N_COMPONENTS 11
|
||||
#define MAX_COMP_POOL_SIZE 1024
|
||||
typedef struct EntityManager EntityManager_t;
|
||||
|
@ -110,6 +110,7 @@ typedef struct _CHitBoxes_t {
|
|||
Rectangle boxes[2];
|
||||
uint8_t n_boxes;
|
||||
uint8_t atk;
|
||||
bool one_hit;
|
||||
} CHitBoxes_t;
|
||||
|
||||
typedef struct _CHurtbox_t {
|
||||
|
|
|
@ -9,6 +9,7 @@ typedef enum ActionType
|
|||
ACTION_JUMP,
|
||||
ACTION_NEXT_SPAWN,
|
||||
ACTION_PREV_SPAWN,
|
||||
ACTION_METAL_TOGGLE,
|
||||
ACTION_CONFIRM,
|
||||
ACTION_EXIT,
|
||||
}ActionType_t;
|
||||
|
|
|
@ -8,12 +8,14 @@ typedef enum EntityTag {
|
|||
ENEMY_ENT_TAG,
|
||||
CRATES_ENT_TAG,
|
||||
BOULDER_ENT_TAG,
|
||||
ARROW_ENT_TAG,
|
||||
} EntityTag_t;
|
||||
|
||||
|
||||
bool init_player_creation(const char* info_file, Assets_t* assets);
|
||||
Entity_t* create_player(EntityManager_t* ent_manager, Assets_t* assets);
|
||||
Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal);
|
||||
Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal, ContainerItem_t item);
|
||||
Entity_t* create_boulder(EntityManager_t* ent_manager, Assets_t* assets);
|
||||
Entity_t* create_arrow(EntityManager_t* ent_manager, Assets_t* assets, uint8_t dir);
|
||||
|
||||
#endif // __ENT_IMPL_H
|
||||
|
|
|
@ -40,6 +40,105 @@ typedef struct CollideEntity {
|
|||
TileArea_t area;
|
||||
} CollideEntity_t;
|
||||
|
||||
void change_a_tile(TileGrid_t* tilemap, unsigned int tile_idx, TileType_t new_type)
|
||||
{
|
||||
tilemap->tiles[tile_idx].tile_type = new_type;
|
||||
|
||||
switch (new_type)
|
||||
{
|
||||
case EMPTY_TILE:
|
||||
tilemap->tiles[tile_idx].solid = NOT_SOLID;
|
||||
break;
|
||||
case ONEWAY_TILE:
|
||||
tilemap->tiles[tile_idx].solid = ONE_WAY;
|
||||
break;
|
||||
case LADDER:
|
||||
{
|
||||
int up_tile = tile_idx - tilemap->width;
|
||||
if (up_tile > 0 && tilemap->tiles[up_tile].tile_type != LADDER)
|
||||
{
|
||||
tilemap->tiles[tile_idx].solid = ONE_WAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap->tiles[tile_idx].solid = NOT_SOLID;
|
||||
}
|
||||
int down_tile = tile_idx + tilemap->width;
|
||||
if (down_tile < tilemap->n_tiles && tilemap->tiles[down_tile].tile_type == LADDER)
|
||||
{
|
||||
tilemap->tiles[down_tile].solid = (tilemap->tiles[tile_idx].tile_type != LADDER)? ONE_WAY : NOT_SOLID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPIKES:
|
||||
tilemap->tiles[tile_idx].solid = NOT_SOLID;
|
||||
break;
|
||||
case SOLID_TILE:
|
||||
tilemap->tiles[tile_idx].solid = SOLID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (new_type == SPIKES)
|
||||
{
|
||||
// Priority: Down, Up, Left, Right
|
||||
if (tile_idx + tilemap->width < tilemap->n_tiles && tilemap->tiles[tile_idx + tilemap->width].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){0,16};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){32,16};
|
||||
}
|
||||
else if (tile_idx - tilemap->width >= 0 && tilemap->tiles[tile_idx - tilemap->width].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){32,16};
|
||||
}
|
||||
else if (tile_idx % tilemap->width != 0 && tilemap->tiles[tile_idx - 1].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){16,32};
|
||||
}
|
||||
else if ((tile_idx + 1) % tilemap->width != 0 && tilemap->tiles[tile_idx + 1].tile_type == SOLID_TILE)
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){16,0};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){16,32};
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){0,16};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){32,16};
|
||||
}
|
||||
}
|
||||
else if (new_type == ONEWAY_TILE)
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){32,10};
|
||||
}
|
||||
else
|
||||
{
|
||||
tilemap->tiles[tile_idx].offset = (Vector2){0,0};
|
||||
tilemap->tiles[tile_idx].size = (Vector2){32,32};
|
||||
}
|
||||
|
||||
tilemap->tiles[tile_idx].moveable = (
|
||||
tilemap->tiles[tile_idx].tile_type == EMPTY_TILE
|
||||
|| tilemap->tiles[tile_idx].tile_type == SPIKES
|
||||
);
|
||||
tilemap->tiles[tile_idx].def = (tilemap->tiles[tile_idx].tile_type == SOLID_TILE) ? 5: 2;
|
||||
|
||||
}
|
||||
|
||||
static inline void remove_entity_from_tilemap(EntityManager_t *p_manager, TileGrid_t* tilemap, Entity_t* p_ent)
|
||||
{
|
||||
CTileCoord_t* p_tilecoord = get_component(p_ent, CTILECOORD_COMP_T);
|
||||
for (size_t i = 0;i < p_tilecoord->n_tiles; ++i)
|
||||
{
|
||||
// Use previously store tile position
|
||||
// Clear from those positions
|
||||
unsigned int tile_idx = p_tilecoord->tiles[i];
|
||||
sc_map_del_64v(&(tilemap->tiles[tile_idx].entities_set), p_ent->m_id);
|
||||
}
|
||||
remove_entity(p_manager, p_ent->m_id);
|
||||
}
|
||||
|
||||
// ------------------------- Collision functions ------------------------------------
|
||||
// Do not subtract one for the size for any collision check, just pass normally. The extra one is important for AABB test
|
||||
static uint8_t check_collision(const CollideEntity_t* ent, TileGrid_t* grid, bool check_oneway)
|
||||
|
@ -975,7 +1074,7 @@ void friction_coefficient_update_system(Scene_t* scene)
|
|||
|
||||
|
||||
// Friction
|
||||
if (p_mstate->water_state & 1)
|
||||
if (p_mstate != NULL && p_mstate->water_state & 1)
|
||||
{
|
||||
// Apply water friction
|
||||
// Consistent in all direction
|
||||
|
@ -1353,33 +1452,48 @@ void movement_update_system(Scene_t* scene)
|
|||
Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx);
|
||||
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
|
||||
unsigned int level_width = tilemap.width * TILE_SIZE;
|
||||
if(p_ctransform->position.x < 0 || p_ctransform->position.x + p_bbox->size.x > level_width)
|
||||
{
|
||||
p_ctransform->position.x = (p_ctransform->position.x < 0) ? 0 : p_ctransform->position.x;
|
||||
if (p_ctransform->position.x + p_bbox->size.x > level_width)
|
||||
{
|
||||
p_ctransform->position.x = level_width - p_bbox->size.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ctransform->position.x = p_ctransform->position.x;
|
||||
}
|
||||
p_ctransform->velocity.x = 0;
|
||||
}
|
||||
|
||||
unsigned int level_height = tilemap.height * TILE_SIZE;
|
||||
if(p_ctransform->position.y < 0 || p_ctransform->position.y + p_bbox->size.y > level_height)
|
||||
if (p_bbox != NULL)
|
||||
{
|
||||
p_ctransform->position.y = (p_ctransform->position.y < 0) ? 0 : p_ctransform->position.y;
|
||||
if (p_ctransform->position.y + p_bbox->size.y > level_height)
|
||||
|
||||
if(p_ctransform->position.x < 0 || p_ctransform->position.x + p_bbox->size.x > level_width)
|
||||
{
|
||||
p_ctransform->position.y = level_height - p_bbox->size.y;
|
||||
p_ctransform->position.x = (p_ctransform->position.x < 0) ? 0 : p_ctransform->position.x;
|
||||
if (p_ctransform->position.x + p_bbox->size.x > level_width)
|
||||
{
|
||||
p_ctransform->position.x = level_width - p_bbox->size.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ctransform->position.x = p_ctransform->position.x;
|
||||
}
|
||||
p_ctransform->velocity.x = 0;
|
||||
}
|
||||
else
|
||||
|
||||
if(p_ctransform->position.y < 0 || p_ctransform->position.y + p_bbox->size.y > level_height)
|
||||
{
|
||||
p_ctransform->position.y = p_ctransform->position.y;
|
||||
p_ctransform->position.y = (p_ctransform->position.y < 0) ? 0 : p_ctransform->position.y;
|
||||
if (p_ctransform->position.y + p_bbox->size.y > level_height)
|
||||
{
|
||||
p_ctransform->position.y = level_height - p_bbox->size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ctransform->position.y = p_ctransform->position.y;
|
||||
}
|
||||
p_ctransform->velocity.y = 0;
|
||||
}
|
||||
p_ctransform->velocity.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
p_ctransform->position.x < 0 || p_ctransform->position.x > level_width
|
||||
|| p_ctransform->position.y < 0 || p_ctransform->position.y > level_height
|
||||
)
|
||||
{
|
||||
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_ent);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1523,7 +1637,7 @@ void update_tilemap_system(Scene_t* scene)
|
|||
|
||||
void hitbox_update_system(Scene_t* scene)
|
||||
{
|
||||
static bool checked_entities[MAX_COMP_POOL_SIZE] = {0};
|
||||
//static bool checked_entities[MAX_COMP_POOL_SIZE] = {0};
|
||||
|
||||
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
|
||||
TileGrid_t tilemap = data->tilemap;
|
||||
|
@ -1534,6 +1648,7 @@ void hitbox_update_system(Scene_t* scene)
|
|||
sc_map_foreach(&scene->ent_manager.component_map[CHITBOXES_T], ent_idx, p_hitbox)
|
||||
{
|
||||
Entity_t *p_ent = get_entity(&scene->ent_manager, ent_idx);
|
||||
if (!p_ent->m_alive) continue;
|
||||
CTransform_t* p_ctransform = get_component(p_ent, CTRANSFORM_COMP_T);
|
||||
for (uint8_t i = 0; i < p_hitbox->n_boxes; ++i)
|
||||
{
|
||||
|
@ -1554,15 +1669,39 @@ void hitbox_update_system(Scene_t* scene)
|
|||
unsigned int tile_idx = tile_y * tilemap.width + tile_x;
|
||||
unsigned int other_ent_idx;
|
||||
Entity_t* p_other_ent;
|
||||
memset(checked_entities, 0, sizeof(checked_entities));
|
||||
Vector2 overlap;
|
||||
//memset(checked_entities, 0, sizeof(checked_entities));
|
||||
|
||||
if (tilemap.tiles[tile_idx].tile_type != EMPTY_TILE)
|
||||
{
|
||||
Vector2 tile_pos = {tile_x * TILE_SIZE, tile_y * TILE_SIZE};
|
||||
tile_pos = Vector2Add(tile_pos, tilemap.tiles[tile_idx].offset);
|
||||
if (
|
||||
find_AABB_overlap(
|
||||
hitbox_pos, (Vector2){p_hitbox->boxes[i].width, p_hitbox->boxes[i].height},
|
||||
tile_pos, tilemap.tiles[tile_idx].size, &overlap
|
||||
)
|
||||
)
|
||||
{
|
||||
if (p_hitbox->atk > tilemap.tiles[tile_idx].def)
|
||||
{
|
||||
change_a_tile(&tilemap, tile_idx, EMPTY_TILE);
|
||||
}
|
||||
if (p_hitbox->one_hit)
|
||||
{
|
||||
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_ent);
|
||||
goto hitbox_done;
|
||||
}
|
||||
}
|
||||
}
|
||||
sc_map_foreach(&tilemap.tiles[tile_idx].entities_set, other_ent_idx, p_other_ent)
|
||||
{
|
||||
if (other_ent_idx == ent_idx) continue;
|
||||
if (checked_entities[other_ent_idx]) continue;
|
||||
//if (checked_entities[other_ent_idx]) continue;
|
||||
|
||||
Entity_t* p_other_ent = get_entity(&scene->ent_manager, other_ent_idx);
|
||||
if (!p_other_ent->m_alive) continue; // To only allow one way collision check
|
||||
if (p_other_ent->m_tag < p_ent->m_tag) continue; // To only allow one way collision check
|
||||
//if (p_other_ent->m_tag < p_ent->m_tag) continue; // To only allow one way collision check
|
||||
|
||||
CHurtbox_t* p_other_hurtbox = get_component(p_other_ent, CHURTBOX_T);
|
||||
if (p_other_hurtbox == NULL) continue;
|
||||
|
@ -1570,7 +1709,6 @@ void hitbox_update_system(Scene_t* scene)
|
|||
Vector2 hurtbox_pos = Vector2Add(p_other_ct->position, p_other_hurtbox->offset);
|
||||
if (p_hitbox->atk <= p_other_hurtbox->def) continue;
|
||||
|
||||
Vector2 overlap;
|
||||
if (
|
||||
find_AABB_overlap(
|
||||
hitbox_pos, (Vector2){p_hitbox->boxes[i].width, p_hitbox->boxes[i].height},
|
||||
|
@ -1578,13 +1716,14 @@ void hitbox_update_system(Scene_t* scene)
|
|||
)
|
||||
)
|
||||
{
|
||||
//if (p_other_ent->m_tag == CRATES_ENT_TAG)
|
||||
if (p_other_ent->m_tag == CRATES_ENT_TAG)
|
||||
{
|
||||
|
||||
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
|
||||
CPlayerState_t* p_pstate = get_component(p_ent, CPLAYERSTATE_T);
|
||||
if (
|
||||
p_ctransform->position.y + p_bbox->size.y <= p_other_ct->position.y
|
||||
p_pstate != NULL
|
||||
&& p_ctransform->position.y + p_bbox->size.y <= p_other_ct->position.y
|
||||
)
|
||||
{
|
||||
p_ctransform->velocity.y = -400;
|
||||
|
@ -1596,25 +1735,20 @@ void hitbox_update_system(Scene_t* scene)
|
|||
p_cjump->jumped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_other_ent);
|
||||
|
||||
CTileCoord_t* p_tilecoord = get_component(
|
||||
p_other_ent, CTILECOORD_COMP_T
|
||||
);
|
||||
|
||||
for (size_t i = 0;i < p_tilecoord->n_tiles; ++i)
|
||||
{
|
||||
// Use previously store tile position
|
||||
// Clear from those positions
|
||||
unsigned int tile_idx = p_tilecoord->tiles[i];
|
||||
sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), other_ent_idx);
|
||||
}
|
||||
remove_entity(&scene->ent_manager, other_ent_idx);
|
||||
if (p_hitbox->one_hit)
|
||||
{
|
||||
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_ent);
|
||||
goto hitbox_done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hitbox_done: continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1658,6 +1792,44 @@ void boulder_destroy_wooden_tile_system(Scene_t* scene)
|
|||
}
|
||||
}
|
||||
|
||||
void container_destroy_system(Scene_t* scene)
|
||||
{
|
||||
unsigned int ent_idx;
|
||||
CContainer_t* p_container;
|
||||
sc_map_foreach(&scene->ent_manager.component_map[CCONTAINER_T], ent_idx, p_container)
|
||||
{
|
||||
Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx);
|
||||
if (!p_ent->m_alive)
|
||||
{
|
||||
Entity_t* new_ent;
|
||||
switch (p_container->item)
|
||||
{
|
||||
case CONTAINER_LEFT_ARROW:
|
||||
new_ent = create_arrow(&scene->ent_manager, &scene->engine->assets, 0);
|
||||
break;
|
||||
case CONTAINER_RIGHT_ARROW:
|
||||
new_ent = create_arrow(&scene->ent_manager, &scene->engine->assets, 1);
|
||||
break;
|
||||
case CONTAINER_UP_ARROW:
|
||||
new_ent = create_arrow(&scene->ent_manager, &scene->engine->assets, 2);
|
||||
break;
|
||||
case CONTAINER_DOWN_ARROW:
|
||||
new_ent = create_arrow(&scene->ent_manager, &scene->engine->assets, 3);
|
||||
break;
|
||||
default:
|
||||
new_ent = NULL;
|
||||
break;
|
||||
}
|
||||
if (new_ent != NULL)
|
||||
{
|
||||
CTransform_t* new_p_ct = get_component(new_ent, CTRANSFORM_COMP_T);
|
||||
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
|
||||
memcpy(&new_p_ct->position, &p_ct->position, sizeof(Vector2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sprite_animation_system(Scene_t* scene)
|
||||
{
|
||||
unsigned int ent_idx;
|
||||
|
|
|
@ -20,7 +20,11 @@ void hitbox_update_system(Scene_t* scene);
|
|||
void sprite_animation_system(Scene_t* scene);
|
||||
void boulder_destroy_wooden_tile_system(Scene_t* scene);
|
||||
void camera_update_system(Scene_t* scene);
|
||||
void container_destroy_system(Scene_t* scene);
|
||||
void player_dir_reset_system(Scene_t* scene);
|
||||
void player_respawn_system(Scene_t* scene);
|
||||
void spike_collision_system(Scene_t* scene);
|
||||
|
||||
|
||||
void change_a_tile(TileGrid_t* tilemap, unsigned int tile_idx, TileType_t new_type);
|
||||
#endif // __GAME_SYSTEMS_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ent_impl.h"
|
||||
#include "constants.h"
|
||||
|
||||
Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal)
|
||||
Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal, ContainerItem_t item)
|
||||
{
|
||||
Entity_t* p_crate = add_entity(ent_manager, CRATES_ENT_TAG);
|
||||
CBBox_t* p_bbox = add_component(p_crate, CBBOX_COMP_T);
|
||||
|
@ -17,6 +17,13 @@ Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool meta
|
|||
CHurtbox_t* p_hurtbox = add_component(p_crate, CHURTBOX_T);
|
||||
p_hurtbox->size = p_bbox->size;
|
||||
p_hurtbox->def = metal ? 2 : 1;
|
||||
|
||||
if (item != CONTAINER_EMPTY)
|
||||
{
|
||||
CContainer_t* p_container = add_component(p_crate, CCONTAINER_T);
|
||||
p_container->item = item;
|
||||
}
|
||||
|
||||
return p_crate;
|
||||
}
|
||||
|
||||
|
@ -41,3 +48,41 @@ Entity_t* create_boulder(EntityManager_t* ent_manager, Assets_t* assets)
|
|||
p_hurtbox->def = 2;
|
||||
return p_boulder;
|
||||
}
|
||||
|
||||
Entity_t* create_arrow(EntityManager_t* ent_manager, Assets_t* assets, uint8_t dir)
|
||||
{
|
||||
Entity_t* p_arrow = add_entity(ent_manager, ARROW_ENT_TAG);
|
||||
add_component(p_arrow, CTILECOORD_COMP_T);
|
||||
CHitBoxes_t* p_hitbox = add_component(p_arrow, CHITBOXES_T);
|
||||
p_hitbox->n_boxes = 1;
|
||||
|
||||
p_hitbox->atk = 3;
|
||||
p_hitbox->one_hit = true;
|
||||
|
||||
CTransform_t* p_ctransform = add_component(p_arrow, CTRANSFORM_COMP_T);
|
||||
p_ctransform->movement_mode = KINEMATIC_MOVEMENT;
|
||||
p_ctransform->active = true;
|
||||
|
||||
//p_hitbox->boxes[0] = (Rectangle){TILE_SIZE - 5, TILE_SIZE / 2 - 5, 5, 5};
|
||||
switch(dir)
|
||||
{
|
||||
case 0:
|
||||
p_hitbox->boxes[0] = (Rectangle){10, TILE_SIZE / 2 - 5, 10, 5};
|
||||
p_ctransform->velocity.x = -250;
|
||||
break;
|
||||
case 2:
|
||||
p_hitbox->boxes[0] = (Rectangle){TILE_SIZE / 2 - 5, 10, 5, 10};
|
||||
p_ctransform->velocity.y = -250;
|
||||
break;
|
||||
case 3:
|
||||
p_hitbox->boxes[0] = (Rectangle){TILE_SIZE / 2 - 5, 10, 5, 10};
|
||||
p_ctransform->velocity.y = 250;
|
||||
break;
|
||||
default:
|
||||
p_hitbox->boxes[0] = (Rectangle){10, TILE_SIZE / 2 - 5, 10, 5};
|
||||
p_ctransform->velocity.x = 250;
|
||||
break;
|
||||
}
|
||||
|
||||
return p_arrow;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef enum SolidType
|
|||
typedef struct Tile {
|
||||
TileType_t tile_type;
|
||||
SolidType_t solid;
|
||||
uint8_t def;
|
||||
unsigned int water_level;
|
||||
struct sc_map_64v entities_set;
|
||||
Vector2 offset;
|
||||
|
|
Loading…
Reference in New Issue