FT collision part3: cleanup.

This commit is contained in:
Muzychenko Andrey 2023-03-05 14:16:07 +03:00
parent ba470e8727
commit 4b86fe2aa7
16 changed files with 144 additions and 202 deletions

View File

@ -211,7 +211,10 @@ void DebugOverlay::DrawBallInfo()
SDL_SetRenderDrawColor(winmain::Renderer, 0, 0, 255, 255); SDL_SetRenderDrawColor(winmain::Renderer, 0, 0, 255, 255);
auto pt1 = proj::xform_to_2d(ballPosition); auto pt1 = proj::xform_to_2d(ballPosition);
SDL_RenderDrawCircle(winmain::Renderer, pt1.X, pt1.Y, 10); vector2 radVec1 = { 0, ballPosition.Y }, radVec2 = { ball->Radius, ballPosition.Y };
auto radVec1I = proj::xform_to_2d(radVec1), radVec2I = proj::xform_to_2d(radVec2);
auto radI = std::sqrt(maths::magnitudeSq(vector2i{ radVec1I.X - radVec2I.X ,radVec1I.Y - radVec2I.Y }));
SDL_RenderDrawCircle(winmain::Renderer, pt1.X, pt1.Y, static_cast<int>(std::round(radI)));
auto nextPos = ballPosition; auto nextPos = ballPosition;
maths::vector_add(nextPos, maths::vector_mul(ball->Direction, ball->Speed / 10.0f)); maths::vector_add(nextPos, maths::vector_mul(ball->Direction, ball->Speed / 10.0f));

View File

@ -41,7 +41,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
groupIndex = loader::query_handle(ballGroupName); groupIndex = loader::query_handle(ballGroupName);
} }
Offset = *loader::query_float_attribute(groupIndex, 0, 500); Radius = *loader::query_float_attribute(groupIndex, 0, 500);
auto visualCount = loader::query_visual_states(groupIndex); auto visualCount = loader::query_visual_states(groupIndex);
for (auto index = 0; index < visualCount; ++index) for (auto index = 0; index < visualCount; ++index)
@ -53,8 +53,8 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
VisualZArray[index] = zDepth; VisualZArray[index] = zDepth;
} }
RenderSprite = new render_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr); RenderSprite = new render_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr);
PinballTable->CollisionCompOffset = Offset; PinballTable->CollisionCompOffset = Radius;
Position.Z = Offset; Position.Z = Radius;
GroupIndex = groupIndex; GroupIndex = groupIndex;
} }
@ -65,7 +65,7 @@ void TBall::Repaint()
Position.Z = Position.Z =
CollisionOffset.X * Position.X + CollisionOffset.X * Position.X +
CollisionOffset.Y * Position.Y + CollisionOffset.Y * Position.Y +
Offset + CollisionOffset.Z; Radius + CollisionOffset.Z;
} }
auto pos2D = proj::xform_to_2d(Position); auto pos2D = proj::xform_to_2d(Position);
@ -120,7 +120,7 @@ int TBall::Message(MessageCode code, float value)
CollisionFlag = 0; CollisionFlag = 0;
CollisionMask = 1; CollisionMask = 1;
Direction.Y = 0.0; Direction.Y = 0.0;
Position.Z = Offset; Position.Z = Radius;
Direction.X = 0.0; Direction.X = 0.0;
Speed = 0.0; Speed = 0.0;
RayMaxDistance = 0.0; RayMaxDistance = 0.0;

View File

@ -32,10 +32,10 @@ public :
bool EdgeCollisionResetFlag{}; bool EdgeCollisionResetFlag{};
vector3 CollisionOffset{}; vector3 CollisionOffset{};
int CollisionFlag; int CollisionFlag;
float Offset; float Radius;
bool HasGroupFlag; bool HasGroupFlag;
int SomeCounter1 = 0; int StuckCounter = 0;
int time_ticks1{}, time_ticks2{}; int LastActiveTime{};
float VisualZArray[50]{}; float VisualZArray[50]{};
bool AsEdgeCollisionFlag{}; bool AsEdgeCollisionFlag{};
}; };

View File

