2020-06-30 17:28:25 +00:00
|
|
|
/// Constants
|
|
|
|
/// ---------
|
|
|
|
static const int PELLET_COUNT = 100;
|
2020-07-01 17:12:08 +00:00
|
|
|
|
|
|
|
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)
|
2020-06-30 17:28:25 +00:00
|
|
|
/// ---------
|
|
|
|
|
2020-06-29 10:31:31 +00:00
|
|
|
enum pellet_motion_t {
|
2020-07-01 17:12:08 +00:00
|
|
|
// 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
|
2020-06-29 10:31:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum pellet_sling_direction_t {
|
2020-07-01 17:12:08 +00:00
|
|
|
PSD_NONE = 0,
|
|
|
|
PSD_CLOCKWISE = 1,
|
|
|
|
PSD_COUNTERCLOCKWISE = 2,
|
|
|
|
|
2020-06-29 10:31:31 +00:00
|
|
|
_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;
|
2020-07-01 17:12:08 +00:00
|
|
|
|
|
|
|
// Automatically calculated every frame for PM_SPIN
|
2020-06-29 10:31:31 +00:00
|
|
|
Subpixel cur_left;
|
|
|
|
Subpixel cur_top;
|
2020-07-01 17:12:08 +00:00
|
|
|
|
|
|
|
SPPoint spin_center; // only used for PM_SPIN
|
2020-06-29 10:31:31 +00:00
|
|
|
Subpixel prev_left;
|
|
|
|
Subpixel prev_top;
|
|
|
|
pellet_pattern_t from_pattern;
|
2020-07-01 17:12:08 +00:00
|
|
|
SPPoint velocity; // unused for PM_SPIN
|
|
|
|
SPPoint spin_velocity; // only used for PM_SPIN
|
2020-06-29 10:31:31 +00:00
|
|
|
bool16 not_rendered;
|
|
|
|
int age;
|
2020-07-01 17:12:08 +00:00
|
|
|
Subpixel speed; // for recalculating velocities with certain motion types
|
2020-06-29 10:31:31 +00:00
|
|
|
int decay_frame;
|
|
|
|
int cloud_frame;
|
|
|
|
int cloud_left; // Not subpixels!
|
|
|
|
int cloud_top; // Not subpixels!
|
2020-07-01 17:12:08 +00:00
|
|
|
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.
|
2020-06-29 10:31:31 +00:00
|
|
|
pellet_sling_direction_t sling_direction;
|
|
|
|
};
|
2020-06-30 17:28:25 +00:00
|
|
|
|
|
|
|
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;
|
2020-07-01 17:12:08 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// Updates the velocity of the currently iterated pellet, depending on its
|
|
|
|
// [motion_type].
|
|
|
|
void motion_type_apply_for_cur(void);
|
2020-06-30 17:28:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Globals
|
|
|
|
/// -------
|
|
|
|
extern CPellets Pellets;
|
|
|
|
/// -------
|