Compare commits

...

5 Commits

Author SHA1 Message Date
En Yi 16714159bb Tweak air point check depending on player stance 2024-08-21 16:28:41 +08:00
En Yi 9f496b4bee Tweak player's swimming hitbox and hurtbox 2024-08-21 16:26:16 +08:00
En Yi 34041a68bb Fix particle emitter not unloading on player death 2024-08-21 16:25:30 +08:00
En Yi 89176142b6 Readjust arrows and bombs spawning
Changelog:
- Make use of anchor point function
- Readjust offsets and anchor points of sprites
- Readjust hitboxes offset and sizes
2024-08-21 12:52:19 +08:00
En Yi d45937da6a Recenter player on ladders 2024-08-21 10:35:23 +08:00
3 changed files with 135 additions and 50 deletions

View File

@ -151,12 +151,23 @@ collision_end:
void destroy_entity(Scene_t* scene, TileGrid_t* tilemap, Entity_t* p_ent)
{
/* Use the helper function to remove any entity
* This is because some components may have deinit steps
* This function will also take care of the tilemap collision handling
* */
Vector2 half_size = {0,0};
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
if (p_bbox != NULL)
{
half_size = p_bbox->half_size;
}
CEmitter_t* p_emitter = get_component(p_ent, CEMITTER_T);
if (p_emitter != NULL)
{
unload_emitter_handle(&scene->part_sys, p_emitter->handle);
}
if (p_ent->m_tag == BOULDER_ENT_TAG)
{
ParticleEmitter_t emitter = {
@ -345,7 +356,9 @@ void player_movement_input_system(Scene_t* scene)
p_ctransform->velocity.x = p_pstate->player_dir.x * 40 * (p_pstate->locked ? 0 : 1);
if (p_pstate->player_dir.y != 0)
{
p_player->position.x = tile_x * TILE_SIZE + 1;
p_player->position.x = tile_x * tilemap.tile_size;
p_player->position.x += (tilemap.tile_size >> 1);
p_player->position.x -= p_bbox->half_size.x;
}
}
}
@ -512,7 +525,35 @@ void player_bbox_update_system(Scene_t* scene)
p_hitbox->boxes[0].height = p_bbox->size.y + 4;
p_hitbox->boxes[1].height = p_bbox->size.y;
CHurtbox_t* p_hurtbox = get_component(p_player, CHURTBOX_T);
p_hurtbox->size = p_bbox->size;
if ((p_mstate->water_state & 1) && !(p_mstate->ground_state & 1))
{
p_hurtbox->size = p_bbox->size;
p_hurtbox->size.x *= 1.7;
p_hitbox->boxes[0].width = p_bbox->size.x * 2.0f;
p_hitbox->boxes[1].width = p_bbox->size.x * 2.0f + 4;
if (p_mstate->x_dir > 0)
{
p_hitbox->boxes[0].x = -p_bbox->size.x;
p_hitbox->boxes[1].x = -p_bbox->size.x - 2;
p_hurtbox->offset.x = -p_bbox->size.x * 0.7;
}
else
{
p_hitbox->boxes[0].x = 0;
p_hitbox->boxes[1].x = -2;
p_hurtbox->offset.x = 0;
}
}
else
{
p_hitbox->boxes[0].x = 0;
p_hitbox->boxes[0].width = p_bbox->size.x;
p_hitbox->boxes[1].x = -2;
p_hitbox->boxes[1].width = p_bbox->size.x + 4;
p_hurtbox->offset = (Vector2){0,0};
p_hurtbox->size = p_bbox->size;
}
}
}
@ -1720,6 +1761,7 @@ void boulder_destroy_wooden_tile_system(Scene_t* scene)
void container_destroy_system(Scene_t* scene)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
unsigned int ent_idx;
CContainer_t* p_container;
sc_map_foreach(&scene->ent_manager.component_map[CCONTAINER_T], ent_idx, p_container)
@ -1735,23 +1777,28 @@ void container_destroy_system(Scene_t* scene)
}
Entity_t* new_ent;
AnchorPoint_t spawn_anchor = AP_MID_CENTER;
switch (p_container->item)
{
case CONTAINER_LEFT_ARROW:
new_ent = create_arrow(&scene->ent_manager, 0);
play_sfx(scene->engine, ARROW_RELEASE_SFX);
spawn_anchor = AP_MID_LEFT;
break;
case CONTAINER_RIGHT_ARROW:
new_ent = create_arrow(&scene->ent_manager, 1);
play_sfx(scene->engine, ARROW_RELEASE_SFX);
spawn_anchor = AP_MID_RIGHT;
break;
case CONTAINER_UP_ARROW:
new_ent = create_arrow(&scene->ent_manager, 2);
play_sfx(scene->engine, ARROW_RELEASE_SFX);
spawn_anchor = AP_TOP_CENTER;
break;
case CONTAINER_DOWN_ARROW:
new_ent = create_arrow(&scene->ent_manager, 3);
play_sfx(scene->engine, ARROW_RELEASE_SFX);
spawn_anchor = AP_BOT_CENTER;
break;
case CONTAINER_BOMB:
if (dmg_src != NULL && dmg_src->m_tag == PLAYER_ENT_TAG)
@ -1784,24 +1831,25 @@ void container_destroy_system(Scene_t* scene)
new_ent = NULL;
break;
}
if (
p_container->item != CONTAINER_EXPLOSION
&& p_container->item != CONTAINER_BOMB
)
{
if (p_container->material == WOODEN_CONTAINER)
{
play_sfx(scene->engine, WOOD_DESTROY_SFX);
}
else
{
play_sfx(scene->engine, METAL_DESTROY_SFX);
}
}
if (new_ent != NULL)
{
new_ent->position = Vector2Add(new_ent->position, p_ent->position);
new_ent->position = Vector2Add(
p_ent->position,
get_anchor_offset(
(Vector2){data->tilemap.tile_size, data->tilemap.tile_size}
, spawn_anchor, false
)
);
}
// In case there's more materials
if (p_container->material == WOODEN_CONTAINER)
{
play_sfx(scene->engine, WOOD_DESTROY_SFX);
}
else
{
play_sfx(scene->engine, METAL_DESTROY_SFX);
}
}
}
@ -1835,12 +1883,32 @@ void airtimer_update_system(Scene_t* scene)
Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx);
if (!p_ent->m_alive) continue;
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
if (p_bbox == NULL) continue;
CMovementState_t* p_mstate = get_component(p_ent, CBBOX_COMP_T);
Vector2 point_to_check = {
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y / 2,
};
Vector2 point_to_check = p_ent->position;
if (p_bbox != NULL)
{
if (p_mstate != NULL && (p_mstate->ground_state & 1))
{
point_to_check = Vector2Add(
point_to_check,
(Vector2){
p_bbox->half_size.x,
p_bbox->half_size.y / 2,
}
);
}
else
{
point_to_check = Vector2Add(
point_to_check,
(Vector2){
p_bbox->half_size.x,
p_bbox->half_size.y / 3,
}
);
}
}
unsigned int tile_idx = get_tile_idx(
point_to_check.x,

View File

@ -9,12 +9,21 @@ bool init_item_creation(Assets_t* assets)
item_sprite_map[0].sprite = get_sprite(assets, "w_crate");
item_sprite_map[1].sprite = get_sprite(assets, "m_crate");
item_sprite_map[2].sprite = get_sprite(assets, "r_arrow");
item_sprite_map[2].offset = (Vector2){-8, 4};
//item_sprite_map[2].offset = (Vector2){-8, 6};
item_sprite_map[2].src_anchor = AP_MID_CENTER;
item_sprite_map[2].src_anchor = AP_MID_CENTER;
item_sprite_map[3].sprite = get_sprite(assets, "u_arrow");
item_sprite_map[3].src_anchor = AP_MID_CENTER;
item_sprite_map[3].src_anchor = AP_MID_CENTER;
item_sprite_map[4].sprite = get_sprite(assets, "l_arrow");
item_sprite_map[4].src_anchor = AP_MID_CENTER;
item_sprite_map[4].src_anchor = AP_MID_CENTER;
item_sprite_map[5].sprite = get_sprite(assets, "d_arrow");
item_sprite_map[5].src_anchor = AP_MID_CENTER;
item_sprite_map[5].src_anchor = AP_MID_CENTER;
item_sprite_map[6].sprite = get_sprite(assets, "bomb");
item_sprite_map[6].offset = (Vector2){0, -4};
item_sprite_map[6].src_anchor = AP_MID_CENTER;
item_sprite_map[6].src_anchor = AP_MID_CENTER;
item_sprite_map[7].sprite = get_sprite(assets, "w_ra_crate");
item_sprite_map[8].sprite = get_sprite(assets, "m_ra_crate");
item_sprite_map[9].sprite = get_sprite(assets, "w_ua_crate");
@ -26,7 +35,8 @@ bool init_item_creation(Assets_t* assets)
item_sprite_map[15].sprite = get_sprite(assets, "w_b_crate");
item_sprite_map[16].sprite = get_sprite(assets, "m_b_crate");
item_sprite_map[17].sprite = get_sprite(assets, "explode");
item_sprite_map[17].offset = (Vector2){-12, -12};
item_sprite_map[17].src_anchor = AP_MID_CENTER;
item_sprite_map[17].src_anchor = AP_MID_CENTER;
item_sprite_map[18].sprite = get_sprite(assets, "chest");
item_sprite_map[19].sprite = get_sprite(assets, "boulder");
item_sprite_map[20].sprite = get_sprite(assets, "exit");
@ -132,25 +142,29 @@ Entity_t* create_arrow(EntityManager_t* ent_manager, uint8_t dir)
p_cspr->sprites = item_sprite_map;
p_cspr->current_idx = 2;
//p_hitbox->boxes[0] = (Rectangle){TILE_SIZE - 5, TILE_SIZE / 2 - 5, 5, 5};
const int HITBOX_LONG_SIDE = 10;
const int HITBOX_SHORT_SIDE = 4;
const int CENTER_POSITION = (TILE_SIZE - HITBOX_SHORT_SIDE) >> 1;
const int HITBOX_CENTER = (HITBOX_SHORT_SIDE >> 1);
switch(dir)
{
case 0:
p_hitbox->boxes[0] = (Rectangle){10, TILE_SIZE / 2 - 5, 10, 5};
p_ctransform->velocity.x = -ARROW_SPEED;
p_cspr->current_idx += 2;
p_hitbox->boxes[0] = (Rectangle){-CENTER_POSITION, -HITBOX_CENTER, HITBOX_LONG_SIDE, HITBOX_SHORT_SIDE};
break;
case 2:
p_hitbox->boxes[0] = (Rectangle){TILE_SIZE / 2 - 5, 10, 5, 10};
p_hitbox->boxes[0] = (Rectangle){-HITBOX_CENTER, -CENTER_POSITION, HITBOX_SHORT_SIDE, HITBOX_LONG_SIDE};
p_ctransform->velocity.y = -ARROW_SPEED;
p_cspr->current_idx += 1;
break;
case 3:
p_hitbox->boxes[0] = (Rectangle){TILE_SIZE / 2 - 5, 10, 5, 10};
p_hitbox->boxes[0] = (Rectangle){-HITBOX_CENTER, CENTER_POSITION - HITBOX_LONG_SIDE, HITBOX_SHORT_SIDE, HITBOX_LONG_SIDE};
p_ctransform->velocity.y = ARROW_SPEED;
p_cspr->current_idx += 3;
break;
default:
p_hitbox->boxes[0] = (Rectangle){10, TILE_SIZE / 2 - 5, 10, 5};
p_hitbox->boxes[0] = (Rectangle){CENTER_POSITION - HITBOX_LONG_SIDE, -HITBOX_CENTER, HITBOX_LONG_SIDE, HITBOX_SHORT_SIDE};
p_ctransform->velocity.x = ARROW_SPEED;
break;
}
@ -163,22 +177,22 @@ Entity_t* create_bomb(EntityManager_t* ent_manager, Vector2 launch_dir)
Entity_t* p_bomb = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_bomb == NULL) return NULL;
p_bomb->position.x += (TILE_SIZE - 25) / 2;
p_bomb->position.y += (TILE_SIZE - 25) / 2;
if (launch_dir.x > 0)
{
p_bomb->position.x += TILE_SIZE/ 2;
}
else if (launch_dir.x < 0)
{
p_bomb->position.x -= TILE_SIZE / 2;
}
//p_bomb->position.x += (TILE_SIZE - 25) / 2;
//p_bomb->position.y += (TILE_SIZE - 25) / 2;
//if (launch_dir.x > 0)
//{
// p_bomb->position.x += TILE_SIZE/ 2;
//}
//else if (launch_dir.x < 0)
//{
// p_bomb->position.x -= TILE_SIZE / 2;
//}
add_component(p_bomb, CTILECOORD_COMP_T);
add_component(p_bomb, CMOVEMENTSTATE_T);
CHitBoxes_t* p_hitbox = add_component(p_bomb, CHITBOXES_T);
p_hitbox->n_boxes = 1;
p_hitbox->boxes[0] = (Rectangle){0, 0, 25, 25};
p_hitbox->boxes[0] = (Rectangle){-13, -13, 26, 26};
p_hitbox->atk = 0;
p_hitbox->one_hit = true;
@ -205,8 +219,8 @@ Entity_t* create_explosion(EntityManager_t* ent_manager)
Entity_t* p_explosion = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_explosion == NULL) return NULL;
p_explosion->position.x -= 16;
p_explosion->position.y -= 16;
//p_explosion->position.x -= 16;
//p_explosion->position.y -= 16;
add_component(p_explosion, CTILECOORD_COMP_T);
CHitBoxes_t* p_hitbox = add_component(p_explosion, CHITBOXES_T);
p_hitbox->n_boxes = 1;
@ -216,7 +230,8 @@ Entity_t* create_explosion(EntityManager_t* ent_manager)
CTransform_t* p_ctransform = add_component(p_explosion, CTRANSFORM_COMP_T);
p_ctransform->movement_mode = KINEMATIC_MOVEMENT;
p_ctransform->active = true;
p_hitbox->boxes[0] = (Rectangle){0, 0, TILE_SIZE + 32, TILE_SIZE + 32};
const int hitbox_sz = TILE_SIZE + 40;
p_hitbox->boxes[0] = (Rectangle){-(hitbox_sz >> 1), -(hitbox_sz >> 1), hitbox_sz, hitbox_sz};
CSprite_t* p_cspr = add_component(p_explosion, CSPRITE_T);
p_cspr->sprites = item_sprite_map;

View File

@ -255,30 +255,32 @@ void change_a_tile(TileGrid_t* tilemap, unsigned int tile_idx, TileType_t new_ty
tilemap->tiles[tile_idx].rotation = TILE_NOROTATE;
const int SPIKE_HITBOX_LONGSIDE = 30;
const int SPIKE_HITBOX_SHORTSIDE = 12;
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};
tilemap->tiles[tile_idx].offset = (Vector2){0,tilemap->tile_size - SPIKE_HITBOX_SHORTSIDE};
tilemap->tiles[tile_idx].size = (Vector2){SPIKE_HITBOX_LONGSIDE, SPIKE_HITBOX_SHORTSIDE};
}
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};
tilemap->tiles[tile_idx].size = (Vector2){SPIKE_HITBOX_LONGSIDE, SPIKE_HITBOX_SHORTSIDE};
tilemap->tiles[tile_idx].rotation = TILE_180ROT;
}
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};
tilemap->tiles[tile_idx].size = (Vector2){SPIKE_HITBOX_SHORTSIDE, SPIKE_HITBOX_LONGSIDE};
tilemap->tiles[tile_idx].rotation = TILE_90CWROT;
}
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};
tilemap->tiles[tile_idx].offset = (Vector2){SPIKE_HITBOX_SHORTSIDE >> 1,0};
tilemap->tiles[tile_idx].size = (Vector2){SPIKE_HITBOX_SHORTSIDE, SPIKE_HITBOX_LONGSIDE};
tilemap->tiles[tile_idx].rotation = TILE_90CCWROT;
}
else