mirror of
https://github.com/luksamuk/engine-psx.git
synced 2025-04-28 13:28:02 +03:00
Add breathing bubbles, remaining air count and breathable bubbles
This commit is contained in:
parent
7d98ff3d48
commit
90164a1b97
7 changed files with 80 additions and 6 deletions
BIN
assets/sfx/BUBBLE.ogg
Normal file
BIN
assets/sfx/BUBBLE.ogg
Normal file
Binary file not shown.
BIN
assets/sfx/COUNT.ogg
Normal file
BIN
assets/sfx/COUNT.ogg
Normal file
Binary file not shown.
|
@ -86,7 +86,8 @@ typedef struct {
|
|||
// TODO: Change this to player value modes.
|
||||
// For now we're only storing info on whether
|
||||
// player is underwater
|
||||
uint8_t underwater;
|
||||
uint8_t underwater;
|
||||
uint16_t remaining_air_frames;
|
||||
|
||||
// Collision modes
|
||||
CollMode gsmode;
|
||||
|
|
6
iso.xml
6
iso.xml
|
@ -310,6 +310,12 @@
|
|||
<file name="SPLASH.VAG"
|
||||
type="data"
|
||||
source="${PROJECT_SOURCE_DIR}/assets/sfx/SPLASH.VAG" />
|
||||
<file name="COUNT.VAG"
|
||||
type="data"
|
||||
source="${PROJECT_SOURCE_DIR}/assets/sfx/COUNT.VAG" />
|
||||
<file name="BUBBLE.VAG"
|
||||
type="data"
|
||||
source="${PROJECT_SOURCE_DIR}/assets/sfx/BUBBLE.VAG" />
|
||||
</dir>
|
||||
|
||||
<dir name="BGM">
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "screen.h"
|
||||
#include "screens/level.h"
|
||||
|
||||
#define ANIM_WALKING 0x0854020e
|
||||
|
||||
// Extern elements
|
||||
extern Player player;
|
||||
extern Camera camera;
|
||||
|
@ -29,6 +31,7 @@ extern SoundEffect sfx_ringl;
|
|||
extern SoundEffect sfx_shield;
|
||||
extern SoundEffect sfx_yea;
|
||||
extern SoundEffect sfx_switch;
|
||||
extern SoundEffect sfx_bubble;
|
||||
|
||||
extern int debug_mode;
|
||||
|
||||
|
@ -726,7 +729,7 @@ _bubble_patch_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
|
|||
}
|
||||
|
||||
static void
|
||||
_bubble_update(ObjectState *state, ObjectTableEntry *, VECTOR *)
|
||||
_bubble_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
|
||||
{
|
||||
// NOTE: this object can only exist as a free object. Do not insist.
|
||||
|
||||
|
@ -786,7 +789,21 @@ _bubble_update(ObjectState *state, ObjectTableEntry *, VECTOR *)
|
|||
// technically have a whole area available to add it, but I felt like I
|
||||
// shouldn't create a whole new texture this time just because of a single
|
||||
// bubble frame.
|
||||
if(state->anim_state.animation == 2 && state->anim_state.frame == 5) {
|
||||
// TODO
|
||||
if((state->anim_state.animation == 2) && (state->anim_state.frame == 5)) {
|
||||
// Bubble has an active trigger area of 32x16 at its bottom so we
|
||||
// always overlap Sonic's mouth.
|
||||
if(aabb_intersects(player_vx, player_vy, player_width, player_height,
|
||||
pos->vx - 16, pos->vy - 16, 32, 16)) {
|
||||
state->props |= OBJ_FLAG_DESTROYED;
|
||||
player.remaining_air_frames = 1800;
|
||||
// TODO: Cancel any drowning music.
|
||||
// TODO: Setup proper action.
|
||||
player.action = ACTION_NONE;
|
||||
player_set_animation_direct(&player, ANIM_WALKING); // TODO!!!
|
||||
player.grnd = 0;
|
||||
player.vel.vy = 0;
|
||||
sound_play_vag(sfx_bubble, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
49
src/player.c
49
src/player.c
|
@ -47,6 +47,8 @@ SoundEffect sfx_shield = { 0 };
|
|||
SoundEffect sfx_yea = { 0 };
|
||||
SoundEffect sfx_switch = { 0 };
|
||||
SoundEffect sfx_splash = { 0 };
|
||||
SoundEffect sfx_count = { 0 };
|
||||
SoundEffect sfx_bubble = { 0 };
|
||||
|
||||
// TODO: Maybe shouldn't be extern?
|
||||
extern TileMap16 map16;
|
||||
|
@ -76,6 +78,7 @@ load_player(Player *player,
|
|||
player->underwater = 0;
|
||||
player->gsmode = CDIR_FLOOR;
|
||||
player->psmode = CDIR_FLOOR;
|
||||
player->remaining_air_frames = 1800; // 30 seconds
|
||||
|
||||
player_set_animation_direct(player, ANIM_STOPPED);
|
||||
player->anim_frame = player->anim_timer = 0;
|
||||
|
@ -108,6 +111,8 @@ load_player(Player *player,
|
|||
if(sfx_yea.addr == 0) sfx_yea = sound_load_vag("\\SFX\\YEA.VAG;1");
|
||||
if(sfx_switch.addr == 0) sfx_switch = sound_load_vag("\\SFX\\SWITCH.VAG;1");
|
||||
if(sfx_splash.addr == 0) sfx_splash = sound_load_vag("\\SFX\\SPLASH.VAG;1");
|
||||
if(sfx_count.addr == 0) sfx_count = sound_load_vag("\\SFX\\COUNT.VAG;1");
|
||||
if(sfx_bubble.addr == 0) sfx_bubble = sound_load_vag("\\SFX\\BUBBLE.VAG;1");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1001,6 +1006,50 @@ player_update(Player *player)
|
|||
explosion->state.anim_state.animation = 2; // Water splash
|
||||
sound_play_vag(sfx_splash, 0);
|
||||
}
|
||||
|
||||
if(!player->underwater)
|
||||
// Reset to 30 secs of air
|
||||
player->remaining_air_frames = 1800;
|
||||
else {
|
||||
if(player->remaining_air_frames > 0) player->remaining_air_frames--;
|
||||
|
||||
uint8_t emit_bubble = !((player->remaining_air_frames + 1) % 120)
|
||||
&& (player->remaining_air_frames > 0);
|
||||
switch(player->remaining_air_frames) {
|
||||
case (25 * 60):
|
||||
case (20 * 60):
|
||||
case (15 * 60):
|
||||
// TODO: Warning chime
|
||||
sound_play_vag(sfx_count, 0);
|
||||
break;
|
||||
case (12 * 60):
|
||||
// TODO: Start drowning music
|
||||
// TODO: Warning bubble "5"
|
||||
emit_bubble = 1;
|
||||
break;
|
||||
case (10 * 60): emit_bubble = 1; break; // TODO: Warning bubble "4"
|
||||
case (8 * 60): emit_bubble = 1; break; // TODO: Warning bubble "3"
|
||||
case (6 * 60): emit_bubble = 1; break; // TODO: Warning bubble "2"
|
||||
case (4 * 60): emit_bubble = 1; break; // TODO: Warning bubble "1"
|
||||
case (2 * 60): emit_bubble = 1; break; // TODO: Warning bubble "0"
|
||||
case 0: break; // TODO: DROWNED!
|
||||
}
|
||||
|
||||
// Bubble emission
|
||||
if(emit_bubble) {
|
||||
// TODO: Either emit 1 or 2 bubbles. In case of 2,
|
||||
// First one has 1/4 chance of being a number bubble,
|
||||
// and the second is definitely a number bubble if not emitted
|
||||
// previously.
|
||||
// For now we emit a single small bubble.
|
||||
PoolObject *bubble = object_pool_create(OBJ_BUBBLE);
|
||||
if(bubble) {
|
||||
bubble->state.anim_state.animation = 0;
|
||||
bubble->freepos.vx = player->pos.vx + (0x6000 * player->anim_dir);
|
||||
bubble->freepos.vy = player->pos.vy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Screen transform
|
||||
|
|
|
@ -576,7 +576,7 @@ screen_level_draw(void *d)
|
|||
"SPD %08x %08x\n"
|
||||
"ANG %08x G.P %s %s %3d\n"
|
||||
"POS %08x %08x\n"
|
||||
"ACT %02u\n"
|
||||
"ACT %02u AIR %02u\n"
|
||||
,
|
||||
player.vel.vz,
|
||||
player.vel.vx, player.vel.vy,
|
||||
|
@ -601,7 +601,8 @@ screen_level_draw(void *d)
|
|||
: " ",
|
||||
(int32_t)(((int32_t)player.angle * (int32_t)(360 << 12)) >> 24), // angle in deg
|
||||
player.pos.vx, player.pos.vy,
|
||||
player.action
|
||||
player.action,
|
||||
player.remaining_air_frames / 60
|
||||
);
|
||||
font_draw_sm(buffer, 8, 12);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue