mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-12-18 10:37:53 +01:00
Code from FT: simplified TFlipper sprite update.
TFlipperEdge moving geometry stored in object.
This commit is contained in:
parent
7feba1e947
commit
acd1ad34b2
9 changed files with 113 additions and 175 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue