sm64pc/src/game/behaviors/bird.inc.c

119 lines
4.6 KiB
C

/**
* Behavior for bhvBird. These are the birds in the castle grounds
* that fly away and scatter when Mario comes near them. There are
* 2 types of birds; spawner birds and spawned birds. Spawner birds
* are loaded by the level, and are inactive until Mario comes within
* 2000 units of them, when they spawn 6 spawned birds and start flying.
* Spawned birds are only spawned by a spawner bird, and start flying
* immediately after spawning.
*/
/**
* If the object is a spawned bird, start flying; if it's a spawner bird,
* spawn spawned birds if Mario comes within 2000 units of it.
*/
static void bird_act_inactive(void) {
// Start flying if the object is a spawned bird or if it's a spawner bird
// and Mario is within 2000 units.
if (o->oBehParams2ndByte == BIRD_BP_SPAWNED || o->oDistanceToMario < 2000.0f) {
// If the object is a spawner bird, play the sound of birds flying away,
// and spawn 6 spawned birds (which will start flying on the next frame).
if (o->oBehParams2ndByte != BIRD_BP_SPAWNED) {
s32 i;
cur_obj_play_sound_2(SOUND_GENERAL_BIRDS_FLY_AWAY);
for (i = 0; i < 6; i++) {
spawn_object(o, MODEL_BIRDS, bhvBird);
}
// The spawner bird's home acts as its target location.
o->oHomeX = -20.0f;
o->oHomeZ = -3990.0f;
}
// Start flying
o->oAction = BIRD_ACT_FLY;
// Start with a random yaw, and a random pitch from 1000 to 5000.
// Positive pitch is downwards.
o->oMoveAnglePitch = 5000 - (s32)(4000.0f * random_float());
o->oMoveAngleYaw = random_u16();
o->oBirdSpeed = 40.0f;
cur_obj_unhide();
}
}
/**
* Make the bird fly.
* The bird flies laterally towards a target; (-20, -3990) if it's a spawner bird,
* and the parent spawner bird if it's a spawned bird.
*/
static void bird_act_fly(void) {
UNUSED s32 unused;
f32 distance;
// Compute forward velocity and vertical velocity from oBirdSpeed and pitch
obj_compute_vel_from_move_pitch(o->oBirdSpeed);
// If the bird's parent is higher than 8000 units, despawn the bird.
// A spawned bird's parent is its spawner bird. A spawner bird's parent
// is itself. In other words, when a group of birds has its spawner bird
// fly past Y=8000, they will all despawn simultaneously. Otherwise, fly.
if (o->parentObj->oPosY > 8000.0f) {
obj_mark_for_deletion(o);
} else {
// If the bird is a spawner bird, fly towards its home; otherwise,
// fly towards the bird's spawner bird.
if (o->oBehParams2ndByte != BIRD_BP_SPAWNED) {
distance = cur_obj_lateral_dist_to_home();
// The spawner bird will start with its downwards (positive) pitch
// and will continuously decrease its pitch (i.e. make itself face more upwards)
// until it reaches its home, at which point it will face directly up.
// This is done by making its target pitch the arctangent of its distance
// to its home and its position - 10,000 (which is always negative).
o->oBirdTargetPitch = atan2s(distance, o->oPosY - 10000.0f);
o->oBirdTargetYaw = cur_obj_angle_to_home();
} else {
distance = lateral_dist_between_objects(o, o->parentObj);
// The bird's target pitch will face directly to its spawner bird.
o->oBirdTargetPitch = atan2s(distance, o->oPosY - o->parentObj->oPosY);
o->oBirdTargetYaw = obj_angle_to_object(o, o->parentObj);
// The bird goes faster the farther it is from its spawner bird so it can catch up.
o->oBirdSpeed = 0.04f * dist_between_objects(o, o->parentObj) + 20.0f;
}
// Approach to match the bird's target yaw and pitch.
obj_move_pitch_approach(o->oBirdTargetPitch, 140);
cur_obj_rotate_yaw_toward(o->oBirdTargetYaw, 800);
obj_roll_to_match_yaw_turn(o->oBirdTargetYaw, 0x3000, 600);
}
// The bird has no gravity, so this function only
// moves the bird using its forward velocity.
// Even if it did have gravity, it would only act as
// a constant added to its Y position every frame since
// its Y velocity is reset every frame by
// obj_compute_vel_from_move_pitch.
cur_obj_move_using_fvel_and_gravity();
}
/**
* Update function for bhvBird.
*/
void bhv_bird_update(void) {
switch (o->oAction) {
case BIRD_ACT_INACTIVE:
bird_act_inactive();
break;
case BIRD_ACT_FLY:
bird_act_fly();
break;
}
}