126 lines
2.7 KiB
C
Executable File
126 lines
2.7 KiB
C
Executable File
/*
|
|
* DESCRIPTION:
|
|
* AI for the "Crumbler" enemy.
|
|
*/
|
|
|
|
#include "crumbler.h"
|
|
|
|
static s32 crumbler_health_get(Enemy* _e, List* _l, Play* _p);
|
|
static s32 crumbler_attack_timer_max_get(Enemy* _e, List* _l, Play* _p);
|
|
|
|
/* Gets the Crumbler health. */
|
|
static s32
|
|
crumbler_health_get(Enemy* _e, List* _l, Play* _p)
|
|
{
|
|
s32 health;
|
|
|
|
health = CRUMBLER_HEALTH_BASE + ((_p->game - 1) * CRUMBLER_HEALTH_GAME_MULTIPLIER);
|
|
|
|
health = CEIL(health, CRUMBLER_HEALTH_MAX);
|
|
|
|
return health;
|
|
}
|
|
|
|
/* Gets the Crumbler attack timer max. */
|
|
static s32
|
|
crumbler_attack_timer_max_get(Enemy* _e, List* _l, Play* _p)
|
|
{
|
|
s32 attackTimerMax;
|
|
|
|
attackTimerMax = CRUMBLER_ATTACK_TIMER_MAX_BASE - ((_p->game - 1) * CRUMBLER_ATTACK_TIMER_MAX_GAME_MULTIPLIER);
|
|
|
|
attackTimerMax = FLOOR(attackTimerMax, CRUMBLER_ATTACK_TIMER_MAX_MIN);
|
|
|
|
return attackTimerMax;
|
|
}
|
|
|
|
/* Initializes the Crumbler. */
|
|
void
|
|
crumbler_init(Enemy* _e, List* _l, Play* _p)
|
|
{
|
|
Atlas atlas;
|
|
|
|
atlas_init
|
|
(
|
|
&atlas,
|
|
_p->g->textures[TEXTURE_ENEMY_CRUMBLER],
|
|
CRUMBLER_ROWS,
|
|
CRUMBLER_COLUMNS,
|
|
CRUMBLER_WIDTH,
|
|
CRUMBLER_HEIGHT
|
|
);
|
|
|
|
sprite_atlas_init
|
|
(
|
|
&_e->sprite,
|
|
&atlas,
|
|
ORIGIN_MIDDLE,
|
|
CRUMBLER_WIDTH,
|
|
CRUMBLER_HEIGHT
|
|
);
|
|
|
|
_e->shadow.r = 0;
|
|
_e->sprite.frame = 1;
|
|
}
|
|
|
|
/* Sets the Crumbler. */
|
|
void
|
|
crumbler_set(Enemy* _e, List* _l, f64 _x, f64 _y, Play* _p)
|
|
{
|
|
_e->shadow.x = _x + CRUMBLER_SHADOW_OFFSET_X;
|
|
_e->shadow.y = _y + CRUMBLER_SHADOW_OFFSET_Y;
|
|
|
|
_e->sprite.x = _e->shadow.x;
|
|
_e->sprite.y = _e->shadow.y - (CRUMBLER_ATTACK_OFFSET_Y + CRUMBLER_SHADOW_OFFSET_Y);
|
|
|
|
_e->isActive = FALSE;
|
|
_e->isActing = TRUE;
|
|
_e->attackTimer = crumbler_attack_timer_max_get(_e, _l, _p);
|
|
_e->health = crumbler_health_get(_e, _l, _p);
|
|
}
|
|
|
|
/*
|
|
* Updates Crumbler.
|
|
* Falls into the arena and then remains stationary.
|
|
*/
|
|
void
|
|
crumbler_update(Enemy* _e, List* _l, Play* _p)
|
|
{
|
|
if (_e->isActing)
|
|
{
|
|
f64 progress;
|
|
|
|
_e->attackTimer--;
|
|
|
|
progress = 1 - ((f64)_e->attackTimer / crumbler_attack_timer_max_get(_e, _l, _p));
|
|
|
|
_e->shadow.r = CRUMBLER_SHADOW_RADIUS * progress;
|
|
|
|
_e->sprite.y = _e->shadow.y - CRUMBLER_SHADOW_OFFSET_Y - (CRUMBLER_ATTACK_OFFSET_Y * (1 - progress));
|
|
|
|
if (_e->attackTimer <= 0)
|
|
{
|
|
_e->isActing = FALSE;
|
|
_e->isActive = TRUE;
|
|
_e->shadow.r = CRUMBLER_SHADOW_RADIUS;
|
|
_e->sprite.frame = 0;
|
|
|
|
sound_play(_p->g->sounds[SOUND_RUMBLE], -1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
f64 progress;
|
|
|
|
_e->animationTimer--;
|
|
|
|
progress = 1 - ((f64)_e->animationTimer / CRUMBLER_ANIMATION_TIMER_MAX);
|
|
|
|
_e->sprite.squash = (SPRITE_SQUASH_DEFAULT + cos((ROTATION_MAX_RAD * progress)) * CRUMBLER_SQUASH_MULTIPLIER);
|
|
_e->sprite.stretch = (SPRITE_STRETCH_DEFAULT + cos((ROTATION_MAX_RAD * progress)) * CRUMBLER_STRETCH_MULTIPLIER);
|
|
|
|
if (_e->animationTimer <= 0)
|
|
_e->animationTimer = CRUMBLER_ANIMATION_TIMER_MAX;
|
|
}
|
|
}
|