Compare commits

...

6 Commits

Author SHA1 Message Date
En Yi 3a4671cecc Add hurtbox to player
Changelog:
- Update player bbox update
- Update hitbox update system to account for player
- Reduce explosion size to allow better chaining behaviour
- Reduce lifetime of destroyed crates
2023-08-17 22:19:01 +08:00
En Yi 8c889690e8 Add null checks when creating new entity
Also, fix player spawn to reuse the player
2023-08-17 21:51:11 +08:00
En Yi 93e3b24e40 Fix transition out of water collision check 2023-08-17 21:24:52 +08:00
En Yi 939fe7bc4e Allow boulder pushing when swimming 2023-08-17 21:10:11 +08:00
En Yi 216a0d9f0b Fix rotation not reset on sandbox restart 2023-08-17 21:03:47 +08:00
En Yi 62ecd3c0fa Create simple dead player respawn system
Changelog:
- Add player dead sprite
- Add function to create dead player entity
    - It is easier to create a new entity than to transform an existing
      one
- Update existing respawn system
2023-08-16 23:45:34 +08:00
6 changed files with 88 additions and 16 deletions

View File

@ -528,6 +528,7 @@ static void spawn_crate(Scene_t* scene, unsigned int tile_idx, bool metal, Conta
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
Entity_t* p_crate = create_crate(&scene->ent_manager, &scene->engine->assets, metal, item);
if (p_crate == NULL) return;
CTransform_t* p_ctransform = get_component(p_crate, CTRANSFORM_COMP_T);
p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
@ -539,6 +540,7 @@ static void spawn_boulder(Scene_t* scene, unsigned int tile_idx)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
Entity_t* p_boulder = create_boulder(&scene->ent_manager, &scene->engine->assets);
if (p_boulder == NULL) return;
CTransform_t* p_ctransform = get_component(p_boulder, CTRANSFORM_COMP_T);
p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
@ -716,6 +718,7 @@ static void restart_editor_level(Scene_t* scene)
{
tilemap.tiles[i].solid = NOT_SOLID;
tilemap.tiles[i].tile_type = EMPTY_TILE;
tilemap.tiles[i].rotation = TILE_NOROTATE;
tilemap.tiles[i].moveable = true;
tilemap.tiles[i].max_water_level = 4;
tilemap.tiles[i].water_level = 0;
@ -860,8 +863,8 @@ void init_sandbox_scene(LevelScene_t* scene)
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);
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, &player_respawn_system);
sc_array_add(&scene->scene.systems, &toggle_block_system);
// This avoid graphical glitch, not essential

View File