@ -126,19 +126,19 @@ void TFlipper::UpdateSprite()
SpriteSet(BmpIndex); SpriteSet(BmpIndex);
} }
int TFlipper::GetFlipperAngleDistance(float dt, float* dst) const int TFlipper::GetFlipperStepAngle(float dt, float* dst) const
{ {
if (!MessageField) if (!MessageField)
return 0; return 0;
auto deltaAngle = FlipperEdge->flipper_angle_delta(dt); auto deltaAngle = FlipperEdge->flipper_angle_delta(dt);
auto distance = std::fabs(std::ceil(FlipperEdge->DistanceDiv * deltaAngle * FlipperEdge->InvT1Radius)); auto step = std::fabs(std::ceil(FlipperEdge->DistanceDiv * deltaAngle * FlipperEdge->InvT1Radius));
if (distance > 3.0f) if (step > 3.0f)
distance = 3.0f; step = 3.0f;
if (distance >= 2.0f) if (step >= 2.0f)
{ {
*dst = deltaAngle / distance; *dst = deltaAngle / step;
return static_cast<int>(distance); return static_cast<int>(step);
} }
*dst = deltaAngle; *dst = deltaAngle;
@ -152,7 +152,6 @@ void TFlipper::FlipperCollision(float deltaAngle)
ray_type ray{}, rayDst{}; ray_type ray{}, rayDst{};
ray.MinDistance = 0.002f; ray.MinDistance = 0.002f;
auto deltaAngleNeg = -deltaAngle;
bool collisionFlag = false; bool collisionFlag = false;
for (auto ball : pb::MainTable->BallList) for (auto ball : pb::MainTable->BallList)
{ {
@ -167,7 +166,7 @@ void TFlipper::FlipperCollision(float deltaAngle)
float sin, cos; float sin, cos;
auto ballPosRot = ray.Origin; auto ballPosRot = ray.Origin;
maths::SinCos(deltaAngleNeg, sin, cos); maths::SinCos(-deltaAngle, sin, cos);
maths::RotatePt(ballPosRot, sin, cos, FlipperEdge->RotOrigin); maths::RotatePt(ballPosRot, sin, cos, FlipperEdge->RotOrigin);
ray.Direction.X = ballPosRot.X - ray.Origin.X; ray.Direction.X = ballPosRot.X - ray.Origin.X;
ray.Direction.Y = ballPosRot.Y - ray.Origin.Y; ray.Direction.Y = ballPosRot.Y - ray.Origin.Y;
@ -188,24 +187,18 @@ void TFlipper::FlipperCollision(float deltaAngle)
auto angleAdvance = deltaAngle / (std::fabs(FlipperEdge->MoveSpeed) * 5.0f); auto angleAdvance = deltaAngle / (std::fabs(FlipperEdge->MoveSpeed) * 5.0f);
FlipperEdge->CurrentAngle -= angleAdvance; FlipperEdge->CurrentAngle -= angleAdvance;
FlipperEdge->AngleRemainder += std::fabs(angleAdvance); FlipperEdge->AngleRemainder += std::fabs(angleAdvance);
if (FlipperEdge->AngleRemainder <= 0.0001f)
{
FlipperEdge->CurrentAngle = FlipperEdge->AngleDst;
FlipperEdge->FlipperFlag = MessageCode::TFlipperNull;
MessageField = 0;
}
FlipperEdge->ControlPointDirtyFlag = true;
} }
else else
{ {
FlipperEdge->CurrentAngle += deltaAngle; FlipperEdge->CurrentAngle += deltaAngle;
FlipperEdge->AngleRemainder -= std::fabs(deltaAngle); FlipperEdge->AngleRemainder -= std::fabs(deltaAngle);
if (FlipperEdge->AngleRemainder <= 0.0001f)
{
FlipperEdge->CurrentAngle = FlipperEdge->AngleDst;
FlipperEdge->FlipperFlag = MessageCode::TFlipperNull;
MessageField = 0;
}
FlipperEdge->ControlPointDirtyFlag = true;
} }
if (FlipperEdge->AngleRemainder <= 0.0001f)
{
FlipperEdge->CurrentAngle = FlipperEdge->AngleDst;
FlipperEdge->FlipperFlag = MessageCode::TFlipperNull;
MessageField = 0;
}
FlipperEdge->ControlPointDirtyFlag = true;
} }

