ReC98/th01/main/player/shots.cpp

161 lines
3.2 KiB
C++

#include "th01/sprites/main_ptn.h"
static const pixel_t SHOT_SPRITE_MARGIN = 2;
static const int SHOT_DECAY_FRAMES = 7;
#define sloppy_unput(i) \
egc_copy_rect_1_to_0_16(left[i], top[i], SHOT_W, SHOT_H);
void CShots::add(screen_x_t new_left, screen_y_t new_top)
{
if(new_left < PLAYFIELD_LEFT || new_left > (PLAYFIELD_RIGHT - 1)) {
return;
}
for(int i = 0; i < SHOT_COUNT; i++) {
if(moving[i] == true) {
continue;
}
if(decay_frame[i] != 0) {
continue;
}
left[i] = new_left;
top[i] = new_top;
moving[i] = true;
mdrv2_se_play(1);
decay_frame[i] = 0;
return;
}
}
void CShots::unput_and_reset_all(void)
{
for(int i = 0; i < SHOT_COUNT; i++) {
if(moving[i]) {
sloppy_unput(i);
moving[i] = false;
} else if(decay_frame[i]) {
sloppy_unput(i);
decay_frame[i] = false;
}
}
}
inline int decay_quarter(int frame) {
return ((frame / 4) + 1);
}
void CShots::unput_update_render(void)
{
for(int i = 0; i < SHOT_COUNT; i++) {
if(moving[i] == true) {
sloppy_unput(i);
top[i] -= 12;
if(!orb_in_portal) {
if(hittest_orb(i, orb_cur_left, orb_cur_top) == true) {
continue;
}
}
if(top[i] >= PLAYFIELD_TOP) {
ptn_put_quarter_8(left[i], top[i], PTN_SHOT, 0);
} else {
moving[i] = false;
}
} else if(decay_frame[i]) {
ptn_unput_quarter_8(
left[i], top[i], PTN_SHOT, decay_quarter(decay_frame[i])
);
decay_frame[i]++;
if(decay_frame[i] > SHOT_DECAY_FRAMES) {
decay_frame[i] = 0;
moving[i] = false;
} else {
ptn_put_quarter_8(
left[i], top[i], PTN_SHOT, decay_quarter(decay_frame[i])
);
}
}
}
}
bool16 CShots::hittest_orb(int i, screen_x_t orb_left, screen_y_t orb_top)
{
if(moving[i] == false) {
return false;
}
if(overlap_lt_gt(
left[i], top[i], SHOT_W, SHOT_H,
orb_left, orb_top, ORB_W, ORB_H
)) {
if((left[i] - orb_left) > (SHOT_W / 2)) {
orb_velocity_x = OVX_4_LEFT;
} else if((left[i] - orb_left) == (SHOT_W / 2)) {
orb_velocity_x = OVX_0;
} else if((left[i] - orb_left) > (-SHOT_W)) {
orb_velocity_x = OVX_4_RIGHT;
}
orb_force_new(0, OF_SHOT);
moving[i] = false;
// Yup, an extra orb update... *Very* sloppy!
orb_move_x(orb_velocity_x);
orb_cur_top += orb_velocity_y_update();
return true;
}
return false;
}
#define on_hit(i) \
sloppy_unput(i); \
moving[i] = false; \
decay_frame[i] = 1; \
mdrv2_se_play(16);
bool16 CShots::hittest_pellet(screen_x_t pellet_left, screen_y_t pellet_top)
{
for(int i = 0; i < SHOT_COUNT; i++) {
if(moving[i] == false) {
continue;
}
if(decay_frame[i] == 1) {
continue;
}
if(overlap_le_ge(
left[i], top[i],
(SHOT_W - SHOT_SPRITE_MARGIN),
(SHOT_H - SHOT_SPRITE_MARGIN),
pellet_left,
pellet_top,
(PELLET_W - SHOT_SPRITE_MARGIN),
(PELLET_H - SHOT_SPRITE_MARGIN)
)) {
on_hit(i);
return true;
}
}
return false;
}
bool16 CShots::hittest_boss(
screen_x_t hitbox_left,
screen_y_t hitbox_top,
pixel_t hitbox_w,
pixel_t hitbox_h
)
{
for(int i = 0; i < SHOT_COUNT; i++) {
if(moving[i] == false) {
continue;
}
if(overlap_point_le_ge_wh(
left[i], top[i], hitbox_left, hitbox_top, hitbox_w, hitbox_h
)) {
on_hit(i);
return true;
}
}
return false;
}
#undef sloppy_unput