Rework water, ground, and air state transition

Changelog:
- Move ground and water states into CTransform
- Update state in movement update system
- Use 2 bits to check state transition for water and ground
scene_man
En Yi 2023-01-03 21:16:52 +08:00
parent 1ba786a91e
commit b2a5e29ce4
2 changed files with 51 additions and 38 deletions

View File

@ -1,6 +1,7 @@
#ifndef __COMPONENTS_H #ifndef __COMPONENTS_H
#define __COMPONENTS_H #define __COMPONENTS_H
#include "raylib.h" #include "raylib.h"
#include <stdint.h>
// TODO: Look at sc to use macros to auto generate functions // TODO: Look at sc to use macros to auto generate functions
#define N_COMPONENTS 5 #define N_COMPONENTS 5
@ -27,7 +28,8 @@ typedef struct _CTransform_t
Vector2 position; Vector2 position;
Vector2 velocity; Vector2 velocity;
Vector2 accel; Vector2 accel;
bool on_ground; uint8_t ground_state:2;
uint8_t water_state:2;
}CTransform_t; }CTransform_t;
// This is to store the occupying tiles // This is to store the occupying tiles
@ -58,7 +60,6 @@ typedef enum PlayerState
typedef struct _CPlayerState_t typedef struct _CPlayerState_t
{ {
unsigned int is_crouch: 1; unsigned int is_crouch: 1;
unsigned int in_water:1;
}CPlayerState_t; }CPlayerState_t;

View File

