ReC98/th04/main/playfld.cpp

100 lines
2.3 KiB
C++

#include "platform.h"
#include "pc98.h"
#include "master.hpp"
#include "th04/main/frames.h"
#include "th04/main/playfld.hpp"
extern "C" {
#include "th04/main/tile/tile.hpp"
}
#if (GAME == 5)
#include "th02/main/scroll.hpp"
#endif
extern int8_t playfield_shake_redraw_time;
inline void shift(
egc_shift_func_t *func,
vram_y_t top,
vram_y_t bottom,
bool negate,
const pixel_t &dots
) {
func(
PLAYFIELD_LEFT,
top,
(PLAYFIELD_RIGHT - 1),
bottom,
(negate) ? -dots : dots
);
// Since these games use page flipping and we only ever shift the active
// VRAM page, we need to force a redraw *on* the next frame after this one
// (*for* the one two frames after this one) to undo the shift we just did.
//
// Forcing a redraw *on this* frame (*for* the next one) is technically
// only necessary during the animation, where the other VRAM page will
// still display its previous shifted state. It's just easier to always
// unconditionally redraw the next two frames, though.
playfield_shake_redraw_time = 2;
}
inline void shift_x(egc_shift_func_t *func, bool negate) {
shift(func, 0, (RES_Y - 1), negate, playfield_shake_x);
}
inline void shift_y(egc_shift_func_t *func, bool negate) {
#if (GAME == 5)
// Micro-optimization to limit the amount of moved pixels during
// bosses.
if(scroll_line == 0) {
shift(
func,
PLAYFIELD_TOP,
(PLAYFIELD_BOTTOM - 1),
negate,
playfield_shake_y
);
return;
}
#endif
shift(func, 0, (RES_Y - 1), negate, playfield_shake_y);
}
void near playfield_shake_update_and_render(void)
{
if(playfield_shake_anim_time) {
playfield_shake_x = (stage_frame_mod2 == 0) ? -2 : 2;
playfield_shake_y = (stage_frame_mod4 <= 1) ? -2 : 2;
playfield_shake_anim_time--;
}
if(playfield_shake_x < 0) {
#if (GAME == 5)
// Doubly strong left shaking?
egc_shift_left(
PLAYFIELD_LEFT,
0,
(PLAYFIELD_RIGHT - 1),
(RES_Y - 1),
-playfield_shake_x
);
#endif
shift_x(egc_shift_left, true);
} else if(playfield_shake_x > 0) {
shift_x(egc_shift_right, false);
}
if(playfield_shake_y < 0) {
shift_y(egc_shift_up, true);
} else if(playfield_shake_y > 0) {
shift_y(egc_shift_down, false);
}
if(playfield_shake_redraw_time) {
playfield_shake_redraw_time--;
tiles_invalidate_all();
playfield_shake_x = 0;
playfield_shake_y = 0;
}
}