From 48721e5811a1d3cc19b9df2c75d283c49e9b038c Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Thu, 7 Oct 2021 08:01:34 +0300 Subject: [PATCH] Fixed flipper animation frame skip bug. It is from original 3DPB, not present in FT. --- SpaceCadetPinball/TFlipper.cpp | 90 ++++++++++++++---------------- SpaceCadetPinball/TFlipper.h | 4 +- SpaceCadetPinball/TFlipperEdge.cpp | 14 ++--- SpaceCadetPinball/TFlipperEdge.h | 6 +- 4 files changed, 53 insertions(+), 61 deletions(-) diff --git a/SpaceCadetPinball/TFlipper.cpp b/SpaceCadetPinball/TFlipper.cpp index a9f194d..94999e5 100644 --- a/SpaceCadetPinball/TFlipper.cpp +++ b/SpaceCadetPinball/TFlipper.cpp @@ -22,14 +22,14 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t Smoothness = visual.Smoothness; auto collMult = *loader::query_float_attribute(groupIndex, 0, 803); - auto bmpCoef2 = *loader::query_float_attribute(groupIndex, 0, 805); - auto bmpCoef1 = *loader::query_float_attribute(groupIndex, 0, 804); + auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805); + auto extendTime = *loader::query_float_attribute(groupIndex, 0, 804); /*Full tilt hack: different flipper speed*/ if (pb::FullTiltMode) { - bmpCoef2 = 0.08f; - bmpCoef1 = 0.04f; + retractTime = 0.08f; + extendTime = 0.04f; } auto vecT2 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 802)); auto vecT1 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 801)); @@ -42,8 +42,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t origin, vecT1, vecT2, - bmpCoef1, - bmpCoef2, + extendTime, + retractTime, collMult, Elasticity, Smoothness); @@ -51,8 +51,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t FlipperEdge = flipperEdge; if (flipperEdge) { - BmpCoef1 = flipperEdge->BmpCoef1 / static_cast(ListBitmap->size() - 1); - BmpCoef2 = flipperEdge->BmpCoef2 / static_cast(ListBitmap->size() - 1); + ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast(ListBitmap->size() - 1); + RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast(ListBitmap->size() - 1); } BmpIndex = 0; InputTime = 0.0; @@ -68,35 +68,30 @@ int TFlipper::Message(int code, float value) if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022) { float timerTime; - int soundIndex = 0, code2 = code; + int command = code; if (code == 1) { control::handler(1, this); - TimerTime = BmpCoef1; - soundIndex = HardHitSoundId; + TimerTime = ExtendAnimationFrameTime; + loader::play_sound(HardHitSoundId); } else if (code == 2) { - TimerTime = BmpCoef2; - soundIndex = SoftHitSoundId; + TimerTime = RetractAnimationFrameTime; + loader::play_sound(SoftHitSoundId); } else { - code2 = 2; - TimerTime = BmpCoef2; + // Retract for all non-input messages + command = 2; + TimerTime = RetractAnimationFrameTime; } - if (soundIndex) - loader::play_sound(soundIndex); - if (Timer) - { - timer::kill(Timer); - Timer = 0; - } if (MessageField) { - auto v10 = value - FlipperEdge->InputTime; - timerTime = v10 - floor(v10 / TimerTime) * TimerTime; + // Message arrived before animation is finished + auto inputDt = value - FlipperEdge->InputTime; + timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime; if (timerTime < 0.0f) timerTime = 0.0; } @@ -104,10 +99,13 @@ int TFlipper::Message(int code, float value) { timerTime = TimerTime; } - MessageField = code2; + + MessageField = command; InputTime = value; + if (Timer) + timer::kill(Timer); Timer = timer::set(timerTime, this, TimerExpired); - FlipperEdge->SetMotion(code2, value); + FlipperEdge->SetMotion(command, value); } if (code == 1020 || code == 1024) @@ -137,49 +135,43 @@ void TFlipper::Collision(TBall* ball, vector_type* nextPosition, vector_type* di void TFlipper::TimerExpired(int timerId, void* caller) { auto flip = static_cast(caller); - int timer; // eax + int bmpCountSub1 = flip->ListBitmap->size() - 1; + + auto newBmpIndex = static_cast(floor((pb::time_now - flip->InputTime) / flip->TimerTime)); + if (newBmpIndex > bmpCountSub1) + newBmpIndex = bmpCountSub1; + if (newBmpIndex < 0) + newBmpIndex = 0; bool bmpIndexOutOfBounds = false; - auto bmpIndexAdvance = static_cast(floor((pb::time_now - flip->InputTime) / flip->TimerTime + 0.5f)); - int bmpCount = flip->ListBitmap->size(); - if (bmpIndexAdvance > bmpCount) - bmpIndexAdvance = bmpCount; - if (bmpIndexAdvance < 0) - bmpIndexAdvance = 0; - - if (!bmpIndexAdvance) - bmpIndexAdvance = 1; - if (flip->MessageField == 1) { - flip->BmpIndex += bmpIndexAdvance; - int countSub1 = flip->ListBitmap->size() - 1; - if (flip->BmpIndex >= countSub1) + flip->BmpIndex = newBmpIndex; + if (flip->BmpIndex >= bmpCountSub1) { - flip->BmpIndex = countSub1; + flip->BmpIndex = bmpCountSub1; bmpIndexOutOfBounds = true; } } if (flip->MessageField == 2) { - flip->BmpIndex -= bmpIndexAdvance; - timer = 0; + flip->BmpIndex = bmpCountSub1 - newBmpIndex; if (flip->BmpIndex <= 0) { flip->BmpIndex = 0; bmpIndexOutOfBounds = true; } } - else - { - timer = 0; - } if (bmpIndexOutOfBounds) + { flip->MessageField = 0; + flip->Timer = 0; + } else - timer = timer::set(flip->TimerTime, flip, TimerExpired); - flip->Timer = timer; + { + flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired); + } auto bmp = flip->ListBitmap->at(flip->BmpIndex); auto zMap = flip->ListZMap->at(flip->BmpIndex); diff --git a/SpaceCadetPinball/TFlipper.h b/SpaceCadetPinball/TFlipper.h index d176d8f..423a46d 100644 --- a/SpaceCadetPinball/TFlipper.h +++ b/SpaceCadetPinball/TFlipper.h @@ -19,8 +19,8 @@ public: int BmpIndex; TFlipperEdge* FlipperEdge; int Timer; - float BmpCoef1{}; - float BmpCoef2{}; + float ExtendAnimationFrameTime{}; + float RetractAnimationFrameTime{}; float TimerTime{}; float InputTime; }; diff --git a/SpaceCadetPinball/TFlipperEdge.cpp b/SpaceCadetPinball/TFlipperEdge.cpp index 886e5e0..151dc50 100644 --- a/SpaceCadetPinball/TFlipperEdge.cpp +++ b/SpaceCadetPinball/TFlipperEdge.cpp @@ -12,15 +12,15 @@ line_type TFlipperEdge::lineA, TFlipperEdge::lineB; circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1; TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, - vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, + vector_type* origin, vector_type* vecT1, vector_type* vecT2, float extendTime, float retractTime, float collMult, float elasticity, float smoothness): TEdgeSegment(collComp, activeFlag, collisionGroup) { vector_type crossProd{}, vecDir1{}, vecDir2{}; Elasticity = elasticity; Smoothness = smoothness; - BmpCoef1 = bmpCoef1; - BmpCoef2 = bmpCoef2; + ExtendTime = extendTime; + RetractTime = retractTime; CollisionMult = collMult; T1Src = *vecT1; @@ -78,9 +78,9 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z; DistanceDivSq = distance1 * distance1; - float bmpCoef = std::min(BmpCoef1, BmpCoef2); + float minMoveTime = std::min(ExtendTime, RetractTime); auto distance = maths::Distance(vecT1, vecT2); - CollisionTimeAdvance = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius); + CollisionTimeAdvance = minMoveTime / (distance / CircleT1Radius + distance / CircleT1Radius); TFlipperEdge::place_in_grid(); EdgeCollisionFlag = 0; @@ -469,12 +469,12 @@ void TFlipperEdge::SetMotion(int code, float value) case 1: Angle2 = flipper_angle(value); Angle1 = AngleMax; - AngleMult = BmpCoef1; + AngleMult = ExtendTime; break; case 2: Angle2 = flipper_angle(value); Angle1 = 0.0; - AngleMult = BmpCoef2; + AngleMult = RetractTime; break; case 1024: FlipperFlag = 0; diff --git a/SpaceCadetPinball/TFlipperEdge.h b/SpaceCadetPinball/TFlipperEdge.h index 6a8d35c..2554b67 100644 --- a/SpaceCadetPinball/TFlipperEdge.h +++ b/SpaceCadetPinball/TFlipperEdge.h @@ -8,7 +8,7 @@ class TFlipperEdge : public TEdgeSegment { public: TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, - vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, float collMult, + vector_type* origin, vector_type* vecT1, vector_type* vecT2, float extendTime, float retractTime, float collMult, float elasticity, float smoothness); void port_draw() override; float FindCollisionDistance(ray_type* ray) override; @@ -50,8 +50,8 @@ public: float InputTime; float AngleStopTime; float AngleMult; - float BmpCoef1; - float BmpCoef2; + float ExtendTime; + float RetractTime; vector_type NextBallPosition{}; static float flipper_sin_angle, flipper_cos_angle;