Code from FT: simplified TFlipper sprite update.

TFlipperEdge moving geometry stored in object.
This commit is contained in:
Muzychenko Andrey 2022-08-23 08:14:28 +03:00
parent 7feba1e947
commit acd1ad34b2
9 changed files with 113 additions and 175 deletions

View File

@ -296,11 +296,10 @@ void DebugOverlay::DrawEdge(TEdgeSegment* edge)
if (flip) if (flip)
{ {
flip->set_control_points(pb::time_now); flip->set_control_points(pb::time_now);
flip->build_edges_in_motion();
DrawLineType(TFlipperEdge::lineA); DrawLineType(flip->lineA);
DrawLineType(TFlipperEdge::lineB); DrawLineType(flip->lineB);
DrawCicleType(TFlipperEdge::circlebase); DrawCicleType(flip->circlebase);
DrawCicleType(TFlipperEdge::circleT1); DrawCicleType(flip->circleT1);
} }
} }

View File

@ -18,19 +18,11 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
HardHitSoundId = visual.SoundIndex4; HardHitSoundId = visual.SoundIndex4;
SoftHitSoundId = visual.SoundIndex3; SoftHitSoundId = visual.SoundIndex3;
Elasticity = visual.Elasticity; Elasticity = visual.Elasticity;
Timer = 0;
Smoothness = visual.Smoothness; Smoothness = visual.Smoothness;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803); auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805); auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805);
auto extendTime = *loader::query_float_attribute(groupIndex, 0, 804); 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<vector3*>(loader::query_float_attribute(groupIndex, 0, 802)); auto vecT2 = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 802));
auto vecT1 = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 801)); auto vecT1 = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 801));
auto origin = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 800)); auto origin = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 800));
@ -49,75 +41,53 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Smoothness); Smoothness);
FlipperEdge = flipperEdge; FlipperEdge = flipperEdge;
if (flipperEdge)
{
ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->size() - 1);
RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->size() - 1);
}
BmpIndex = 0; BmpIndex = 0;
InputTime = 0.0; if (table)
table->FlipperList.push_back(this);
} }
TFlipper::~TFlipper() TFlipper::~TFlipper()
{ {
delete FlipperEdge; 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) int TFlipper::Message(int code, float value)
{ {
if (code == 1 || code == 2 || (code > 1008 && code <= 1011) || code == 1022) if (code == 1 || code == 2 || (code > 1008 && code <= 1011) || code == 1022)
{ {
float timerTime;
int command = code;
if (code == 1) if (code == 1)
{ {
control::handler(1, this); control::handler(1, this);
TimerTime = ExtendAnimationFrameTime;
loader::play_sound(HardHitSoundId, this, "TFlipper1"); loader::play_sound(HardHitSoundId, this, "TFlipper1");
} }
else if (code == 2) else if (code == 2)
{ {
TimerTime = RetractAnimationFrameTime;
loader::play_sound(SoftHitSoundId, this, "TFlipper2"); loader::play_sound(SoftHitSoundId, this, "TFlipper2");
} }
else else
{ {
// Retract for all non-input messages // Retract for all non-input messages
command = 2; code = 2;
TimerTime = RetractAnimationFrameTime;
} }
if (MessageField) MessageField = FlipperEdge->SetMotion(code, value);
{ return 0;
// 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);
} }
if (code == 1020 || code == 1024) if (code == 1020 || code == 1024)
{ {
if (MessageField) if (MessageField)
{ {
if (Timer) MessageField = 0;
timer::kill(Timer); FlipperEdge->SetMotion(1024, value);
BmpIndex = -1; UpdateSprite(0);
MessageField = 2;
TimerExpired(Timer, this);
FlipperEdge->SetMotion(code, value);
} }
} }
return 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<TFlipper*>(caller); int bmpCountSub1 = ListBitmap->size() - 1;
int bmpCountSub1 = flip->ListBitmap->size() - 1;
auto newBmpIndex = static_cast<int>(floor(flip->FlipperEdge->flipper_angle(pb::time_now) / flip->FlipperEdge->AngleMax * bmpCountSub1 + 0.5)); auto newBmpIndex = static_cast<int>(floor(FlipperEdge->flipper_angle(timeNow) / FlipperEdge->AngleMax * bmpCountSub1 + 0.5f));
if (newBmpIndex > bmpCountSub1) newBmpIndex = Clamp(newBmpIndex, 0, bmpCountSub1);
newBmpIndex = bmpCountSub1; if (BmpIndex == newBmpIndex)
if (newBmpIndex < 0) return;
newBmpIndex = 0;
bool bmpIndexOutOfBounds = false; BmpIndex = newBmpIndex;
if (flip->MessageField == 1) auto bmp = ListBitmap->at(BmpIndex);
{ auto zMap = ListZMap->at(BmpIndex);
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);
render::sprite_set( render::sprite_set(
flip->RenderSprite, RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - flip->PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,
bmp->YPosition - flip->PinballTable->YOffset); bmp->YPosition - PinballTable->YOffset);
} }

View File

@ -13,14 +13,8 @@ public:
void port_draw() override; void port_draw() override;
void Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, void Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance,
TEdgeSegment* edge) override; TEdgeSegment* edge) override;
void UpdateSprite(float timeNow);
static void TimerExpired(int timerId, void* caller);
int BmpIndex; int BmpIndex;
TFlipperEdge* FlipperEdge; TFlipperEdge* FlipperEdge;
int Timer;
float ExtendAnimationFrameTime{};
float RetractAnimationFrameTime{};
float TimerTime{};
float InputTime;
}; };