View File

@ -14,7 +14,7 @@ public:
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(); void UpdateSprite();
int GetFlipperAngleDistance(float dt, float* dst) const; int GetFlipperStepAngle(float dt, float* dst) const;
void FlipperCollision(float deltaAngle); void FlipperCollision(float deltaAngle);
int BmpIndex; int BmpIndex;

View File

@ -133,23 +133,24 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float distance)
return; return;
} }
auto someProduct = (NextBallPosition.Y - T1.Y) * (RotOrigin.X - T1.X) - vector2 t1NextPos{NextBallPosition.X - T1.X, NextBallPosition.Y - T1.Y},
(NextBallPosition.X - T1.X) * (RotOrigin.Y - T1.Y); t1RotOrigin{RotOrigin.X - T1.X, RotOrigin.Y - T1.Y};
auto crossProduct = maths::cross(t1RotOrigin, t1NextPos);
bool someFlag = false; bool frontCollision = false;
if (someProduct <= 0) if (crossProduct <= 0)
{ {
if (AngleMax > 0) if (AngleMax > 0)
someFlag = true; frontCollision = true;
} }
else if (AngleMax <= 0) else if (AngleMax <= 0)
{ {
someFlag = true; frontCollision = true;
} }
if (FlipperFlag == MessageCode::TFlipperRetract) if (FlipperFlag == MessageCode::TFlipperRetract)
{ {
someFlag ^= true; frontCollision ^= true;
CollisionLinePerp = LineB.PerpendicularC; CollisionLinePerp = LineB.PerpendicularC;
} }
else else
@ -160,7 +161,7 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float distance)
auto dx = NextBallPosition.X - RotOrigin.X; auto dx = NextBallPosition.X - RotOrigin.X;
auto dy = NextBallPosition.Y - RotOrigin.Y; auto dy = NextBallPosition.Y - RotOrigin.Y;
auto distanceSq = dy * dy + dx * dx; auto distanceSq = dy * dy + dx * dx;
if (someFlag) if (frontCollision)
{ {
float boost = 0; float boost = 0;
if (circlebase.RadiusSq * 1.01f < distanceSq) if (circlebase.RadiusSq * 1.01f < distanceSq)
@ -204,7 +205,7 @@ void TFlipperEdge::place_in_grid(RectF* aabb)
TTableLayer::edges_insert_square(yMin, xMin, yMax, xMax, this, nullptr); TTableLayer::edges_insert_square(yMin, xMin, yMax, xMax, this, nullptr);
auto offset = 1.0f / InvT1Radius + pb::ball_min_smth; auto offset = 1.0f / InvT1Radius + pb::BallHalfRadius;
XMin = xMin - offset; XMin = xMin - offset;
YMin = yMin - offset; YMin = yMin - offset;
XMax = xMax + offset; XMax = xMax + offset;

View File

@ -611,7 +611,7 @@ TBall* TPinballTable::AddBall(float x, float y)
if (ball != nullptr) if (ball != nullptr)
{ {
ball->ActiveFlag = 1; ball->ActiveFlag = 1;
ball->Position.Z = ball->Offset; ball->Position.Z = ball->Radius;
ball->Direction = {}; ball->Direction = {};
ball->Speed = 0; ball->Speed = 0;
ball->TimeDelta = 0; ball->TimeDelta = 0;
@ -632,8 +632,8 @@ TBall* TPinballTable::AddBall(float x, float y)
ball->Position.X = x; ball->Position.X = x;
ball->Position.Y = y; ball->Position.Y = y;
ball->PrevPosition = ball->Position; ball->PrevPosition = ball->Position;
ball->SomeCounter1 = 0; ball->StuckCounter = 0;
ball->time_ticks1 = ball->time_ticks2 = pb::time_ticks; ball->LastActiveTime = pb::time_ticks;
return ball; return ball;
} }

View File

@ -144,7 +144,7 @@ void TRamp::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
ball->RampFieldForce.X = plane->FieldForce.X; ball->RampFieldForce.X = plane->FieldForce.X;
ball->RampFieldForce.Y = plane->FieldForce.Y; ball->RampFieldForce.Y = plane->FieldForce.Y;
ball->Position.Z = ball->Position.X * ball->CollisionOffset.X + ball->Position.Y * ball->CollisionOffset.Y + ball->Position.Z = ball->Position.X * ball->CollisionOffset.X + ball->Position.Y * ball->CollisionOffset.Y +
ball->Offset + ball->CollisionOffset.Z; ball->Radius + ball->CollisionOffset.Z;
ball->CollisionMask = CollisionGroup; ball->CollisionMask = CollisionGroup;
return; return;
} }
@ -164,13 +164,13 @@ void TRamp::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
{ {
ball->CollisionMask = Wall1CollisionGroup; ball->CollisionMask = Wall1CollisionGroup;
if (BallZOffsetFlag) if (BallZOffsetFlag)
ball->Position.Z = ball->Offset + Wall1BallOffset; ball->Position.Z = ball->Radius + Wall1BallOffset;
} }
else else
{ {
ball->CollisionMask = Wall2CollisionGroup; ball->CollisionMask = Wall2CollisionGroup;
if (BallZOffsetFlag) if (BallZOffsetFlag)
ball->Position.Z = ball->Offset + Wall2BallOffset; ball->Position.Z = ball->Radius + Wall2BallOffset;
} }
} }
} }

View File

@ -7,6 +7,7 @@
#include "render.h" #include "render.h"
#include "TPinballTable.h" #include "TPinballTable.h"
#include "TBall.h" #include "TBall.h"
#include "TDrain.h"
#include "timer.h" #include "timer.h"
TSink::TSink(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true) TSink::TSink(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
@ -59,7 +60,7 @@ void TSink::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
{ {
if (PinballTable->TiltLockFlag) if (PinballTable->TiltLockFlag)
{ {
maths::basic_collision(ball, nextPosition, direction, Elasticity, Smoothness, 1000000000.0, 0.0); PinballTable->Drain->Collision(ball, nextPosition, direction, distance, edge);
} }
else else
{ {

View File

@ -1063,13 +1063,13 @@ void control::cheat_bump_rank()
} }
} }
void control::BallThrowOrDisable(TBall& ball, int dt) void control::UnstuckBall(TBall& ball, int dt)
{ {
if (!CheckBallInControlBounds(ball, *flip1) && if (!CheckBallInControlBounds(ball, *flip1) &&
!CheckBallInControlBounds(ball, *flip2) && !CheckBallInControlBounds(ball, *flip2) &&
!CheckBallInControlBounds(ball, *plunger)) !CheckBallInControlBounds(ball, *plunger))
{ {
if (ball.SomeCounter1 <= 20) if (ball.StuckCounter <= 20)
{ {
vector3 throwDir{0.0f, -1.0f, 0.0f}; vector3 throwDir{0.0f, -1.0f, 0.0f};
ball.throw_ball(&throwDir, 90.0f, 1.0f, 0.0f); ball.throw_ball(&throwDir, 90.0f, 1.0f, 0.0f);

View File

@ -89,7 +89,7 @@ public:
static void table_set_multiball(float time); static void table_set_multiball(float time);
static void table_bump_ball_sink_lock(); static void table_bump_ball_sink_lock();
static void table_set_replay(float value); static void table_set_replay(float value);
static void BallThrowOrDisable(TBall& ball, int dt); static void UnstuckBall(TBall& ball, int dt);
static bool CheckBallInControlBounds(const TBall& ball, const TCollisionComponent& cmp); static bool CheckBallInControlBounds(const TBall& ball, const TCollisionComponent& cmp);
static void cheat_bump_rank(); static void cheat_bump_rank();
static int SpecialAddScore(int score); static int SpecialAddScore(int score);

View File

@ -222,6 +222,11 @@ float maths::magnitudeSq(const vector2& vec)
return vec.X * vec.X + vec.Y * vec.Y; return vec.X * vec.X + vec.Y * vec.Y;
} }
int maths::magnitudeSq(const vector2i& vec)
{
return vec.X * vec.X + vec.Y * vec.Y;
}
void maths::vector_add(vector2& vec1Dst, const vector2& vec2) void maths::vector_add(vector2& vec1Dst, const vector2& vec2)
{ {
vec1Dst.X += vec2.X; vec1Dst.X += vec2.X;

View File

@ -53,7 +53,6 @@ struct ray_type
float MaxDistance; float MaxDistance;
float MinDistance; float MinDistance;
float TimeNow; float TimeNow;
float TimeDelta;
int CollisionMask; int CollisionMask;
}; };
@ -115,6 +114,7 @@ public:
static float cross(const vector2& vec1, const vector2& vec2); static float cross(const vector2& vec1, const vector2& vec2);
static float magnitude(const vector3& vec); static float magnitude(const vector3& vec);
static float magnitudeSq(const vector2& vec); static float magnitudeSq(const vector2& vec);
static int magnitudeSq(const vector2i& vec);
static void vector_add(vector2& vec1Dst, const vector2& vec2); static void vector_add(vector2& vec1Dst, const vector2& vec2);
static vector2 vector_sub(const vector2& vec1, const vector2& vec2); static vector2 vector_sub(const vector2& vec1, const vector2& vec2);
static vector3 vector_sub(const vector3& vec1, const vector3& vec2); static vector3 vector_sub(const vector3& vec1, const vector3& vec2);

View File

@ -33,7 +33,7 @@ DatFile* pb::record_table = nullptr;
int pb::time_ticks = 0; int pb::time_ticks = 0;
GameModes pb::game_mode = GameModes::GameOver; GameModes pb::game_mode = GameModes::GameOver;
float pb::time_now = 0, pb::time_next = 0, pb::time_ticks_remainder = 0; float pb::time_now = 0, pb::time_next = 0, pb::time_ticks_remainder = 0;
float pb::ball_speed_limit, pb::ball_min_smth, pb::ball_inv_smth, pb::ball_collision_dist; float pb::BallMaxSpeed, pb::BallHalfRadius, pb::ball_collision_dist;
bool pb::FullTiltMode = false, pb::FullTiltDemoMode = false, pb::cheat_mode = false, pb::demo_mode = false; bool pb::FullTiltMode = false, pb::FullTiltDemoMode = false, pb::cheat_mode = false, pb::demo_mode = false;
std::string pb::DatFileName, pb::BasePath; std::string pb::DatFileName, pb::BasePath;
ImU32 pb::TextBoxColor; ImU32 pb::TextBoxColor;
@ -104,10 +104,9 @@ int pb::init()
high_score::read(); high_score::read();
auto ball = MainTable->BallList.at(0); auto ball = MainTable->BallList.at(0);
ball_speed_limit = ball->Offset * 200.0f; BallMaxSpeed = ball->Radius * 200.0f;
ball_min_smth = ball->Offset * 0.5f; BallHalfRadius = ball->Radius * 0.5f;
ball_inv_smth = 1.0f / ball_min_smth; ball_collision_dist = (ball->Radius + BallHalfRadius) * 2.0f;
ball_collision_dist = (ball->Offset + ball_min_smth) * 2.0f;
int red = 255, green = 255, blue = 255; int red = 255, green = 255, blue = 255;
auto fontColor = get_rc_string(Msg::TextBoxColor); auto fontColor = get_rc_string(Msg::TextBoxColor);
@ -272,6 +271,7 @@ void pb::ballset(float dx, float dy)
ball->Direction.X = dx * sensitivity; ball->Direction.X = dx * sensitivity;
ball->Direction.Y = dy * sensitivity; ball->Direction.Y = dy * sensitivity;
ball->Speed = maths::normalize_2d(ball->Direction); ball->Speed = maths::normalize_2d(ball->Direction);
ball->LastActiveTime = time_ticks;
} }
} }
} }
@ -320,158 +320,141 @@ void pb::frame(float dtMilliSec)
void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
{ {
vector2 vec1{}, vec2{};
for (auto ball : MainTable->BallList) for (auto ball : MainTable->BallList)
{ {
if (!ball->ActiveFlag || ball->HasGroupFlag || ball->CollisionComp || ball->Speed >= 0.8f) if (!ball->ActiveFlag || ball->HasGroupFlag || ball->CollisionComp || ball->Speed >= 0.8f)
{ {
if (ball->SomeCounter1 > 0) if (ball->StuckCounter > 0)
{ {
vector2 dxy{ball->Position.X - ball->PrevPosition.X, ball->Position.Y - ball->PrevPosition.Y}; vector2 dist{ball->Position.X - ball->PrevPosition.X, ball->Position.Y - ball->PrevPosition.Y};
auto offsetX2 = ball->Offset * 2.0f; auto radiusX2 = ball->Radius * 2.0f;
if (offsetX2 * offsetX2 < maths::magnitudeSq(dxy)) if (radiusX2 * radiusX2 < maths::magnitudeSq(dist))
ball->SomeCounter1 = 0; ball->StuckCounter = 0;
} }
ball->time_ticks1 = ball->time_ticks2 = time_ticks; ball->LastActiveTime = time_ticks;
} }
else if (time_ticks - ball->time_ticks2 > 500) else if (time_ticks - ball->LastActiveTime > 500)
{ {
vector2 dxy{ball->Position.X - ball->PrevPosition.X, ball->Position.Y - ball->PrevPosition.Y}; vector2 dist{ball->Position.X - ball->PrevPosition.X, ball->Position.Y - ball->PrevPosition.Y};
auto offsetD2 = ball->Offset / 2.0f; auto radiusD2 = ball->Radius / 2.0f;
ball->PrevPosition = ball->Position; ball->PrevPosition = ball->Position;
if (offsetD2 * offsetD2 < maths::magnitudeSq(dxy)) if (radiusD2 * radiusD2 < maths::magnitudeSq(dist))
ball->SomeCounter1 = 0; ball->StuckCounter = 0;
else else
ball->SomeCounter1++; ball->StuckCounter++;
control::BallThrowOrDisable(*ball, time_ticks - ball->time_ticks1); control::UnstuckBall(*ball, time_ticks - ball->LastActiveTime);
} }
} }
int distanceCoefArray[20]{-1}; int ballSteps[20]{-1};
float distanceArray[20]{}, distanceArrayX[20]{}, distanceArrayY[20]{}; float ballStepsDistance[20]{};
int minDistanceCoef = -1; int maxStep = -1;
for (auto index = 0u; index < MainTable->BallList.size(); index++) for (auto index = 0u; index < MainTable->BallList.size(); index++)
{ {
auto ball = MainTable->BallList[index]; auto ball = MainTable->BallList[index];
if (ball->ActiveFlag != 0) if (ball->ActiveFlag != 0)
{ {
vector2 vecDst{};
ball->TimeDelta = timeDelta; ball->TimeDelta = timeDelta;
if (ball->TimeDelta > 0.01f && ball->Speed < 0.8f) if (ball->TimeDelta > 0.01f && ball->Speed < 0.8f)
ball->TimeDelta = 0.01f; ball->TimeDelta = 0.01f;
ball->AsEdgeCollisionFlag = false; ball->AsEdgeCollisionFlag = false;
if (ball->CollisionComp) if (ball->CollisionComp)
{ {
ball->CollisionComp->FieldEffect(ball, &vec1); ball->CollisionComp->FieldEffect(ball, &vecDst);
} }
else else
{ {
if (MainTable->ActiveFlag) TTableLayer::edge_manager->FieldEffects(ball, &vecDst);
{ vecDst.X *= timeDelta;
vec2.X = 0.0; vecDst.Y *= timeDelta;
vec2.Y = 0.0; ball->Direction.X *= ball->Speed;
TTableLayer::edge_manager->FieldEffects(ball, &vec2); ball->Direction.Y *= ball->Speed;
vec2.X = vec2.X * timeDelta; maths::vector_add(ball->Direction, vecDst);
vec2.Y = vec2.Y * timeDelta; ball->Speed = maths::normalize_2d(ball->Direction);
ball->Direction.X = ball->Speed * ball->Direction.X; if (ball->Speed > BallMaxSpeed)
ball->Direction.Y = ball->Speed * ball->Direction.Y; ball->Speed = BallMaxSpeed;
maths::vector_add(ball->Direction, vec2);
ball->Speed = maths::normalize_2d(ball->Direction);
if (ball->Speed > ball_speed_limit)
ball->Speed = ball_speed_limit;
distanceArray[index] = ball->Speed * ball->TimeDelta; ballStepsDistance[index] = ball->Speed * ball->TimeDelta;
auto distanceCoef = static_cast<int>(std::ceil(distanceArray[index] * ball_inv_smth)) - 1; auto ballStep = static_cast<int>(std::ceil(ballStepsDistance[index] / BallHalfRadius)) - 1;
distanceCoefArray[index] = distanceCoef; ballSteps[index] = ballStep;
if (distanceCoef >= 0) if (ballStep > maxStep)
{ maxStep = ballStep;
distanceArrayX[index] = ball->Direction.X * ball_min_smth;
distanceArrayY[index] = ball->Direction.Y * ball_min_smth;
if (distanceCoef > minDistanceCoef)
minDistanceCoef = distanceCoef;
}
}
} }
} }
} }
float deltaAngle[4]{}; float deltaAngle[4]{};
int flipperSteps[4]{};
for (auto index = 0u; index < MainTable->FlipperList.size(); index++) for (auto index = 0u; index < MainTable->FlipperList.size(); index++)
{ {
auto distanceCoef = MainTable->FlipperList[index]->GetFlipperAngleDistance(timeDelta, &deltaAngle[index]) - 1; auto flipStep = MainTable->FlipperList[index]->GetFlipperStepAngle(timeDelta, &deltaAngle[index]) - 1;
distanceArrayY[index] = static_cast<float>(distanceCoef); flipperSteps[index] = flipStep;
if (distanceCoef > minDistanceCoef) if (flipStep > maxStep)
minDistanceCoef = distanceCoef; maxStep = flipStep;
} }
ray_type ray{}; ray_type ray{};
ray.MinDistance = 0.002f; ray.MinDistance = 0.002f;
for (auto index4 = 0; index4 <= minDistanceCoef; index4++) for (auto step = 0; step <= maxStep; step++)
{ {
for (auto index5 = 0u; index5 < MainTable->BallList.size(); index5++) for (auto ballIndex = 0u; ballIndex < MainTable->BallList.size(); ballIndex++)
{ {
auto ball = MainTable->BallList[index5]; auto ball = MainTable->BallList[ballIndex];
if (!ball->AsEdgeCollisionFlag && index4 <= distanceCoefArray[index5]) if (!ball->AsEdgeCollisionFlag && step <= ballSteps[ballIndex])
{ {
float distanceSum = 0.0f;
ray.CollisionMask = ball->CollisionMask; ray.CollisionMask = ball->CollisionMask;
ball->TimeNow = timeNow; ball->TimeNow = timeNow;
if (ball_min_smth > 0.0f)
for (auto distanceSum = 0.0f; distanceSum < BallHalfRadius;)
{ {
while (true) ray.Origin = ball->Position;
ray.Direction = ball->Direction;
if (step >= ballSteps[ballIndex])
{ {
ray.Origin = ball->Position; ray.MaxDistance = ballStepsDistance[ballIndex] - ballSteps[ballIndex] * BallHalfRadius;
ray.Direction = ball->Direction; }
if (index4 >= distanceCoefArray[index5]) else
{ {
ray.MaxDistance = distanceArray[index5] - distanceCoefArray[index5] * ball_min_smth; ray.MaxDistance = BallHalfRadius;
} }
else ray.TimeNow = ball->TimeNow;
{
ray.MaxDistance = ball_min_smth;
}
ray.TimeNow = ball->TimeNow;
TEdgeSegment* edge = nullptr; TEdgeSegment* edge = nullptr;
auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge); auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge);
if (distance > 0.0f) if (distance > 0.0f)
{ {
// Todo: ball to ball collision // Todo: ball to ball collision
//distance = ball_to_ball_collision(); //distance = ball_to_ball_collision();
} }
if (ball->EdgeCollisionResetFlag) if (ball->EdgeCollisionResetFlag)
{ {
ball->EdgeCollisionResetFlag = false; ball->EdgeCollisionResetFlag = false;
} }
else else
{ {
ball->EdgeCollisionCount = 0; ball->EdgeCollisionCount = 0;
ball->EdgeCollisionResetFlag = true; ball->EdgeCollisionResetFlag = true;
} }
if (distance >= 1e9f) if (distance >= 1e9f)
{ {
ball->Position.X += ray.MaxDistance * ray.Direction.X; ball->Position.X += ray.MaxDistance * ray.Direction.X;
ball->Position.Y += ray.MaxDistance * ray.Direction.Y; ball->Position.Y += ray.MaxDistance * ray.Direction.Y;
break;
}
edge->EdgeCollision(ball, distance);
if (distance > 0.0f && !ball->AsEdgeCollisionFlag)
{
distanceSum += distance;
if (distanceSum < ball_min_smth)
continue;
}
break; break;
} }
edge->EdgeCollision(ball, distance);
if (distance <= 0.0f || ball->AsEdgeCollisionFlag)
break;
distanceSum += distance;
} }
} }
} }
for (auto index = 0u; index < MainTable->FlipperList.size(); index++) for (auto flipIndex = 0u; flipIndex < MainTable->FlipperList.size(); flipIndex++)
{ {
if (distanceArrayY[index] >= index4) if (flipperSteps[flipIndex] >= step)
MainTable->FlipperList[index]->FlipperCollision(deltaAngle[index]); MainTable->FlipperList[flipIndex]->FlipperCollision(deltaAngle[flipIndex]);
} }
} }
@ -744,50 +727,6 @@ bool pb::chk_highscore()
return false; return false;
} }
float pb::collide(float timeNow, float timeDelta, TBall* ball)
{
ray_type ray{};
vector2 positionMod{};
if (ball->ActiveFlag && !ball->CollisionComp)
{
if (ball_speed_limit < ball->Speed)
ball->Speed = ball_speed_limit;
auto maxDistance = timeDelta * ball->Speed;
ball->TimeDelta = timeDelta;
ball->RayMaxDistance = maxDistance;
ball->TimeNow = timeNow;
ray.Origin = ball->Position;
ray.Direction = ball->Direction;
ray.MaxDistance = maxDistance;
ray.CollisionMask = ball->CollisionMask;
ray.TimeNow = timeNow;
ray.TimeDelta = timeDelta;
ray.MinDistance = 0.0020000001f;
TEdgeSegment* edge = nullptr;
auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge);
ball->EdgeCollisionCount = 0;
if (distance >= 1000000000.0f)
{
maxDistance = timeDelta * ball->Speed;
ball->RayMaxDistance = maxDistance;
positionMod.X = maxDistance * ball->Direction.X;
positionMod.Y = maxDistance * ball->Direction.Y;
maths::vector_add(ball->Position, positionMod);
}
else
{
edge->EdgeCollision(ball, distance);
if (ball->Speed > 0.000000001f)
return fabs(distance / ball->Speed);
}
}
return timeDelta;
}
void pb::PushCheat(const std::string& cheat) void pb::PushCheat(const std::string& cheat)
{ {
for (auto ch : cheat) for (auto ch : cheat)

View File

@ -43,7 +43,7 @@ class pb
public: public:
static int time_ticks; static int time_ticks;
static float time_now, time_next, time_ticks_remainder; static float time_now, time_next, time_ticks_remainder;
static float ball_speed_limit, ball_min_smth, ball_inv_smth, ball_collision_dist; static float BallMaxSpeed, BallHalfRadius, ball_collision_dist;
static GameModes game_mode; static GameModes game_mode;
static bool cheat_mode; static bool cheat_mode;
static DatFile* record_table; static DatFile* record_table;
@ -74,7 +74,6 @@ public:
static void high_scores(); static void high_scores();
static void tilt_no_more(); static void tilt_no_more();
static bool chk_highscore(); static bool chk_highscore();
static float collide(float timeNow, float timeDelta, TBall* ball);
static void PushCheat(const std::string& cheat); static void PushCheat(const std::string& cheat);
static LPCSTR get_rc_string(Msg uID); static LPCSTR get_rc_string(Msg uID);
static int get_rc_int(Msg uID, int* dst); static int get_rc_int(Msg uID, int* dst);

View File

@ -786,6 +786,7 @@ void winmain::RenderUi()
ShowExitPopup = false; ShowExitPopup = false;
pause(false); pause(false);
ImGui::OpenPopup(exitText); ImGui::OpenPopup(exitText);
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
} }
if (ImGui::BeginPopupModal(exitText, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) if (ImGui::BeginPopupModal(exitText, nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{ {