diff --git a/src/engine/math_util.c b/src/engine/math_util.c index a8642a29..68623017 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -587,6 +587,25 @@ f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec) { return current; } +/** + * Similar to approach_s32, but converts to s16 and allows for overflow between 32767 and -32768 + */ +s32 approach_angle(s32 current, s32 target, s32 inc) { + s32 dist = (s16)(target - current); + if (dist < 0) { + dist += inc; + if (dist > 0) { + dist = 0; + } + } else if (dist > 0) { + dist -= inc; + if (dist < 0) { + dist = 0; + } + } + return (target - dist); +} + /** * Helper function for atan2s. Does a look up of the arctangent of y/x assuming * the resulting angle is in range [0, 0x2000] (1/8 of a circle). diff --git a/src/engine/math_util.h b/src/engine/math_util.h index 6e37ea4e..49b08830 100644 --- a/src/engine/math_util.h +++ b/src/engine/math_util.h @@ -375,6 +375,7 @@ void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 * void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s32 pitch, s32 yaw); s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec); f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec); +s32 approach_angle(s32 current, s32 target, s32 inc); s16 atan2s(f32 y, f32 x); f32 atan2f(f32 a, f32 b); void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c); diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index c23cc7c3..610f2060 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -195,7 +195,7 @@ s32 act_climbing_pole(struct MarioState *m) { marioObj->oMarioPolePos += m->controller->stickY / 8.0f; marioObj->oMarioPoleYawVel = 0; - m->faceAngle[1] = cameraAngle - approach_s32((s16)(cameraAngle - m->faceAngle[1]), 0, 0x400, 0x400); + m->faceAngle[1] = approach_angle(m->faceAngle[1], cameraAngle, 0x400); if (set_pole_position(m, 0.0f) == POLE_NONE) { animSpeed = m->controller->stickY / 4.0f * 0x10000; @@ -337,12 +337,11 @@ s32 update_hang_moving(struct MarioState *m) { m->forwardVel = maxSpeed; } - m->faceAngle[1] = - #ifdef TIGHTER_HANGING_CONTROLS - m->intendedYaw; - #else - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); - #endif +#ifdef TIGHTER_HANGING_CONTROLS + m->faceAngle[1] = m->intendedYaw; +#else + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); +#endif m->slideYaw = m->faceAngle[1]; m->slideVelX = m->forwardVel * sins(m->faceAngle[1]); diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 122344a8..67f5b01f 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -376,7 +376,6 @@ s32 set_mario_npc_dialog(s32 actionArg) { // 23: end s32 act_reading_npc_dialog(struct MarioState *m) { s32 headTurnAmount = 0; - s16 angleToNPC; if (m->actionArg == MARIO_DIALOG_LOOK_UP) { headTurnAmount = -1024; @@ -387,9 +386,7 @@ s32 act_reading_npc_dialog(struct MarioState *m) { if (m->actionState < 8) { // turn to NPC - angleToNPC = mario_obj_angle_to_object(m, m->usedObj); - m->faceAngle[1] = - angleToNPC - approach_s32((angleToNPC - m->faceAngle[1]) << 16 >> 16, 0, 2048, 2048); + m->faceAngle[1] = approach_angle(m->faceAngle[1], mario_obj_angle_to_object(m, m->usedObj), 0x800); // turn head to npc m->actionTimer += headTurnAmount; // set animation diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index ab1678c2..45771b77 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -165,7 +165,6 @@ void update_sliding_angle(struct MarioState *m, f32 accel, f32 lossFactor) { struct Surface *floor = m->floor; s16 slopeAngle = atan2s(floor->normal.z, floor->normal.x); f32 steepness = sqrtf(floor->normal.x * floor->normal.x + floor->normal.z * floor->normal.z); - UNUSED f32 normalY = floor->normal.y; m->slideVelX += accel * steepness * sins(slopeAngle); m->slideVelZ += accel * steepness * coss(slopeAngle); @@ -207,7 +206,7 @@ void update_sliding_angle(struct MarioState *m, f32 accel, f32 lossFactor) { mario_update_windy_ground(m); //! Speed is capped a frame late (butt slide HSG) - m->forwardVel = sqrtf(m->slideVelX * m->slideVelX + m->slideVelZ * m->slideVelZ); + m->forwardVel = sqrtf(sqr(m->slideVelX) + sqr(m->slideVelZ)); if (m->forwardVel > 100.0f) { m->slideVelX = m->slideVelX * 100.0f / m->forwardVel; m->slideVelZ = m->slideVelZ * 100.0f / m->forwardVel; @@ -257,7 +256,7 @@ s32 update_sliding(struct MarioState *m, f32 stopSpeed) { break; } - oldSpeed = sqrtf(m->slideVelX * m->slideVelX + m->slideVelZ * m->slideVelZ); + oldSpeed = sqrtf(sqr(m->slideVelX) + sqr(m->slideVelZ)); //! This is attempting to use trig derivatives to rotate Mario's speed. // It is slightly off/asymmetric since it uses the new X speed, but the old @@ -265,7 +264,7 @@ s32 update_sliding(struct MarioState *m, f32 stopSpeed) { m->slideVelX += m->slideVelZ * (m->intendedMag / 32.0f) * sideward * 0.05f; m->slideVelZ -= m->slideVelX * (m->intendedMag / 32.0f) * sideward * 0.05f; - newSpeed = sqrtf(m->slideVelX * m->slideVelX + m->slideVelZ * m->slideVelZ); + newSpeed = sqrtf(sqr(m->slideVelX) + sqr(m->slideVelZ)); if (oldSpeed > 0.0f && newSpeed > 0.0f) { m->slideVelX = m->slideVelX * oldSpeed / newSpeed; @@ -286,9 +285,8 @@ void apply_slope_accel(struct MarioState *m) { f32 slopeAccel; struct Surface *floor = m->floor; - f32 steepness = sqrtf(floor->normal.x * floor->normal.x + floor->normal.z * floor->normal.z); + f32 steepness = sqrtf(sqr(floor->normal.x) + sqr(floor->normal.z)); - UNUSED f32 normalY = floor->normal.y; s16 floorDYaw = m->floorAngle - m->faceAngle[1]; if (mario_floor_is_slope(m)) { @@ -386,9 +384,7 @@ void update_shell_speed(struct MarioState *m) { m->forwardVel = 64.0f; } - m->faceAngle[1] = - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); - + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); apply_slope_accel(m); } @@ -485,12 +481,10 @@ void update_walking_speed(struct MarioState *m) { } else if (turnRange > 0xFFF) { turnRange = 0xFFF; } - m->faceAngle[1] = - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, turnRange, turnRange); + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, turnRange); } #else - m->faceAngle[1] = - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); #endif apply_slope_accel(m); } @@ -1343,8 +1337,7 @@ s32 act_burning_ground(struct MarioState *m) { m->forwardVel = approach_f32(m->forwardVel, 32.0f, 4.0f, 1.0f); if (m->input & INPUT_NONZERO_ANALOG) { - m->faceAngle[1] = - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x600, 0x600); + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x600); } apply_slope_accel(m); diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c index 7d57a2a9..fbcd170c 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -1129,8 +1129,7 @@ static void update_metal_water_walking_speed(struct MarioState *m) { m->forwardVel = 32.0f; } - m->faceAngle[1] = - m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); m->slideVelX = m->forwardVel * sins(m->faceAngle[1]); m->slideVelZ = m->forwardVel * coss(m->faceAngle[1]); diff --git a/src/game/puppycam2.c b/src/game/puppycam2.c index ad928260..e56636da 100644 --- a/src/game/puppycam2.c +++ b/src/game/puppycam2.c @@ -1187,9 +1187,7 @@ void puppycam_projection_behaviours(void) if ((ABS(gPlayer1Controller->rawStickX) > 20 && !(gMarioState->action & ACT_FLAG_BUTT_OR_STOMACH_SLIDE)) || (gMarioState->action & ACT_FLAG_BUTT_OR_STOMACH_SLIDE && (s16)ABS(((gPuppyCam.yaw + 0x8000) % 0xFFFF - 0x8000) - ((gMarioState->faceAngle[1]) % 0xFFFF - 0x8000)) < 0x3000 )) - gPuppyCam.yawTarget = gMarioState->faceAngle[1]+0x8000 - approach_s32((s16)(gMarioState->faceAngle[1]+0x8000 - gPuppyCam.yawTarget), 0, - ((gPuppyCam.options.turnAggression*10)*ABS(gMarioState->forwardVel/32) * ABS(gPlayer1Controller->rawStickX/80.0f)*turnRate), - ((gPuppyCam.options.turnAggression*10)*ABS(gMarioState->forwardVel/32) * ABS(gPlayer1Controller->rawStickX/80.0f)*turnRate)); + gPuppyCam.yawTarget = approach_angle(gPuppyCam.yawTarget, (gMarioState->faceAngle[1] + 0x8000), ((gPuppyCam.options.turnAggression * 10) * ABS(gMarioState->forwardVel / 32) * ABS(gPlayer1Controller->rawStickX / 80.0f) * turnRate)); } } else @@ -1264,8 +1262,8 @@ void puppycam_projection_behaviours(void) gPuppyCam.floorY[1] = 0; gPuppyCam.targetFloorHeight = gPuppyCam.targetObj->oPosY; gPuppyCam.lastTargetFloorHeight = gPuppyCam.targetObj->oPosY; - gPuppyCam.yawTarget = gMarioState->faceAngle[1]+0x8000 - approach_s32((s16)(gMarioState->faceAngle[1]+0x8000 - gPuppyCam.yawTarget), 0, - 1000*(gMarioState->forwardVel/32), 1000*(gMarioState->forwardVel/32)); + + gPuppyCam.yawTarget = approach_angle(gPuppyCam.yawTarget, (gMarioState->faceAngle[1] + 0x8000), (1000 * (gMarioState->forwardVel / 32))); if (gMarioState->waterLevel-100 - gMarioState->pos[1] > 5 && gPuppyCam.flags & PUPPYCAM_BEHAVIOUR_PITCH_ROTATION) gPuppyCam.swimPitch = approach_f32_asymptotic(gPuppyCam.swimPitch,gMarioState->faceAngle[0]/10,0.05f); else