ReC98/th01/main/bullet/pellet.hpp

115 lines
3.6 KiB
C++
Raw Normal View History

/// Constants
/// ---------
static const int PELLET_COUNT = 100;
static const unsigned char PELLET_SLING_DELTA_ANGLE = +0x08;
static const unsigned char PELLET_SPIN_DELTA_ANGLE = +0x04;
#define PELLET_SPIN_CIRCLE_RADIUS to_sp(16.0f)
#define PELLET_CHASE_TOP_MAX to_sp(PLAYFIELD_BOTTOM - 80.0f)
/// ---------
enum pellet_motion_t {
// No velocity change during regular pellet updates.
PM_NORMAL = 0,
// Accelerates the Y velocity of the pellet by its [speed] every frame.
PM_GRAVITY = 1,
// Slings the pellet in a (counter-)clockwise motion around its spawn
// point, with a sling radius of [speed] and a rotational speed of
// [PELLET_SLING_DELTA_ANGLE]° per frame. Once the pellet completed one
// full revolution, it is fired towards the player's position on that
// frame, in a straight line at the same [speed].
PM_SLING_AIMED = 2,
// Lets the pellet bounce off the top of the playfield once, negating its
// X velocity, and zeroing its Y velocity. The pellet then switches to
// PM_GRAVITY.
// Unused in the original game. Should have bounced the bullets off the
// left and right edge of the playfield as well, but that code doesn't
// actually work in ZUN's original code.
PM_BOUNCE_FROM_TOP_THEN_GRAVITY = 3,
// Lets the pellet bounce off the top of the playfield once, zeroing its
// X velocity, and setting its Y velocity to [speed]. The pellet then
// switches to PM_NORMAL.
PM_FALL_STRAIGHT_FROM_TOP_THEN_NORMAL = 4,
// Spins the pellet on a circle around a [spin_center] point, which moves
// at [spin_velocity], with [PELLET_SPIN_CIRCLE_RADIUS] and a rotational
// speed of [PELLET_SPIN_DELTA_ANGLE]° per frame. Since both the center of
// rotation and the angle are changed every frame, this will result in a
// swerving motion for individual pellets. Use this type for a ring of
// pellets to create moving multi-bullet circles, as seen in the Kikuri
// fight.
PM_SPIN = 5,
// For every frame this pellet is above [PELLET_CHASE_TOP_MAX], its
// velocity is adjusted by -1, 0, or +1 in both coordinates, depending on
// the location of the player relative to this pellet.
PM_CHASE = 6,
_pellet_motion_t_FORCE_INT = 0x7FFF
};
enum pellet_sling_direction_t {
PSD_NONE = 0,
PSD_CLOCKWISE = 1,
PSD_COUNTERCLOCKWISE = 2,
_pellet_sling_direction_t_FORCE_INT = 0x7FFF
};
enum pellet_pattern_t {
_pellet_pattern_t_FORCE_INT = 0x7FFF
};
struct pellet_t {
unsigned char moving;
unsigned char motion_type;
// Automatically calculated every frame for PM_SPIN
Subpixel cur_left;
Subpixel cur_top;
SPPoint spin_center; // only used for PM_SPIN
Subpixel prev_left;
Subpixel prev_top;
pellet_pattern_t from_pattern;
SPPoint velocity; // unused for PM_SPIN
SPPoint spin_velocity; // only used for PM_SPIN
bool16 not_rendered;
int age;
Subpixel speed; // for recalculating velocities with certain motion types
int decay_frame;
int cloud_frame;
int cloud_left; // Not subpixels!
int cloud_top; // Not subpixels!
int angle; // for recalculating velocities with certain motion types
// Direction for PM_SLING_AIMED. Not reset when a pellet is destroyed -
// and therefore effectively only calculated once for every instance of
// this structure.
pellet_sling_direction_t sling_direction;
};
class CPellets {
pellet_t near pellets[PELLET_COUNT];
int alive_count; // only used for one single optimization
int unknown_zero[10];
public:
int unknown_seven;
bool16 interlace_field;
bool spawn_with_cloud;
protected:
// Updates the velocity of the currently iterated pellet, depending on its
// [motion_type].
void motion_type_apply_for_cur(void);
};
/// Globals
/// -------
extern CPellets Pellets;
/// -------