View File

@ -2,14 +2,11 @@
#include "TFlipperEdge.h" #include "TFlipperEdge.h"
#include "pb.h"
#include "TLine.h" #include "TLine.h"
#include "TPinballTable.h" #include "TPinballTable.h"
#include "TTableLayer.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, TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table,
vector3* origin, vector3* vecT1, vector3* vecT2, float extendTime, float retractTime, vector3* origin, vector3* vecT1, vector3* vecT2, float extendTime, float retractTime,
@ -19,8 +16,6 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
Elasticity = elasticity; Elasticity = elasticity;
Smoothness = smoothness; Smoothness = smoothness;
ExtendTime = extendTime;
RetractTime = retractTime;
CollisionMult = collMult; CollisionMult = collMult;
T1Src = static_cast<vector2>(*vecT1); T1Src = static_cast<vector2>(*vecT1);
@ -51,7 +46,19 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
if (crossProd.Z < 0.0f) if (crossProd.Z < 0.0f)
AngleMax = -AngleMax; AngleMax = -AngleMax;
FlipperFlag = 0; 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 dirX1 = vecDir1.X;
auto dirY1 = -vecDir1.Y; auto dirY1 = -vecDir1.Y;
@ -87,13 +94,12 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
InputTime = 0.0; InputTime = 0.0;
CollisionFlag1 = 0; CollisionFlag1 = 0;
AngleStopTime = 0.0; AngleStopTime = 0.0;
AngleMult = 0.0; AngleAdvanceTime = 0.0;
} }
void TFlipperEdge::port_draw() void TFlipperEdge::port_draw()
{ {
set_control_points(InputTime); set_control_points(InputTime);
build_edges_in_motion();
} }
float TFlipperEdge::FindCollisionDistance(ray_type* ray) float TFlipperEdge::FindCollisionDistance(ray_type* ray)
@ -112,7 +118,6 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
CollisionFlag1 = 0; CollisionFlag1 = 0;
CollisionFlag2 = 0; CollisionFlag2 = 0;
set_control_points(ogRay->TimeNow); set_control_points(ogRay->TimeNow);
build_edges_in_motion();
auto ballInside = is_ball_inside(ogRay->Origin.X, ogRay->Origin.Y); auto ballInside = is_ball_inside(ogRay->Origin.X, ogRay->Origin.Y);
srcRay.MinDistance = ogRay->MinDistance; srcRay.MinDistance = ogRay->MinDistance;
if (ballInside == 0) if (ballInside == 0)
@ -120,7 +125,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Direction = ogRay->Direction; srcRay.Direction = ogRay->Direction;
srcRay.MaxDistance = ogRay->MaxDistance; srcRay.MaxDistance = ogRay->MaxDistance;
srcRay.Origin = ogRay->Origin; 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) if (distance == 0.0f)
{ {
NextBallPosition = dstRay.Origin; 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.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.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.X = RotOrigin.X - ogRay->Origin.X;
srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y; srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
maths::normalize_2d(srcRay.Direction); maths::normalize_2d(srcRay.Direction);
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f; srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 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; return 1e+09;
} }
@ -196,7 +201,6 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
while (timeNow < stopTime) while (timeNow < stopTime)
{ {
set_control_points(timeNow); set_control_points(timeNow);
build_edges_in_motion();
auto ballInside = is_ball_inside(posX, posY); auto ballInside = is_ball_inside(posX, posY);
if (ballInside != 0) if (ballInside != 0)
{ {
@ -220,7 +224,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f; srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f; srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.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.X = posX;
NextBallPosition.Y = posY; 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.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.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; CollisionDirection = dstRay.Direction;
if (distance >= 1e+09f) if (distance >= 1e+09f)
{ {
@ -265,7 +269,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.MinDistance = ogRay->MinDistance; srcRay.MinDistance = ogRay->MinDistance;
srcRay.Origin = ogRay->Origin; srcRay.Origin = ogRay->Origin;
srcRay.MaxDistance = rayMaxDistance; srcRay.MaxDistance = rayMaxDistance;
auto distance = maths::distance_to_flipper(srcRay, dstRay); auto distance = maths::distance_to_flipper(this, srcRay, dstRay);
if (distance < 1e+09f) if (distance < 1e+09f)
{ {
NextBallPosition = dstRay.Origin; NextBallPosition = dstRay.Origin;
@ -312,7 +316,7 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float distance)
if (circlebase.RadiusSq * 1.01f < distanceSq) if (circlebase.RadiusSq * 1.01f < distanceSq)
{ {
float v11; float v11;
float v20 = sqrt(distanceSq / DistanceDivSq) * (fabs(AngleMax) / AngleMult); float v20 = sqrt(distanceSq / DistanceDivSq) * (fabs(AngleMax) / AngleAdvanceTime);
float dot1 = maths::DotProduct(CollisionLinePerp, CollisionDirection); float dot1 = maths::DotProduct(CollisionLinePerp, CollisionDirection);
if (dot1 >= 0.0f) if (dot1 >= 0.0f)
v11 = dot1 * v20; v11 = dot1 * v20;
@ -389,46 +393,39 @@ void TFlipperEdge::place_in_grid()
void TFlipperEdge::set_control_points(float timeNow) 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; A1 = A1Src;
A2 = A2Src; A2 = A2Src;
B1 = B1Src; B1 = B1Src;
B2 = B2Src; B2 = B2Src;
T1 = T1Src; T1 = T1Src;
maths::RotatePt(A1, flipper_sin_angle, flipper_cos_angle, RotOrigin); maths::RotatePt(A1, sin, cos, RotOrigin);
maths::RotatePt(A2, flipper_sin_angle, flipper_cos_angle, RotOrigin); maths::RotatePt(A2, sin, cos, RotOrigin);
maths::RotatePt(T1, flipper_sin_angle, flipper_cos_angle, RotOrigin); maths::RotatePt(T1, sin, cos, RotOrigin);
maths::RotatePt(B1, flipper_sin_angle, flipper_cos_angle, RotOrigin); maths::RotatePt(B1, sin, cos, RotOrigin);
maths::RotatePt(B2, flipper_sin_angle, flipper_cos_angle, RotOrigin); maths::RotatePt(B2, sin, cos, RotOrigin);
}
void TFlipperEdge::build_edges_in_motion()
{
maths::line_init(lineA, A1.X, A1.Y, A2.X, A2.Y); maths::line_init(lineA, A1.X, A1.Y, A2.X, A2.Y);
maths::line_init(lineB, B1.X, B1.Y, B2.X, B2.Y); maths::line_init(lineB, B1.X, B1.Y, B2.X, B2.Y);
circlebase.RadiusSq = CirclebaseRadiusSq; circlebase = {RotOrigin, CirclebaseRadiusSq};
circlebase.Center.X = RotOrigin.X; circleT1 = {T1, CircleT1RadiusSq};
circlebase.Center.Y = RotOrigin.Y;
circleT1.RadiusSq = CircleT1RadiusSq;
circleT1.Center.X = T1.X;
circleT1.Center.Y = T1.Y;
} }
float TFlipperEdge::flipper_angle(float timeNow) float TFlipperEdge::flipper_angle(float timeNow)
{ {
// When not moving, flipper is at destination angle.
if (!FlipperFlag) if (!FlipperFlag)
return Angle1; return AngleDst;
float currentAngleDuration = fabsf((Angle1 - Angle2) / AngleMax * AngleMult); // How much time it takes to go from source to destination angle, in sec.
float currentAngleRatio; auto arcDuration = std::abs((AngleDst - AngleSrc) / AngleMax * AngleAdvanceTime);
if (currentAngleDuration >= 0.0000001f) // How close the flipper is to destination, in [0, 1] range.
currentAngleRatio = (timeNow - InputTime) / currentAngleDuration; auto t = arcDuration >= 0.0000001f ? (timeNow - InputTime) / arcDuration : 1.0f;
else t = Clamp(t, 0.0f, 1.0f);
currentAngleRatio = 1.0;
currentAngleRatio = std::min(1.0f, std::max(currentAngleRatio, 0.0f)); // Result = linear interpolation between source and destination angle.
return currentAngleRatio * (Angle1 - Angle2) + Angle2; return AngleSrc + t * (AngleDst - AngleSrc);
} }
int TFlipperEdge::is_ball_inside(float x, float y) int TFlipperEdge::is_ball_inside(float x, float y)
@ -459,28 +456,32 @@ int TFlipperEdge::is_ball_inside(float x, float y)
return 0; return 0;
} }
void TFlipperEdge::SetMotion(int code, float value) int TFlipperEdge::SetMotion(int code, float value)
{ {
switch (code) switch (code)
{ {
case 1: case 1:
Angle2 = flipper_angle(value); AngleSrc = flipper_angle(value);
Angle1 = AngleMax; AngleDst = AngleMax;
AngleMult = ExtendTime; AngleAdvanceTime = ExtendTime;
break; break;
case 2: case 2:
Angle2 = flipper_angle(value); AngleSrc = flipper_angle(value);
Angle1 = 0.0; AngleDst = 0.0f;
AngleMult = RetractTime; AngleAdvanceTime = RetractTime;
break; break;
case 1024: case 1024:
FlipperFlag = 0; AngleSrc = 0.0f;
Angle1 = 0.0; AngleDst = 0.0f;
return; break;
default: break; default: break;
} }
if (AngleSrc == AngleDst)
code = 0;
InputTime = value; InputTime = value;
FlipperFlag = code; FlipperFlag = code;
AngleStopTime = AngleMult + InputTime; AngleStopTime = AngleAdvanceTime + InputTime;
return code;
} }

View File

@ -15,10 +15,9 @@ public:
void EdgeCollision(TBall* ball, float distance) override; void EdgeCollision(TBall* ball, float distance) override;
void place_in_grid() override; void place_in_grid() override;
void set_control_points(float timeNow); void set_control_points(float timeNow);
void build_edges_in_motion();
float flipper_angle(float timeNow); float flipper_angle(float timeNow);
int is_ball_inside(float x, float y); int is_ball_inside(float x, float y);
void SetMotion(int code, float value); int SetMotion(int code, float value);
int FlipperFlag; int FlipperFlag;
float Elasticity; float Elasticity;
@ -31,8 +30,8 @@ public:
float CirclebaseRadiusMSq; float CirclebaseRadiusMSq;
float CircleT1RadiusMSq; float CircleT1RadiusMSq;
float AngleMax; float AngleMax;
float Angle2{}; float AngleSrc{};
float Angle1; float AngleDst;
int CollisionFlag1; int CollisionFlag1;
int CollisionFlag2{}; int CollisionFlag2{};
vector2 CollisionLinePerp{}; vector2 CollisionLinePerp{};
@ -49,13 +48,11 @@ public:
int EdgeCollisionFlag; int EdgeCollisionFlag;
float InputTime; float InputTime;
float AngleStopTime; float AngleStopTime;
float AngleMult; float AngleAdvanceTime;
float ExtendTime; float ExtendTime;
float RetractTime; float RetractTime;
vector2 NextBallPosition{}; vector2 NextBallPosition{};
vector2 A1, A2, B1, B2, T1;
static float flipper_sin_angle, flipper_cos_angle; line_type lineA, lineB;
static vector2 A1, A2, B1, B2, T1; circle_type circlebase, circleT1;
static line_type lineA, lineB;
static circle_type circlebase, circleT1;
}; };

View File

@ -67,6 +67,7 @@ public:
int Height{}; int Height{};
std::vector<TPinballComponent*> ComponentList; std::vector<TPinballComponent*> ComponentList;
std::vector<TBall*> BallList; std::vector<TBall*> BallList;
std::vector<TFlipper*> FlipperList;
TLightGroup* LightGroup; TLightGroup* LightGroup;
float GravityDirVectMult{}; float GravityDirVectMult{};
float GravityAngleX{}; float GravityAngleX{};

View File

@ -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. // 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 // 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 distance = 1000000000.0f;
auto distanceType = FlipperIntersect::none; auto distanceType = FlipperIntersect::none;
auto newDistance = ray_intersect_line(ray1, TFlipperEdge::lineA); auto newDistance = ray_intersect_line(ray1, flipper->lineA);
if (newDistance < distance) if (newDistance < distance)
{ {
distance = newDistance; distance = newDistance;
distanceType = FlipperIntersect::lineA; distanceType = FlipperIntersect::lineA;
} }
newDistance = ray_intersect_circle(ray1, TFlipperEdge::circlebase); newDistance = ray_intersect_circle(ray1, flipper->circlebase);
if (newDistance < distance) if (newDistance < distance)
{ {
distance = newDistance; distance = newDistance;
distanceType = FlipperIntersect::circlebase; distanceType = FlipperIntersect::circlebase;
} }
newDistance = ray_intersect_circle(ray1, TFlipperEdge::circleT1); newDistance = ray_intersect_circle(ray1, flipper->circleT1);
if (newDistance < distance) if (newDistance < distance)
{ {
distance = newDistance; distance = newDistance;
distanceType = FlipperIntersect::circleT1; distanceType = FlipperIntersect::circleT1;
} }
newDistance = ray_intersect_line(ray1, TFlipperEdge::lineB); newDistance = ray_intersect_line(ray1, flipper->lineB);
if (newDistance < distance) if (newDistance < distance)
{ {
distance = newDistance; distance = newDistance;
@ -332,19 +332,19 @@ float maths::distance_to_flipper(const ray_type& ray1, ray_type& ray2)
switch (distanceType) switch (distanceType)
{ {
case FlipperIntersect::lineA: case FlipperIntersect::lineA:
ray2.Direction = TFlipperEdge::lineA.PerpendicularC; ray2.Direction = flipper->lineA.PerpendicularC;
ray2.Origin = TFlipperEdge::lineA.RayIntersect; ray2.Origin = flipper->lineA.RayIntersect;
break; break;
case FlipperIntersect::lineB: case FlipperIntersect::lineB:
ray2.Direction = TFlipperEdge::lineB.PerpendicularC; ray2.Direction = flipper->lineB.PerpendicularC;
ray2.Origin = TFlipperEdge::lineB.RayIntersect; ray2.Origin = flipper->lineB.RayIntersect;
break; break;
case FlipperIntersect::circlebase: case FlipperIntersect::circlebase:
case FlipperIntersect::circleT1: case FlipperIntersect::circleT1:
ray2.Origin.X = distance * ray1.Direction.X + ray1.Origin.X; ray2.Origin.X = distance * ray1.Direction.X + ray1.Origin.X;
ray2.Origin.Y = distance * ray1.Direction.Y + ray1.Origin.Y; ray2.Origin.Y = distance * ray1.Direction.Y + ray1.Origin.Y;
ray2.Direction = vector_sub(ray2.Origin, distanceType == FlipperIntersect::circlebase ? 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); normalize_2d(ray2.Direction);
break; break;
case FlipperIntersect::none: case FlipperIntersect::none:

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
class TBall; class TBall;
class TFlipperEdge;
struct vector2 struct vector2
{ {
@ -118,7 +119,7 @@ public:
static float Distance(const vector2& vec1, const vector2& vec2); static float Distance(const vector2& vec1, const vector2& vec2);
static void SinCos(float angle, float& sinOut, float& cosOut); static void SinCos(float angle, float& sinOut, float& cosOut);
static void RotatePt(vector2& point, float sin, float cos, const vector2& origin); 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 RotateVector(vector2& vec, float angle);
static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector2& lineEnd, static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector2& lineEnd,
vector2& lineStart); vector2& lineStart);

View File

@ -24,6 +24,7 @@
#include "GroupData.h" #include "GroupData.h"
#include "partman.h" #include "partman.h"
#include "score.h" #include "score.h"
#include "TFlipper.h"
#include "TPinballTable.h" #include "TPinballTable.h"
#include "TTextBox.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) if (drawBalls)
{ {
for (auto ball : MainTable->BallList) for (auto ball : MainTable->BallList)