mirror of
https://github.com/luksamuk/engine-psx.git
synced 2025-04-28 13:28:02 +03:00
Attempts at fixing object collision, implement checkpoint
This commit is contained in:
parent
07539bfb32
commit
1568a7cd9f
8 changed files with 82 additions and 59 deletions
|
@ -163,7 +163,7 @@ loopback = 0
|
|||
[[checkpoint.fragment.animations]]
|
||||
name = "active"
|
||||
id = 1
|
||||
duration = 2
|
||||
duration = 4
|
||||
frames = [
|
||||
[0, 48, 16, 16],
|
||||
[16, 48, 16, 16],
|
||||
|
@ -185,7 +185,7 @@ loopback = 0
|
|||
[[spring_yellow.animations]]
|
||||
name = "bounce"
|
||||
id = 1
|
||||
duration = 2
|
||||
duration = 4
|
||||
frames = [
|
||||
[80, 32, 32, 8],
|
||||
[80, 40, 32, 40],
|
||||
|
@ -206,7 +206,7 @@ loopback = 0
|
|||
[[spring_red.animations]]
|
||||
name = "bounce"
|
||||
id = 1
|
||||
duration = 2
|
||||
duration = 4
|
||||
frames = [
|
||||
[48, 32, 32, 8],
|
||||
[48, 40, 32, 40],
|
||||
|
@ -227,7 +227,7 @@ loopback = 0
|
|||
[[spring_yellow_diagonal.animations]]
|
||||
name = "bounce"
|
||||
id = 1
|
||||
duration = 2
|
||||
duration = 4
|
||||
frames = [
|
||||
[144, 80, 32, 32],
|
||||
[176, 80, 48, 48],
|
||||
|
@ -248,7 +248,7 @@ loopback = 0
|
|||
[[spring_red_diagonal.animations]]
|
||||
name = "bounce"
|
||||
id = 1
|
||||
duration = 2
|
||||
duration = 4
|
||||
frames = [
|
||||
[144, 32, 32, 32],
|
||||
[176, 32, 48, 48],
|
||||
|
|
BIN
assets/sfx/CHEK.ogg
Normal file
BIN
assets/sfx/CHEK.ogg
Normal file
Binary file not shown.
|
@ -16,6 +16,8 @@ typedef enum {
|
|||
OBJ_FLAG_DESTROYED = 0x1,
|
||||
OBJ_FLAG_INVISIBLE = 0x2,
|
||||
OBJ_FLAG_ANIM_LOCK = 0x4,
|
||||
|
||||
OBJ_FLAG_CHECKPOINT_ACTIVE = 0x8,
|
||||
} ObjectGeneralFlag;
|
||||
|
||||
typedef struct {
|
||||
|
|
3
iso.xml
3
iso.xml
|
@ -175,6 +175,9 @@
|
|||
<file name="SPRN.VAG"
|
||||
type="data"
|
||||
source="${PROJECT_SOURCE_DIR}/assets/sfx/SPRN.VAG" />
|
||||
<file name="CHEK.VAG"
|
||||
type="data"
|
||||
source="${PROJECT_SOURCE_DIR}/assets/sfx/CHEK.VAG" />
|
||||
</dir>
|
||||
|
||||
<dir name="BGM">
|
||||
|
|
|
@ -208,20 +208,6 @@ linecast(LevelData *lvl, TileMap128 *map128, TileMap16 *map16,
|
|||
return ev;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
aabb_intersects(int32_t a_vx, int32_t a_vy, int32_t aw, int32_t ah,
|
||||
int32_t b_vx, int32_t b_vy, int32_t bw, int32_t bh)
|
||||
{
|
||||
int32_t a_right = a_vx + aw;
|
||||
int32_t a_bottom = a_vy + ah;
|
||||
int32_t b_right = b_vx + bw;
|
||||
int32_t b_bottom = b_vy + bh;
|
||||
|
||||
return !((a_vx > b_right) || (a_right < b_vx) ||
|
||||
(a_bottom < b_vy) || (a_vy > b_bottom));
|
||||
}
|
||||
|
||||
void
|
||||
_draw_collision_hitbox(int32_t vx, int32_t vy, int32_t w, int32_t h)
|
||||
{
|
||||
|
@ -237,12 +223,28 @@ _draw_collision_hitbox(int32_t vx, int32_t vy, int32_t w, int32_t h)
|
|||
sort_prim(hitbox, 3); // Object layer
|
||||
}
|
||||
|
||||
int
|
||||
aabb_intersects(int32_t a_vx, int32_t a_vy, int32_t aw, int32_t ah,
|
||||
int32_t b_vx, int32_t b_vy, int32_t bw, int32_t bh)
|
||||
{
|
||||
if(debug_mode > 1) _draw_collision_hitbox(b_vx, b_vy, bw, bh);
|
||||
|
||||
int32_t a_right = a_vx + aw;
|
||||
int32_t a_bottom = a_vy + ah;
|
||||
int32_t b_right = b_vx + bw;
|
||||
int32_t b_bottom = b_vy + bh;
|
||||
|
||||
return !((a_vx > b_right) || (a_right < b_vx) ||
|
||||
(a_bottom < b_vy) || (a_vy > b_bottom));
|
||||
}
|
||||
|
||||
ObjectCollision
|
||||
hitbox_collision(int32_t p_vx, int32_t p_vy, int32_t pw, int32_t ph,
|
||||
int32_t o_vx, int32_t o_vy, int32_t ow, int32_t oh)
|
||||
{
|
||||
int32_t player_x = p_vx + (pw >> 1);
|
||||
int32_t player_y = p_vy + (ph >> 1);
|
||||
|
||||
int32_t obj_x = o_vx + (ow >> 1);
|
||||
int32_t obj_y = o_vy + (oh >> 1);
|
||||
|
||||
|
@ -252,8 +254,8 @@ hitbox_collision(int32_t p_vx, int32_t p_vy, int32_t pw, int32_t ph,
|
|||
int32_t combined_x_radius = (ow >> 1) + (pw >> 1) + 1;
|
||||
int32_t combined_y_radius = (oh >> 1) + (ph >> 1);
|
||||
|
||||
int32_t combined_x_diameter = combined_x_radius << 1;
|
||||
int32_t combined_y_diameter = combined_y_radius << 1;
|
||||
int32_t combined_x_diameter = ow + pw + 1;
|
||||
int32_t combined_y_diameter = oh + ph;
|
||||
|
||||
int32_t left_difference = player_x - obj_x + combined_x_radius;
|
||||
if((left_difference < 0) || (left_difference > combined_x_diameter))
|
||||
|
@ -266,14 +268,14 @@ hitbox_collision(int32_t p_vx, int32_t p_vy, int32_t pw, int32_t ph,
|
|||
uint8_t is_right = player_x > obj_x;
|
||||
uint8_t is_bottom = player_y > obj_y;
|
||||
|
||||
int32_t x_distance = left_difference - (is_right ? ow : 0);
|
||||
int32_t x_distance = left_difference - (is_right ? ow : 0) + 1;
|
||||
int32_t y_distance = top_difference - (is_bottom ? (4 + oh) : 0);
|
||||
|
||||
ObjectCollision col;
|
||||
y_distance -= (oh >> 1);
|
||||
x_distance -= (ow >> 1);
|
||||
if(abs(x_distance) > abs(y_distance)) {
|
||||
col = (y_distance < 0) ? OBJ_SIDE_TOP : OBJ_SIDE_BOTTOM;
|
||||
col = (y_distance > 0) ? OBJ_SIDE_TOP : OBJ_SIDE_BOTTOM;
|
||||
}
|
||||
else {
|
||||
col = (x_distance < 0) ? OBJ_SIDE_LEFT : OBJ_SIDE_RIGHT;
|
||||
|
|
|
@ -422,12 +422,8 @@ _render_obj(ObjectState *obj, ObjectTableEntry *typedata,
|
|||
setPolyF4(poly);
|
||||
increment_prim(sizeof(POLY_F4));
|
||||
setSemiTrans(poly, 1);
|
||||
if(obj->id == 0)
|
||||
setRGB0(poly, 128, 128, 0);
|
||||
else setRGB0(poly, 128, 0, 0);
|
||||
if(obj->id == 0)
|
||||
setXYWH(poly, px - 4, py - 4 - 32, 8, 8);
|
||||
else setXYWH(poly, px - 4, py - 4, 8, 8);
|
||||
setRGB0(poly, 128, 0, 0);
|
||||
setXYWH(poly, px - 4, py - 4, 8, 8);
|
||||
sort_prim(poly, 3); // 3 = front sprite and character layer
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ extern Camera camera;
|
|||
extern SoundEffect sfx_ring;
|
||||
extern SoundEffect sfx_pop;
|
||||
extern SoundEffect sfx_sprn;
|
||||
extern SoundEffect sfx_chek;
|
||||
extern int debug_mode;
|
||||
|
||||
// Update functions
|
||||
|
@ -29,6 +30,7 @@ static void _ring_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR
|
|||
static void _goal_sign_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR *pos);
|
||||
static void _monitor_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR *pos);
|
||||
static void _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_red);
|
||||
static void _checkpoint_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos);
|
||||
|
||||
// Player hitbox information. Calculated once per frame.
|
||||
static int32_t player_vx, player_vy; // Top left corner of player hitbox
|
||||
|
@ -70,7 +72,7 @@ object_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR *pos)
|
|||
player_height = (player_attacking
|
||||
? HEIGHT_RADIUS_ROLLING
|
||||
: HEIGHT_RADIUS_NORMAL) << 1;
|
||||
player_vy = (player.pos.vy >> 12) - (player_height >> 1);
|
||||
player_vy = (player.pos.vy >> 12) - (player_height >> 1) - 1;
|
||||
|
||||
if(debug_mode > 1) {
|
||||
_draw_player_hitbox();
|
||||
|
@ -83,6 +85,7 @@ object_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR *pos)
|
|||
case OBJ_MONITOR: _monitor_update(state, typedata, pos); break;
|
||||
case OBJ_SPRING_YELLOW: _spring_update(state, typedata, pos, 0); break;
|
||||
case OBJ_SPRING_RED: _spring_update(state, typedata, pos, 1); break;
|
||||
case OBJ_CHECKPOINT: _checkpoint_update(state, typedata, pos); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,8 +101,8 @@ _ring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
|
|||
// Calculate actual top left corner of ring AABB
|
||||
pos->vx -= 8; pos->vy -= (8 + 32);
|
||||
|
||||
if(aabb_intersects(pos->vx, pos->vy, 16, 16,
|
||||
player_vx, player_vy, player_width, player_height))
|
||||
if(aabb_intersects(player_vx, player_vy, player_width, player_height,
|
||||
pos->vx, pos->vy, 16, 16))
|
||||
{
|
||||
state->anim_state.animation = 1;
|
||||
state->anim_state.frame = 0;
|
||||
|
@ -160,11 +163,11 @@ _monitor_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
|
|||
int32_t hitbox_vy = pos->vy - 32; // Monitor hitbox is a 28x32 solid box
|
||||
|
||||
// Perform collision detection
|
||||
if(aabb_intersects(solidity_vx, solidity_vy, 32, 32,
|
||||
player_vx, player_vy, player_width, player_height))
|
||||
if(aabb_intersects(player_vx, player_vy, player_width, player_height,
|
||||
solidity_vx, solidity_vy, 32, 32))
|
||||
{
|
||||
if(aabb_intersects(hitbox_vx, hitbox_vy, 28, 32,
|
||||
player_vx, player_vy, player_width, player_height)
|
||||
if(aabb_intersects(player_vx, player_vy, player_width, player_height,
|
||||
hitbox_vx, hitbox_vy, 28, 32)
|
||||
&& player_attacking) {
|
||||
state->anim_state.animation = 1;
|
||||
state->anim_state.frame = 0;
|
||||
|
@ -219,7 +222,7 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
solidity_w = 16;
|
||||
solidity_h = 32;
|
||||
} else if(state->flipmask & MASK_FLIP_FLIPY) {
|
||||
solidity_vy -= 32;
|
||||
solidity_vy -= 48;
|
||||
}
|
||||
|
||||
ObjectCollision collision_side =
|
||||
|
@ -231,7 +234,7 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
case OBJ_SIDE_LEFT:
|
||||
if(state->flipmask & MASK_FLIP_ROTCT) {
|
||||
if(player.grnd) player.vel.vz = is_red ? -0x10000 : -0xa000;
|
||||
else player.vel.vy = is_red ? -0x10000 : -0xa000;
|
||||
else player.vel.vx = is_red ? -0x10000 : -0xa000;
|
||||
player.ctrllock = 16;
|
||||
player.anim_dir = -1;
|
||||
state->anim_state.animation = 1;
|
||||
|
@ -239,7 +242,7 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
} else {
|
||||
player.ev_right = (CollisionEvent) {
|
||||
.collided = 1,
|
||||
.coord = solidity_vx + 2,
|
||||
.coord = solidity_vx + 1,
|
||||
.angle = 0
|
||||
};
|
||||
}
|
||||
|
@ -247,7 +250,7 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
case OBJ_SIDE_RIGHT:
|
||||
if(state->flipmask & MASK_FLIP_ROTCW) {
|
||||
if(player.grnd) player.vel.vz = is_red ? 0x10000 : 0xa000;
|
||||
else player.vel.vy = is_red ? 0x10000 : 0xa000;
|
||||
else player.vel.vx = is_red ? 0x10000 : 0xa000;
|
||||
player.ctrllock = 16;
|
||||
player.anim_dir = 1;
|
||||
state->anim_state.animation = 1;
|
||||
|
@ -262,15 +265,13 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
break;
|
||||
case OBJ_SIDE_TOP:
|
||||
if(state->flipmask == 0) {
|
||||
if(player.vel.vy > 0) {
|
||||
player.grnd = 0;
|
||||
player.vel.vy = is_red ? -0x10000 : -0xa000;
|
||||
player.angle = 0;
|
||||
player.action = 0;
|
||||
state->anim_state.animation = 1;
|
||||
player_set_animation_direct(&player, ANIM_WALKING);
|
||||
sound_play_vag(sfx_sprn, 0);
|
||||
}
|
||||
player.grnd = 0;
|
||||
player.vel.vy = is_red ? -0x10000 : -0xa000;
|
||||
player.angle = 0;
|
||||
player.action = 0;
|
||||
state->anim_state.animation = 1;
|
||||
player_set_animation_direct(&player, ANIM_WALKING);
|
||||
sound_play_vag(sfx_sprn, 0);
|
||||
} else {
|
||||
player.ev_grnd1 = player.ev_grnd2 = (CollisionEvent) {
|
||||
.collided = 1,
|
||||
|
@ -281,15 +282,13 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
break;
|
||||
case OBJ_SIDE_BOTTOM:
|
||||
if(state->flipmask & MASK_FLIP_FLIPY) {
|
||||
if(player.vel.vy > 0) {
|
||||
player.grnd = 0;
|
||||
player.vel.vy = is_red ? 0x10000 : 0xa000;
|
||||
player.angle = 0;
|
||||
player.action = 0;
|
||||
state->anim_state.animation = 1;
|
||||
player_set_animation_direct(&player, ANIM_WALKING);
|
||||
sound_play_vag(sfx_sprn, 0);
|
||||
}
|
||||
player.grnd = 0;
|
||||
player.vel.vy = is_red ? 0x10000 : 0xa000;
|
||||
player.angle = 0;
|
||||
player.action = 0;
|
||||
state->anim_state.animation = 1;
|
||||
player_set_animation_direct(&player, ANIM_WALKING);
|
||||
sound_play_vag(sfx_sprn, 0);
|
||||
} else {
|
||||
player.ev_ceil1 = player.ev_ceil2 = (CollisionEvent) {
|
||||
.collided = 1,
|
||||
|
@ -304,3 +303,22 @@ _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_r
|
|||
state->anim_state.frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_checkpoint_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
|
||||
{
|
||||
if(!(state->props & OBJ_FLAG_CHECKPOINT_ACTIVE)) {
|
||||
int32_t hitbox_vx = pos->vx - 8;
|
||||
int32_t hitbox_vy = pos->vy - 48;
|
||||
|
||||
if(aabb_intersects(player_vx, player_vy, player_width, player_height,
|
||||
hitbox_vx, hitbox_vy, 16, 48))
|
||||
{
|
||||
state->props |= OBJ_FLAG_CHECKPOINT_ACTIVE;
|
||||
state->frag_anim_state->animation = 1;
|
||||
state->frag_anim_state->frame = 0;
|
||||
sound_play_vag(sfx_chek, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ SoundEffect sfx_dropd = { 0 };
|
|||
SoundEffect sfx_ring = { 0 };
|
||||
SoundEffect sfx_pop = { 0 };
|
||||
SoundEffect sfx_sprn = { 0 };
|
||||
SoundEffect sfx_chek = { 0 };
|
||||
|
||||
// TODO: Maybe shouldn't be extern?
|
||||
extern TileMap16 map16;
|
||||
|
@ -80,7 +81,8 @@ load_player(Player *player,
|
|||
if(sfx_dropd.addr == 0) sfx_dropd = sound_load_vag("\\SFX\\DROPD.VAG;1");
|
||||
if(sfx_ring.addr == 0) sfx_ring = sound_load_vag("\\SFX\\RING.VAG;1");
|
||||
if(sfx_pop.addr == 0) sfx_pop = sound_load_vag("\\SFX\\POP.VAG;1");
|
||||
if(sfx_sprn.addr == 0) sfx_sprn = sound_load_vag("\\SFX\\SPRN.VAG;1");
|
||||
if(sfx_sprn.addr == 0) sfx_sprn = sound_load_vag("\\SFX\\SPRN.VAG;1");
|
||||
if(sfx_chek.addr == 0) sfx_chek = sound_load_vag("\\SFX\\CHEK.VAG;1");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue