Add monitor image behaviour, change debug mode cycling on level

This commit is contained in:
Lucas S. Vieira 2024-11-12 13:51:49 -03:00
parent 4909f7d00c
commit 1fa493d4e8
7 changed files with 132 additions and 39 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before After
Before After

View file

@ -339,6 +339,63 @@ frames = [
]
loopback = -1
# ============
[monitor_image]
[[monitor_image.animations]]
id = 0
name = "none"
duration = 3
frames = [
[168, 0, 16, 16],
[184, 0, 16, 16],
[200, 0, 16, 16],
]
loopback = 0
[[monitor_image.animations]]
id = 1
name = "ring"
duration = 2
frames = [[216, 0, 16, 16]]
loopback = 0
[[monitor_image.animations]]
id = 2
name = "speedshoes"
duration = 2
frames = [[232, 0, 16, 16]]
loopback = 0
[[monitor_image.animations]]
id = 3
name = "shield"
duration = 2
frames = [[168, 16, 16, 16]]
loopback = 0
[[monitor_image.animations]]
id = 4
name = "invincibility"
duration = 2
frames = [[184, 16, 16, 16]]
loopback = 0
[[monitor_image.animations]]
id = 5
name = "1up"
duration = 2
frames = [[200, 16, 16, 16]]
loopback = 0
[[monitor_image.animations]]
id = 6
name = "super"
duration = 2
frames = [[216, 16, 16, 16]]
loopback = 0
# ============
# Dummy objects
# ============

View file

@ -50,4 +50,5 @@
<tile id="11" type="goal_sign"/>
<tile id="12" type="startpos"/>
<tile id="13" type="explosion"/>
<tile id="14" type="monitor_image"/>
</tileset>

View file

@ -25,6 +25,7 @@ typedef enum {
OBJ_SWITCH = 0x08,
OBJ_GOAL_SIGN = 0x09,
OBJ_EXPLOSION = 0x0a,
OBJ_MONITOR_IMAGE = 0x0b,
} ObjectType;
#define MASK_FLIP_FLIPX 0x1 // Flip on X axis

View file

@ -43,6 +43,7 @@ static void _spring_diagonal_update(ObjectState *state, ObjectTableEntry *, VECT
static void _checkpoint_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos);
static void _spikes_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos);
static void _explosion_update(ObjectState *state, ObjectTableEntry *, VECTOR *);
static void _monitor_image_update(ObjectState *state, ObjectTableEntry *, VECTOR *);
// Player hitbox information. Calculated once per frame.
static int32_t player_vx, player_vy; // Top left corner of player hitbox
@ -102,6 +103,7 @@ object_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR *pos)
case OBJ_CHECKPOINT: _checkpoint_update(state, typedata, pos); break;
case OBJ_SPIKES: _spikes_update(state, typedata, pos); break;
case OBJ_EXPLOSION: _explosion_update(state, typedata, pos); break;
case OBJ_MONITOR_IMAGE: _monitor_image_update(state, typedata, pos); break;
}
}
@ -226,7 +228,7 @@ _goal_sign_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
}
static void
_monitor_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
_monitor_update(ObjectState *state, ObjectTableEntry *entry, VECTOR *pos)
{
if(state->anim_state.animation == 0) {
// Calculate solidity
@ -255,13 +257,12 @@ _monitor_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos)
explosion->freepos.vy = (pos->vy << 12);
explosion->state.anim_state.animation = 0; // Small explosion
// TODO: This should be the behaviour of our monitor particles
switch(((MonitorExtra *)state->extra)->kind) {
case MONITOR_KIND_RING:
level_ring_count += 10;
break;
default: break;
}
// Create monitor image object.
// Account for fragment offset as well.
PoolObject *image = object_pool_create(OBJ_MONITOR_IMAGE);
image->freepos.vx = (pos->vx << 12) + ((int32_t)entry->fragment->offsetx << 12);
image->freepos.vy = (pos->vy << 12) + ((int32_t)entry->fragment->offsety << 12);
image->state.anim_state.animation = ((MonitorExtra *)state->extra)->kind;
if(!player.grnd && player.vel.vy > 0) {
player.vel.vy *= -1;
@ -513,3 +514,24 @@ _explosion_update(ObjectState *state, ObjectTableEntry *, VECTOR *)
if(state->anim_state.animation == OBJ_ANIMATION_NO_ANIMATION)
state->props |= OBJ_FLAG_DESTROYED;
}
static void
_monitor_image_update(ObjectState *state, ObjectTableEntry *, VECTOR *)
{
state->timer++;
// Monitor images ascend for 15 frames, then stay still for 15 more
if(state->timer <= 15) state->freepos->vy -= (ONE << 1);
if(state->timer > 30) {
state->props |= OBJ_FLAG_DESTROYED;
switch(state->anim_state.animation) {
case MONITOR_KIND_RING:
sound_play_vag(sfx_ring, 0);
level_ring_count += 10;
break;
default: break;
}
}
}

View file

@ -135,9 +135,14 @@ screen_level_update(void *d)
{
screen_level_data *data = (screen_level_data *)d;
if((pad_pressing(PAD_L1) && pad_pressed(PAD_R1)) ||
(pad_pressed(PAD_L1) && pad_pressing(PAD_R1))) {
debug_mode = (debug_mode + 1) % 3;
// Debug mode cycling
{
if(pad_pressing(PAD_L1) && pad_pressed(PAD_R1))
debug_mode++;
else if(pad_pressed(PAD_L1) && pad_pressing(PAD_R1))
debug_mode--;
if(debug_mode > 2) debug_mode = 0;
else if(debug_mode < 0) debug_mode = 2;
}
level_set_clearcolor();
@ -311,7 +316,7 @@ screen_level_draw(void *d)
}
// Heads-up display
if(debug_mode <= 1) {
if(!debug_mode) {
font_set_color(
LERPC(level_fade, 0xc8),
LERPC(level_fade, 0xc8),
@ -362,35 +367,40 @@ screen_level_draw(void *d)
GetVideoMode() == MODE_PAL ? "PAL" : "NTSC", get_frame_rate());
font_draw_sm(buffer, 248, 12);
if(debug_mode > 1) {
// Sound debug
uint32_t elapsed_sectors;
sound_xa_get_elapsed_sectors(&elapsed_sectors);
snprintf(buffer, 255, "%08u", elapsed_sectors);
font_draw_sm(buffer, 248, 20);
// Sound debug
uint32_t elapsed_sectors;
sound_xa_get_elapsed_sectors(&elapsed_sectors);
snprintf(buffer, 255, "%08u", elapsed_sectors);
font_draw_sm(buffer, 248, 20);
// Free object debug
snprintf(buffer, 255, "OBJS %3d", object_pool_get_count());
font_draw_sm(buffer, 248, 28);
// Free object debug
snprintf(buffer, 255, "OBJS %3d", object_pool_get_count());
font_draw_sm(buffer, 248, 28);
// Player debug
snprintf(buffer, 255,
"GSP %08x\n"
"SPD %08x %08x\n"
"ANG %04x\n"
"POS %08x %08x\n"
"ACT %02u\n"
"REV %08x\n"
,
player.vel.vz,
player.vel.vx, player.vel.vy,
player.angle,
player.pos.vx, player.pos.vy,
player.action,
player.spinrev
);
font_draw_sm(buffer, 8, 12);
}
// Rings and time, for convenience
snprintf(buffer, 255, "RING %03d", level_ring_count);
font_draw_sm(buffer, 248, 36);
snprintf(buffer, 255, "TIME %03d", (get_elapsed_frames() / 60));
font_draw_sm(buffer, 248, 44);
// Player debug
snprintf(buffer, 255,
"GSP %08x\n"
"SPD %08x %08x\n"
"ANG %04x\n"
"POS %08x %08x\n"
"ACT %02u\n"
"REV %08x\n"
,
player.vel.vz,
player.vel.vx, player.vel.vy,
player.angle,
player.pos.vx, player.pos.vy,
player.action,
player.spinrev
);
font_draw_sm(buffer, 8, 12);
}
}

View file

@ -41,6 +41,7 @@ class ObjectId(Enum):
# This happens when the object in question is a particle
# or effect.
EXPLOSION = 0x0a
MONITOR_IMAGE = 0x0b
@staticmethod
def get(name):
@ -56,6 +57,7 @@ class ObjectId(Enum):
"goal_sign": ObjectId.GOAL_SIGN,
"switch": ObjectId.SWITCH,
"explosion": ObjectId.EXPLOSION,
"monitor_image": ObjectId.MONITOR_IMAGE,
}
result = switch.get(name.lower())
assert result is not None, f"Unknown common object {name}"