@ -217,6 +217,7 @@ void free_component_to_mempool(ComponentEnum_t comp_type, unsigned long idx)
void print_mempool_stats(char* buffer)
{
buffer += sprintf(buffer, "Entity free: %u\n", ent_mempool.free_list.count);
for (size_t i = 0; i < N_COMPONENTS; ++i)
{
buffer += sprintf(

View File

@ -15,6 +15,7 @@ typedef enum EntityTag {
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_dead_player(EntityManager_t* ent_manager, Assets_t* assets);
bool init_item_creation(Assets_t* assets);

View File

@ -199,16 +199,27 @@ static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor)
void player_respawn_system(Scene_t* scene)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
TileGrid_t tilemap = data->tilemap;
Entity_t* p_player;
// Cannot create player while looping though the players
// So have to create outside of the loop
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player)
{
if (!p_player->m_alive)
{
CTransform_t* p_ct = get_component(p_player, CTRANSFORM_COMP_T);
Entity_t* ent = create_dead_player(&scene->ent_manager, &scene->engine->assets);
if (ent != NULL)
{
CTransform_t* new_ct = get_component(ent, CTRANSFORM_COMP_T);
memcpy(&new_ct->position, &p_ct->position, sizeof(p_ct->position));
}
p_player->m_alive = true;
CTransform_t* p_ctransform = get_component(p_player, CTRANSFORM_COMP_T);
memset(&p_ctransform->position, 0, sizeof(p_ctransform->position));
memset(&p_ctransform->velocity, 0, sizeof(p_ctransform->velocity));
memset(&p_ctransform->accel, 0, sizeof(p_ctransform->accel));
memset(&p_ct->position, 0, sizeof(p_ct->position));
memset(&p_ct->velocity, 0, sizeof(p_ct->velocity));
memset(&p_ct->accel, 0, sizeof(p_ct->accel));
}
}
}
@ -445,6 +456,8 @@ void player_bbox_update_system(Scene_t* scene)
p_hitbox->boxes[0].height = p_bbox->size.y + 2;
//p_hitbox->boxes[1].y = p_bbox->size.y / 4;
p_hitbox->boxes[1].height = p_bbox->size.y - 1;
CHurtbox_t* p_hurtbox = get_component(p_player, CHURTBOX_T);
p_hurtbox->size = p_bbox->size;
}
}
@ -1016,7 +1029,10 @@ void player_pushing_system(Scene_t* scene)
{
CMovementState_t* p_movement = get_component(p_player, CMOVEMENTSTATE_T);
CPlayerState_t* p_pstate = get_component(p_player, CPLAYERSTATE_T);
if (!(p_movement->ground_state & 1) || p_pstate->player_dir.x == 0) continue;
if (
!(p_movement->ground_state & 1 || p_movement->water_state & 1)
|| p_pstate->player_dir.x == 0
) continue;
CTransform_t* p_ctransform = get_component(p_player, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(p_player, CBBOX_COMP_T);
@ -1277,7 +1293,16 @@ void state_transition_update_system(Scene_t* scene)
for (unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
{
unsigned int tile_idx = tile_y * data->tilemap.width + tile_x;
in_water |= data->tilemap.tiles[tile_idx].water_level > 0;
if (data->tilemap.tiles[tile_idx].water_level == 0) continue;
uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP;
Vector2 tl = {tile_x * data->tilemap.tile_size, (tile_y + 1) * data->tilemap.tile_size - water_height};
Vector2 overlap;
in_water |= find_AABB_overlap(
p_ctransform->position, p_bbox->size,
tl, (Vector2){data->tilemap.tile_size, water_height}
, &overlap
) > 0;
}
}
}
@ -1454,10 +1479,18 @@ void hitbox_update_system(Scene_t* scene)
}
if (p_ent->m_tag != PLAYER_ENT_TAG)
{
if (p_other_ent->m_tag == PLAYER_ENT_TAG)
{
p_other_ent->m_alive = false;
}
else
{
remove_component(p_other_ent, CHURTBOX_T);
CLifeTimer_t* p_clifetimer = add_component(p_other_ent, CLIFETIMER_T);
p_clifetimer->life_time = 8;
p_clifetimer->life_time = 6;
}
}
else
{

View File

@ -34,8 +34,9 @@ bool init_item_creation(Assets_t* assets)
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);
if (p_crate == NULL) return NULL;
CBBox_t* p_bbox = add_component(p_crate, CBBOX_COMP_T);
set_bbox(p_bbox, TILE_SIZE, TILE_SIZE);
p_bbox->solid = true;
p_bbox->fragile = !metal;
@ -75,8 +76,9 @@ Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool meta
Entity_t* create_boulder(EntityManager_t* ent_manager, Assets_t* assets)
{
Entity_t* p_boulder = add_entity(ent_manager, BOULDER_ENT_TAG);
CBBox_t* p_bbox = add_component(p_boulder, CBBOX_COMP_T);
if (p_boulder == NULL) return NULL;
CBBox_t* p_bbox = add_component(p_boulder, CBBOX_COMP_T);
set_bbox(p_bbox, TILE_SIZE, TILE_SIZE);
p_bbox->solid = true;
p_bbox->fragile = false;
@ -99,6 +101,8 @@ 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)
{
Entity_t* p_arrow = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_arrow == NULL) return NULL;
add_component(p_arrow, CTILECOORD_COMP_T);
CHitBoxes_t* p_hitbox = add_component(p_arrow, CHITBOXES_T);
p_hitbox->n_boxes = 1;
@ -143,6 +147,8 @@ Entity_t* create_arrow(EntityManager_t* ent_manager, Assets_t* assets, uint8_t d
Entity_t* create_bomb(EntityManager_t* ent_manager, Assets_t* assets, Vector2 launch_dir)
{
Entity_t* p_bomb = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_bomb == NULL) return NULL;
add_component(p_bomb, CTILECOORD_COMP_T);
add_component(p_bomb, CMOVEMENTSTATE_T);
CHitBoxes_t* p_hitbox = add_component(p_bomb, CHITBOXES_T);
@ -173,6 +179,8 @@ Entity_t* create_bomb(EntityManager_t* ent_manager, Assets_t* assets, Vector2 la
Entity_t* create_explosion(EntityManager_t* ent_manager, Assets_t* assets)
{
Entity_t* p_explosion = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_explosion == NULL) return NULL;
add_component(p_explosion, CTILECOORD_COMP_T);
CHitBoxes_t* p_hitbox = add_component(p_explosion, CHITBOXES_T);
p_hitbox->n_boxes = 1;
@ -182,9 +190,9 @@ Entity_t* create_explosion(EntityManager_t* ent_manager, Assets_t* assets)
CTransform_t* p_ctransform = add_component(p_explosion, CTRANSFORM_COMP_T);
p_ctransform->movement_mode = KINEMATIC_MOVEMENT;
p_ctransform->active = true;
p_ctransform->position.x -= 24;
p_ctransform->position.y -= 24;
p_hitbox->boxes[0] = (Rectangle){0, 0, TILE_SIZE + 48, TILE_SIZE + 48};
p_ctransform->position.x -= 16;
p_ctransform->position.y -= 16;
p_hitbox->boxes[0] = (Rectangle){0, 0, TILE_SIZE + 32, TILE_SIZE + 32};
CSprite_t* p_cspr = add_component(p_explosion, CSPRITE_T);
p_cspr->sprites = item_sprite_map;

View File

@ -4,7 +4,7 @@
#include <string.h>
#include "raymath.h"
#define N_PLAYER_SPRITES 8
#define N_PLAYER_SPRITES 9
enum PlayerSpriteEnum
{
SPR_PLAYER_STAND = 0,
@ -15,6 +15,7 @@ enum PlayerSpriteEnum
SPR_PLAYER_CROUCH,
SPR_PLAYER_CRMOVE,
SPR_PLAYER_SWIM,
SPR_PLAYER_DEAD,
};
static SpriteRenderInfo_t player_sprite_map[N_PLAYER_SPRITES] = {0};
@ -25,6 +26,7 @@ static unsigned int player_sprite_transition_func(Entity_t* ent)
CMovementState_t* p_move = get_component(ent, CMOVEMENTSTATE_T);
CSprite_t* p_spr = get_component(ent, CSPRITE_T);
CPlayerState_t* p_plr = get_component(ent, CPLAYERSTATE_T);
if (p_ctrans->velocity.x > 0) p_spr->flip_x = true;
else if (p_ctrans->velocity.x < 0) p_spr->flip_x = false;
@ -56,6 +58,8 @@ static unsigned int player_sprite_transition_func(Entity_t* ent)
Entity_t* create_player(EntityManager_t* ent_manager, Assets_t* assets)
{
Entity_t* p_ent = add_entity(ent_manager, PLAYER_ENT_TAG);
if (p_ent == NULL) return NULL;
CBBox_t* p_bbox = add_component(p_ent, CBBOX_COMP_T);
set_bbox(p_bbox, PLAYER_WIDTH, PLAYER_HEIGHT);
@ -86,6 +90,9 @@ Entity_t* create_player(EntityManager_t* ent_manager, Assets_t* assets)
.height = p_bbox->size.y - 1,
};
p_hitbox->atk = 2;
CHurtbox_t* p_hurtbox = add_component(p_ent, CHURTBOX_T);
p_hurtbox->size = p_bbox->size;
CSprite_t* p_cspr = add_component(p_ent, CSPRITE_T);
p_cspr->sprites = player_sprite_map;
p_cspr->transition_func = &player_sprite_transition_func;
@ -93,6 +100,25 @@ Entity_t* create_player(EntityManager_t* ent_manager, Assets_t* assets)
return p_ent;
}
Entity_t* create_dead_player(EntityManager_t* ent_manager, Assets_t* assets)
{
Entity_t* p_ent = add_entity(ent_manager, NO_ENT_TAG);
if (p_ent == NULL) return NULL;
CTransform_t* p_ct = add_component(p_ent, CTRANSFORM_COMP_T);
p_ct->active = true;
p_ct->shape_factor = (Vector2){1, 1};
p_ct->velocity.y = -450;
CSprite_t* p_cspr = add_component(p_ent, CSPRITE_T);
p_cspr->sprites = player_sprite_map;
p_cspr->current_idx = SPR_PLAYER_DEAD;
add_component(p_ent, CMOVEMENTSTATE_T);
return p_ent;
}
bool init_player_creation(const char* info_file, Assets_t* assets)
{
static bool already_init = false;