@ -237,7 +237,7 @@ static void level_scene_render_func(Scene_t* scene)
DrawText(buffer, (tilemap.width + 3) * TILE_SIZE + 1, 60, 12, BLACK); DrawText(buffer, (tilemap.width + 3) * TILE_SIZE + 1, 60, 12, BLACK);
sprintf(buffer, "Crouch: %s", p_pstate->is_crouch? "YES":"NO"); sprintf(buffer, "Crouch: %s", p_pstate->is_crouch? "YES":"NO");
DrawText(buffer, tilemap.width * TILE_SIZE + 1, 90, 12, BLACK); DrawText(buffer, tilemap.width * TILE_SIZE + 1, 90, 12, BLACK);
sprintf(buffer, "Water: %s", p_pstate->in_water? "YES":"NO"); sprintf(buffer, "Water: %s", p_ct->water_state & 1? "YES":"NO");
DrawText(buffer, tilemap.width * TILE_SIZE + 1, 120, 12, BLACK); DrawText(buffer, tilemap.width * TILE_SIZE + 1, 120, 12, BLACK);
} }
} }
@ -260,7 +260,9 @@ static void player_movement_input_system(Scene_t* scene)
p_pstate->is_crouch = data->crouch_pressed; p_pstate->is_crouch = data->crouch_pressed;
p_ctransform->accel.x = 0; p_ctransform->accel.x = 0;
p_ctransform->accel.y = 0; p_ctransform->accel.y = 0;
if (!p_pstate->in_water)
bool in_water = (p_ctransform->water_state & 1);
if (!in_water)
{ {
data->player_dir.y = 0; data->player_dir.y = 0;
p_ctransform->accel = Vector2Scale(Vector2Normalize(data->player_dir), MOVE_ACCEL/1.2); p_ctransform->accel = Vector2Scale(Vector2Normalize(data->player_dir), MOVE_ACCEL/1.2);
@ -281,11 +283,11 @@ static void player_movement_input_system(Scene_t* scene)
} }
if (!p_ctransform->on_ground) if (!(p_ctransform->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_pstate->in_water) if (in_water)
{ {
unsigned int tile_idx = get_tile_idx( unsigned int tile_idx = get_tile_idx(
p_ctransform->position.x + p_bbox->size.x / 2, p_ctransform->position.x + p_bbox->size.x / 2,
@ -311,7 +313,7 @@ static void player_movement_input_system(Scene_t* scene)
bool jump_valid = true; bool jump_valid = true;
// Check Jump from crouch // Check Jump from crouch
if (p_pstate->is_crouch) if(data->crouch_pressed)
{ {
Vector2 test_pos = p_ctransform->position; Vector2 test_pos = p_ctransform->position;
Vector2 test_bbox = {PLAYER_WIDTH, PLAYER_HEIGHT}; Vector2 test_bbox = {PLAYER_WIDTH, PLAYER_HEIGHT};
@ -324,7 +326,7 @@ static void player_movement_input_system(Scene_t* scene)
// Jump okay // Jump okay
if (jump_valid) if (jump_valid)
{ {
if (!p_pstate->in_water) if (!in_water)
{ {
p_ctransform->velocity.y -= p_cjump->jump_speed; p_ctransform->velocity.y -= p_cjump->jump_speed;
} }
@ -342,7 +344,7 @@ static void player_movement_input_system(Scene_t* scene)
} }
// Friction // Friction
if (p_pstate->in_water) if (in_water)
{ {
// Apply water friction // Apply water friction
// Consistent in all direction // Consistent in all direction
@ -376,8 +378,8 @@ static void player_bbox_update_system(Scene_t *scene)
{ {
CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_player, CTRANSFORM_COMP_T); CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_player, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(&scene->ent_manager, p_player, CBBOX_COMP_T); CBBox_t* p_bbox = get_component(&scene->ent_manager, p_player, CBBOX_COMP_T);
CPlayerState_t* p_pstate = get_component(&scene->ent_manager, p_player, CPLAYERSTATE_T); //CPlayerState_t* p_pstate = get_component(&scene->ent_manager, p_player, CPLAYERSTATE_T);
if (p_ctransform->on_ground) if (p_ctransform->ground_state & 1)
{ {
AnchorPoint_t anchor = AP_BOT_CENTER; AnchorPoint_t anchor = AP_BOT_CENTER;
int dx[3] = {1, 0, 2}; int dx[3] = {1, 0, 2};
@ -400,7 +402,7 @@ static void player_bbox_update_system(Scene_t *scene)
} }
} }
Vector2 new_bbox; Vector2 new_bbox;
if (p_pstate->is_crouch) if(data->crouch_pressed)
{ {
new_bbox.x = PLAYER_C_WIDTH; new_bbox.x = PLAYER_C_WIDTH;
new_bbox.y = PLAYER_C_HEIGHT; new_bbox.y = PLAYER_C_HEIGHT;
@ -416,7 +418,7 @@ static void player_bbox_update_system(Scene_t *scene)
} }
else else
{ {
if (p_pstate->in_water) if (p_ctransform->water_state & 1)
{ {
Vector2 new_bbox = {PLAYER_C_WIDTH, PLAYER_C_HEIGHT}; Vector2 new_bbox = {PLAYER_C_WIDTH, PLAYER_C_HEIGHT};
Vector2 offset = shift_bbox(p_bbox->size, new_bbox, AP_MID_CENTER); Vector2 offset = shift_bbox(p_bbox->size, new_bbox, AP_MID_CENTER);
@ -436,11 +438,19 @@ static void player_bbox_update_system(Scene_t *scene)
static void movement_update_system(Scene_t* scene) static void movement_update_system(Scene_t* scene)
{ {
LevelSceneData_t *data = (LevelSceneData_t *)scene->scene_data;
// Update movement // Update movement
float delta_time = 0.017; // TODO: Will need to think about delta time handling float delta_time = 0.017; // TODO: Will need to think about delta time handling
CTransform_t * p_ctransform; //CTransform_t * p_ctransform;
sc_map_foreach_value(&scene->ent_manager.component_map[CTRANSFORM_COMP_T], p_ctransform) Entity_t* p_ent;
//sc_map_foreach_value(&scene->ent_manager.component_map[CTRANSFORM_COMP_T], p_ctransform)
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
{ {
CTransform_t * p_ctransform = get_component(&scene->ent_manager, p_ent, CTRANSFORM_COMP_T);
CBBox_t * p_bbox = get_component(&scene->ent_manager, p_ent, CBBOX_COMP_T);
if (p_ctransform == NULL) continue;
p_ctransform->velocity = p_ctransform->velocity =
Vector2Add( Vector2Add(
p_ctransform->velocity, p_ctransform->velocity,
@ -461,25 +471,11 @@ static void movement_update_system(Scene_t* scene)
p_ctransform->position, p_ctransform->position,
Vector2Scale(p_ctransform->velocity, delta_time) Vector2Scale(p_ctransform->velocity, delta_time)
); );
}
} if (p_bbox == NULL) continue;
static void player_ground_air_transition_system(Scene_t* scene)
{
LevelSceneData_t *data = (LevelSceneData_t *)scene->scene_data;
Entity_t *p_player;
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player)
{
CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_player, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(&scene->ent_manager, p_player, CBBOX_COMP_T);
CJump_t* p_cjump = get_component(&scene->ent_manager, p_player, CJUMP_COMP_T);
CPlayerState_t* p_pstate = get_component(&scene->ent_manager, p_player, CPLAYERSTATE_T);
// State checks
bool on_ground = check_on_ground(p_ctransform->position, p_bbox->size, &data->tilemap); bool on_ground = check_on_ground(p_ctransform->position, p_bbox->size, &data->tilemap);
bool in_water = false; bool in_water = false;
if (!p_pstate->in_water) if (!(p_ctransform->water_state & 1))
{ {
unsigned int tile_idx = get_tile_idx( unsigned int tile_idx = get_tile_idx(
p_ctransform->position.x + p_bbox->size.x / 2, p_ctransform->position.x + p_bbox->size.x / 2,
@ -504,11 +500,30 @@ static void player_ground_air_transition_system(Scene_t* scene)
} }
} }
} }
p_ctransform->ground_state <<= 1;
p_ctransform->ground_state |= on_ground? 1:0;
p_ctransform->ground_state &= 3;
p_ctransform->water_state <<= 1;
p_ctransform->water_state |= in_water? 1:0;
p_ctransform->water_state &= 3;
}
}
static void player_ground_air_transition_system(Scene_t* scene)
{
Entity_t *p_player;
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player)
{
CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_player, CTRANSFORM_COMP_T);
CJump_t* p_cjump = get_component(&scene->ent_manager, p_player, CJUMP_COMP_T);
// Handle Ground<->Air Transition // Handle Ground<->Air Transition
//if (!on_ground && p_ctransform->on_ground) bool in_water = (p_ctransform->water_state & 1);
if ((on_ground && !p_ctransform->on_ground) || in_water) // Landing or in water
if (p_ctransform->ground_state == 0b01 || in_water)
{ {
// Recover jumps
p_cjump->jumps = p_cjump->max_jumps; p_cjump->jumps = p_cjump->max_jumps;
p_cjump->jumped = false; p_cjump->jumped = false;
p_cjump->short_hop = false; p_cjump->short_hop = false;
@ -517,13 +532,10 @@ static void player_ground_air_transition_system(Scene_t* scene)
} }
// TODO: Handle in water <-> out of water transition // TODO: Handle in water <-> out of water transition
if (p_pstate->in_water && !in_water) if (p_ctransform->water_state == 0b10)
{ {
p_cjump->jumps -= (p_cjump->jumps > 0)? 1:0; p_cjump->jumps -= (p_cjump->jumps > 0)? 1:0;
} }
p_ctransform->on_ground = on_ground;
p_pstate->in_water = in_water;
} }
} }