diff --git a/SpaceCadetPinball/DebugOverlay.cpp b/SpaceCadetPinball/DebugOverlay.cpp index 0898ee7..a0c794d 100644 --- a/SpaceCadetPinball/DebugOverlay.cpp +++ b/SpaceCadetPinball/DebugOverlay.cpp @@ -296,11 +296,10 @@ void DebugOverlay::DrawEdge(TEdgeSegment* edge) if (flip) { flip->set_control_points(pb::time_now); - flip->build_edges_in_motion(); - DrawLineType(TFlipperEdge::lineA); - DrawLineType(TFlipperEdge::lineB); - DrawCicleType(TFlipperEdge::circlebase); - DrawCicleType(TFlipperEdge::circleT1); + DrawLineType(flip->lineA); + DrawLineType(flip->lineB); + DrawCicleType(flip->circlebase); + DrawCicleType(flip->circleT1); } } diff --git a/SpaceCadetPinball/TFlipper.cpp b/SpaceCadetPinball/TFlipper.cpp index bd40e5a..064b2cc 100644 --- a/SpaceCadetPinball/TFlipper.cpp +++ b/SpaceCadetPinball/TFlipper.cpp @@ -18,19 +18,11 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t HardHitSoundId = visual.SoundIndex4; SoftHitSoundId = visual.SoundIndex3; Elasticity = visual.Elasticity; - Timer = 0; Smoothness = visual.Smoothness; auto collMult = *loader::query_float_attribute(groupIndex, 0, 803); 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) - { - 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)); auto origin = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 800)); @@ -49,75 +41,53 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t Smoothness); FlipperEdge = flipperEdge; - if (flipperEdge) - { - ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast(ListBitmap->size() - 1); - RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast(ListBitmap->size() - 1); - } BmpIndex = 0; - InputTime = 0.0; + if (table) + table->FlipperList.push_back(this); } TFlipper::~TFlipper() { delete FlipperEdge; + if (PinballTable) + { + auto& flippers = PinballTable->FlipperList; + auto position = std::find(flippers.begin(), flippers.end(), this); + if (position != flippers.end()) + flippers.erase(position); + } } int TFlipper::Message(int code, float value) { if (code == 1 || code == 2 || (code > 1008 && code <= 1011) || code == 1022) { - float timerTime; - int command = code; if (code == 1) { control::handler(1, this); - TimerTime = ExtendAnimationFrameTime; loader::play_sound(HardHitSoundId, this, "TFlipper1"); } else if (code == 2) { - TimerTime = RetractAnimationFrameTime; loader::play_sound(SoftHitSoundId, this, "TFlipper2"); } else { // Retract for all non-input messages - command = 2; - TimerTime = RetractAnimationFrameTime; + code = 2; } - if (MessageField) - { - // Message arrived before animation is finished - auto inputDt = value - FlipperEdge->InputTime; - timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime; - if (timerTime < 0.0f) - timerTime = 0.0; - } - else - { - timerTime = TimerTime; - } - - MessageField = command; - InputTime = value; - if (Timer) - timer::kill(Timer); - Timer = timer::set(timerTime, this, TimerExpired); - FlipperEdge->SetMotion(command, value); + MessageField = FlipperEdge->SetMotion(code, value); + return 0; } if (code == 1020 || code == 1024) { if (MessageField) { - if (Timer) - timer::kill(Timer); - BmpIndex = -1; - MessageField = 2; - TimerExpired(Timer, this); - FlipperEdge->SetMotion(code, value); + MessageField = 0; + FlipperEdge->SetMotion(1024, value); + UpdateSprite(0); } } return 0; @@ -132,53 +102,22 @@ void TFlipper::Collision(TBall* ball, vector2* nextPosition, vector2* direction, { } -void TFlipper::TimerExpired(int timerId, void* caller) +void TFlipper::UpdateSprite(float timeNow) { - auto flip = static_cast(caller); - int bmpCountSub1 = flip->ListBitmap->size() - 1; + int bmpCountSub1 = ListBitmap->size() - 1; - auto newBmpIndex = static_cast(floor(flip->FlipperEdge->flipper_angle(pb::time_now) / flip->FlipperEdge->AngleMax * bmpCountSub1 + 0.5)); - if (newBmpIndex > bmpCountSub1) - newBmpIndex = bmpCountSub1; - if (newBmpIndex < 0) - newBmpIndex = 0; + auto newBmpIndex = static_cast(floor(FlipperEdge->flipper_angle(timeNow) / FlipperEdge->AngleMax * bmpCountSub1 + 0.5f)); + newBmpIndex = Clamp(newBmpIndex, 0, bmpCountSub1); + if (BmpIndex == newBmpIndex) + return; - bool bmpIndexOutOfBounds = false; - if (flip->MessageField == 1) - { - flip->BmpIndex = newBmpIndex; - if (flip->BmpIndex >= bmpCountSub1) - { - flip->BmpIndex = bmpCountSub1; - bmpIndexOutOfBounds = true; - } - } - if (flip->MessageField == 2) - { - flip->BmpIndex = newBmpIndex; - if (flip->BmpIndex <= 0) - { - flip->BmpIndex = 0; - bmpIndexOutOfBounds = true; - } - } - - if (bmpIndexOutOfBounds) - { - flip->MessageField = 0; - flip->Timer = 0; - } - else - { - flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired); - } - - auto bmp = flip->ListBitmap->at(flip->BmpIndex); - auto zMap = flip->ListZMap->at(flip->BmpIndex); + BmpIndex = newBmpIndex; + auto bmp = ListBitmap->at(BmpIndex); + auto zMap = ListZMap->at(BmpIndex); render::sprite_set( - flip->RenderSprite, + RenderSprite, bmp, zMap, - bmp->XPosition - flip->PinballTable->XOffset, - bmp->YPosition - flip->PinballTable->YOffset); + bmp->XPosition - PinballTable->XOffset, + bmp->YPosition - PinballTable->YOffset); } diff --git a/SpaceCadetPinball/TFlipper.h b/SpaceCadetPinball/TFlipper.h index a0e3538..cbf349a 100644 --- a/SpaceCadetPinball/TFlipper.h +++ b/SpaceCadetPinball/TFlipper.h @@ -13,14 +13,8 @@ public: void port_draw() override; void Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge) override; - - static void TimerExpired(int timerId, void* caller); + void UpdateSprite(float timeNow); int BmpIndex; TFlipperEdge* FlipperEdge; - int Timer; - float ExtendAnimationFrameTime{}; - float RetractAnimationFrameTime{}; - float TimerTime{}; - float InputTime; }; diff --git a/SpaceCadetPinball/TFlipperEdge.cpp b/SpaceCadetPinball/TFlipperEdge.cpp index 7d17567..10d423d 100644 --- a/SpaceCadetPinball/TFlipperEdge.cpp +++ b/SpaceCadetPinball/TFlipperEdge.cpp @@ -2,14 +2,11 @@ #include "TFlipperEdge.h" +#include "pb.h" #include "TLine.h" #include "TPinballTable.h" #include "TTableLayer.h" -float TFlipperEdge::flipper_sin_angle, TFlipperEdge::flipper_cos_angle; -vector2 TFlipperEdge::A1, TFlipperEdge::A2, TFlipperEdge::B1, TFlipperEdge::B2, TFlipperEdge::T1; -line_type TFlipperEdge::lineA, TFlipperEdge::lineB; -circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1; TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, vector3* origin, vector3* vecT1, vector3* vecT2, float extendTime, float retractTime, @@ -19,8 +16,6 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi Elasticity = elasticity; Smoothness = smoothness; - ExtendTime = extendTime; - RetractTime = retractTime; CollisionMult = collMult; T1Src = static_cast(*vecT1); @@ -51,7 +46,19 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi if (crossProd.Z < 0.0f) AngleMax = -AngleMax; FlipperFlag = 0; - Angle1 = 0.0; + AngleDst = 0.0; + + // 3DPB and FT have different formats for flipper speed: + // 3DPB: Time it takes for flipper to go from source to destination, in sec. + // FT: Flipper movement speed, in radians per sec. + if (pb::FullTiltMode) + { + auto angleMax = std::abs(AngleMax); + retractTime = angleMax / retractTime; + extendTime = angleMax / extendTime; + } + ExtendTime = extendTime; + RetractTime = retractTime; auto dirX1 = vecDir1.X; auto dirY1 = -vecDir1.Y; @@ -87,13 +94,12 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi InputTime = 0.0; CollisionFlag1 = 0; AngleStopTime = 0.0; - AngleMult = 0.0; + AngleAdvanceTime = 0.0; } void TFlipperEdge::port_draw() { set_control_points(InputTime); - build_edges_in_motion(); } float TFlipperEdge::FindCollisionDistance(ray_type* ray) @@ -112,7 +118,6 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) CollisionFlag1 = 0; CollisionFlag2 = 0; set_control_points(ogRay->TimeNow); - build_edges_in_motion(); auto ballInside = is_ball_inside(ogRay->Origin.X, ogRay->Origin.Y); srcRay.MinDistance = ogRay->MinDistance; if (ballInside == 0) @@ -120,7 +125,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) srcRay.Direction = ogRay->Direction; srcRay.MaxDistance = ogRay->MaxDistance; srcRay.Origin = ogRay->Origin; - auto distance = maths::distance_to_flipper(srcRay, dstRay); + auto distance = maths::distance_to_flipper(this, srcRay, dstRay); if (distance == 0.0f) { NextBallPosition = dstRay.Origin; @@ -166,14 +171,14 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f; srcRay.MaxDistance = ogRay->MaxDistance + 10.0f; - if (maths::distance_to_flipper(srcRay, dstRay) >= 1e+09f) + if (maths::distance_to_flipper(this, srcRay, dstRay) >= 1e+09f) { srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X; srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y; maths::normalize_2d(srcRay.Direction); srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f; - if (maths::distance_to_flipper(srcRay, dstRay) >= 1e+09f) + if (maths::distance_to_flipper(this, srcRay, dstRay) >= 1e+09f) { return 1e+09; } @@ -196,7 +201,6 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) while (timeNow < stopTime) { set_control_points(timeNow); - build_edges_in_motion(); auto ballInside = is_ball_inside(posX, posY); if (ballInside != 0) { @@ -220,7 +224,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f; srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f; srcRay.MaxDistance = ogRay->MaxDistance + 10.0f; - if (maths::distance_to_flipper(srcRay, dstRay) >= 1e+09f) + if (maths::distance_to_flipper(this, srcRay, dstRay) >= 1e+09f) { NextBallPosition.X = posX; NextBallPosition.Y = posY; @@ -249,7 +253,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f; srcRay.MaxDistance = ogRay->MaxDistance + 10.0f; - auto distance = maths::distance_to_flipper(srcRay, dstRay); + auto distance = maths::distance_to_flipper(this, srcRay, dstRay); CollisionDirection = dstRay.Direction; if (distance >= 1e+09f) { @@ -265,7 +269,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray) srcRay.MinDistance = ogRay->MinDistance; srcRay.Origin = ogRay->Origin; srcRay.MaxDistance = rayMaxDistance; - auto distance = maths::distance_to_flipper(srcRay, dstRay); + auto distance = maths::distance_to_flipper(this, srcRay, dstRay); if (distance < 1e+09f) { NextBallPosition = dstRay.Origin; @@ -312,7 +316,7 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float distance) if (circlebase.RadiusSq * 1.01f < distanceSq) { float v11; - float v20 = sqrt(distanceSq / DistanceDivSq) * (fabs(AngleMax) / AngleMult); + float v20 = sqrt(distanceSq / DistanceDivSq) * (fabs(AngleMax) / AngleAdvanceTime); float dot1 = maths::DotProduct(CollisionLinePerp, CollisionDirection); if (dot1 >= 0.0f) v11 = dot1 * v20; @@ -389,46 +393,39 @@ void TFlipperEdge::place_in_grid() void TFlipperEdge::set_control_points(float timeNow) { - maths::SinCos(flipper_angle(timeNow), flipper_sin_angle, flipper_cos_angle); + float sin, cos; + maths::SinCos(flipper_angle(timeNow), sin, cos); A1 = A1Src; A2 = A2Src; B1 = B1Src; B2 = B2Src; T1 = T1Src; - maths::RotatePt(A1, flipper_sin_angle, flipper_cos_angle, RotOrigin); - maths::RotatePt(A2, flipper_sin_angle, flipper_cos_angle, RotOrigin); - maths::RotatePt(T1, flipper_sin_angle, flipper_cos_angle, RotOrigin); - maths::RotatePt(B1, flipper_sin_angle, flipper_cos_angle, RotOrigin); - maths::RotatePt(B2, flipper_sin_angle, flipper_cos_angle, RotOrigin); -} - -void TFlipperEdge::build_edges_in_motion() -{ + maths::RotatePt(A1, sin, cos, RotOrigin); + maths::RotatePt(A2, sin, cos, RotOrigin); + maths::RotatePt(T1, sin, cos, RotOrigin); + maths::RotatePt(B1, sin, cos, RotOrigin); + maths::RotatePt(B2, sin, cos, RotOrigin); maths::line_init(lineA, A1.X, A1.Y, A2.X, A2.Y); maths::line_init(lineB, B1.X, B1.Y, B2.X, B2.Y); - circlebase.RadiusSq = CirclebaseRadiusSq; - circlebase.Center.X = RotOrigin.X; - circlebase.Center.Y = RotOrigin.Y; - circleT1.RadiusSq = CircleT1RadiusSq; - circleT1.Center.X = T1.X; - circleT1.Center.Y = T1.Y; + circlebase = {RotOrigin, CirclebaseRadiusSq}; + circleT1 = {T1, CircleT1RadiusSq}; } float TFlipperEdge::flipper_angle(float timeNow) { + // When not moving, flipper is at destination angle. if (!FlipperFlag) - return Angle1; + return AngleDst; - float currentAngleDuration = fabsf((Angle1 - Angle2) / AngleMax * AngleMult); - float currentAngleRatio; + // How much time it takes to go from source to destination angle, in sec. + auto arcDuration = std::abs((AngleDst - AngleSrc) / AngleMax * AngleAdvanceTime); - if (currentAngleDuration >= 0.0000001f) - currentAngleRatio = (timeNow - InputTime) / currentAngleDuration; - else - currentAngleRatio = 1.0; + // How close the flipper is to destination, in [0, 1] range. + auto t = arcDuration >= 0.0000001f ? (timeNow - InputTime) / arcDuration : 1.0f; + t = Clamp(t, 0.0f, 1.0f); - currentAngleRatio = std::min(1.0f, std::max(currentAngleRatio, 0.0f)); - return currentAngleRatio * (Angle1 - Angle2) + Angle2; + // Result = linear interpolation between source and destination angle. + return AngleSrc + t * (AngleDst - AngleSrc); } int TFlipperEdge::is_ball_inside(float x, float y) @@ -459,28 +456,32 @@ int TFlipperEdge::is_ball_inside(float x, float y) return 0; } -void TFlipperEdge::SetMotion(int code, float value) +int TFlipperEdge::SetMotion(int code, float value) { switch (code) { case 1: - Angle2 = flipper_angle(value); - Angle1 = AngleMax; - AngleMult = ExtendTime; + AngleSrc = flipper_angle(value); + AngleDst = AngleMax; + AngleAdvanceTime = ExtendTime; break; case 2: - Angle2 = flipper_angle(value); - Angle1 = 0.0; - AngleMult = RetractTime; + AngleSrc = flipper_angle(value); + AngleDst = 0.0f; + AngleAdvanceTime = RetractTime; break; case 1024: - FlipperFlag = 0; - Angle1 = 0.0; - return; + AngleSrc = 0.0f; + AngleDst = 0.0f; + break; default: break; } + if (AngleSrc == AngleDst) + code = 0; + InputTime = value; FlipperFlag = code; - AngleStopTime = AngleMult + InputTime; + AngleStopTime = AngleAdvanceTime + InputTime; + return code; } diff --git a/SpaceCadetPinball/TFlipperEdge.h b/SpaceCadetPinball/TFlipperEdge.h index 07c776c..ac7b80a 100644 --- a/SpaceCadetPinball/TFlipperEdge.h +++ b/SpaceCadetPinball/TFlipperEdge.h @@ -15,10 +15,9 @@ public: void EdgeCollision(TBall* ball, float distance) override; void place_in_grid() override; void set_control_points(float timeNow); - void build_edges_in_motion(); float flipper_angle(float timeNow); int is_ball_inside(float x, float y); - void SetMotion(int code, float value); + int SetMotion(int code, float value); int FlipperFlag; float Elasticity; @@ -31,8 +30,8 @@ public: float CirclebaseRadiusMSq; float CircleT1RadiusMSq; float AngleMax; - float Angle2{}; - float Angle1; + float AngleSrc{}; + float AngleDst; int CollisionFlag1; int CollisionFlag2{}; vector2 CollisionLinePerp{}; @@ -49,13 +48,11 @@ public: int EdgeCollisionFlag; float InputTime; float AngleStopTime; - float AngleMult; + float AngleAdvanceTime; float ExtendTime; float RetractTime; vector2 NextBallPosition{}; - - static float flipper_sin_angle, flipper_cos_angle; - static vector2 A1, A2, B1, B2, T1; - static line_type lineA, lineB; - static circle_type circlebase, circleT1; + vector2 A1, A2, B1, B2, T1; + line_type lineA, lineB; + circle_type circlebase, circleT1; }; diff --git a/SpaceCadetPinball/TPinballTable.h b/SpaceCadetPinball/TPinballTable.h index c0d3f73..e4b27a4 100644 --- a/SpaceCadetPinball/TPinballTable.h +++ b/SpaceCadetPinball/TPinballTable.h @@ -67,6 +67,7 @@ public: int Height{}; std::vector ComponentList; std::vector BallList; + std::vector FlipperList; TLightGroup* LightGroup; float GravityDirVectMult{}; float GravityAngleX{}; diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index fe3eaad..d8b51b4 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -300,29 +300,29 @@ void maths::RotatePt(vector2& point, float sin, float cos, const vector2& origin // Return the distance from ray1 origin to the intersection point with the closest flipper feature. // Sets ray2 origin to intersection point, direction to collision direction -float maths::distance_to_flipper(const ray_type& ray1, ray_type& ray2) +float maths::distance_to_flipper(TFlipperEdge* flipper, const ray_type& ray1, ray_type& ray2) { auto distance = 1000000000.0f; auto distanceType = FlipperIntersect::none; - auto newDistance = ray_intersect_line(ray1, TFlipperEdge::lineA); + auto newDistance = ray_intersect_line(ray1, flipper->lineA); if (newDistance < distance) { distance = newDistance; distanceType = FlipperIntersect::lineA; } - newDistance = ray_intersect_circle(ray1, TFlipperEdge::circlebase); + newDistance = ray_intersect_circle(ray1, flipper->circlebase); if (newDistance < distance) { distance = newDistance; distanceType = FlipperIntersect::circlebase; } - newDistance = ray_intersect_circle(ray1, TFlipperEdge::circleT1); + newDistance = ray_intersect_circle(ray1, flipper->circleT1); if (newDistance < distance) { distance = newDistance; distanceType = FlipperIntersect::circleT1; } - newDistance = ray_intersect_line(ray1, TFlipperEdge::lineB); + newDistance = ray_intersect_line(ray1, flipper->lineB); if (newDistance < distance) { distance = newDistance; @@ -332,19 +332,19 @@ float maths::distance_to_flipper(const ray_type& ray1, ray_type& ray2) switch (distanceType) { case FlipperIntersect::lineA: - ray2.Direction = TFlipperEdge::lineA.PerpendicularC; - ray2.Origin = TFlipperEdge::lineA.RayIntersect; + ray2.Direction = flipper->lineA.PerpendicularC; + ray2.Origin = flipper->lineA.RayIntersect; break; case FlipperIntersect::lineB: - ray2.Direction = TFlipperEdge::lineB.PerpendicularC; - ray2.Origin = TFlipperEdge::lineB.RayIntersect; + ray2.Direction = flipper->lineB.PerpendicularC; + ray2.Origin = flipper->lineB.RayIntersect; break; case FlipperIntersect::circlebase: case FlipperIntersect::circleT1: ray2.Origin.X = distance * ray1.Direction.X + ray1.Origin.X; ray2.Origin.Y = distance * ray1.Direction.Y + ray1.Origin.Y; ray2.Direction = vector_sub(ray2.Origin, distanceType == FlipperIntersect::circlebase ? - TFlipperEdge::circlebase.Center : TFlipperEdge::circleT1.Center); + flipper->circlebase.Center : flipper->circleT1.Center); normalize_2d(ray2.Direction); break; case FlipperIntersect::none: diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index 9e2e829..0ad31ad 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -1,6 +1,7 @@ #pragma once class TBall; +class TFlipperEdge; struct vector2 { @@ -118,7 +119,7 @@ public: static float Distance(const vector2& vec1, const vector2& vec2); static void SinCos(float angle, float& sinOut, float& cosOut); static void RotatePt(vector2& point, float sin, float cos, const vector2& origin); - static float distance_to_flipper(const ray_type& ray1, ray_type& ray2); + static float distance_to_flipper(TFlipperEdge* flipper, const ray_type& ray1, ray_type& ray2); static void RotateVector(vector2& vec, float angle); static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector2& lineEnd, vector2& lineStart); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 1197a3e..02f1d72 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -24,6 +24,7 @@ #include "GroupData.h" #include "partman.h" #include "score.h" +#include "TFlipper.h" #include "TPinballTable.h" #include "TTextBox.h" @@ -329,6 +330,11 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) } } + for (auto flipper : MainTable->FlipperList) + { + flipper->UpdateSprite(timeNow); + } + if (drawBalls) { for (auto ball : MainTable->BallList)