From 4b86fe2aa7ff399ed25529aa20849e25a3ea6681 Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Sun, 5 Mar 2023 14:16:07 +0300 Subject: [PATCH] FT collision part3: cleanup. --- SpaceCadetPinball/DebugOverlay.cpp | 5 +- SpaceCadetPinball/TBall.cpp | 10 +- SpaceCadetPinball/TBall.h | 6 +- SpaceCadetPinball/TFlipper.cpp | 39 ++--- SpaceCadetPinball/TFlipper.h | 2 +- SpaceCadetPinball/TFlipperEdge.cpp | 19 +-- SpaceCadetPinball/TPinballTable.cpp | 6 +- SpaceCadetPinball/TRamp.cpp | 6 +- SpaceCadetPinball/TSink.cpp | 3 +- SpaceCadetPinball/control.cpp | 4 +- SpaceCadetPinball/control.h | 2 +- SpaceCadetPinball/maths.cpp | 5 + SpaceCadetPinball/maths.h | 2 +- SpaceCadetPinball/pb.cpp | 233 ++++++++++------------------ SpaceCadetPinball/pb.h | 3 +- SpaceCadetPinball/winmain.cpp | 1 + 16 files changed, 144 insertions(+), 202 deletions(-) diff --git a/SpaceCadetPinball/DebugOverlay.cpp b/SpaceCadetPinball/DebugOverlay.cpp index 13cbc2c..cdee9b3 100644 --- a/SpaceCadetPinball/DebugOverlay.cpp +++ b/SpaceCadetPinball/DebugOverlay.cpp @@ -211,7 +211,10 @@ void DebugOverlay::DrawBallInfo() SDL_SetRenderDrawColor(winmain::Renderer, 0, 0, 255, 255); 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(std::round(radI))); auto nextPos = ballPosition; maths::vector_add(nextPos, maths::vector_mul(ball->Direction, ball->Speed / 10.0f)); diff --git a/SpaceCadetPinball/TBall.cpp b/SpaceCadetPinball/TBall.cpp index c10f085..ab440a6 100644 --- a/SpaceCadetPinball/TBall.cpp +++ b/SpaceCadetPinball/TBall.cpp @@ -41,7 +41,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false) 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); for (auto index = 0; index < visualCount; ++index) @@ -53,8 +53,8 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false) VisualZArray[index] = zDepth; } RenderSprite = new render_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr); - PinballTable->CollisionCompOffset = Offset; - Position.Z = Offset; + PinballTable->CollisionCompOffset = Radius; + Position.Z = Radius; GroupIndex = groupIndex; } @@ -65,7 +65,7 @@ void TBall::Repaint() Position.Z = CollisionOffset.X * Position.X + CollisionOffset.Y * Position.Y + - Offset + CollisionOffset.Z; + Radius + CollisionOffset.Z; } auto pos2D = proj::xform_to_2d(Position); @@ -120,7 +120,7 @@ int TBall::Message(MessageCode code, float value) CollisionFlag = 0; CollisionMask = 1; Direction.Y = 0.0; - Position.Z = Offset; + Position.Z = Radius; Direction.X = 0.0; Speed = 0.0; RayMaxDistance = 0.0; diff --git a/SpaceCadetPinball/TBall.h b/SpaceCadetPinball/TBall.h index 528ef7c..19a0c83 100644 --- a/SpaceCadetPinball/TBall.h +++ b/SpaceCadetPinball/TBall.h @@ -32,10 +32,10 @@ public : bool EdgeCollisionResetFlag{}; vector3 CollisionOffset{}; int CollisionFlag; - float Offset; + float Radius; bool HasGroupFlag; - int SomeCounter1 = 0; - int time_ticks1{}, time_ticks2{}; + int StuckCounter = 0; + int LastActiveTime{}; float VisualZArray[50]{}; bool AsEdgeCollisionFlag{}; }; diff --git a/SpaceCadetPinball/TFlipper.cpp b/SpaceCadetPinball/TFlipper.cpp index 15d49e6..063dc05 100644 --- a/SpaceCadetPinball/TFlipper.cpp +++ b/SpaceCadetPinball/TFlipper.cpp @@ -126,19 +126,19 @@ void TFlipper::UpdateSprite() SpriteSet(BmpIndex); } -int TFlipper::GetFlipperAngleDistance(float dt, float* dst) const +int TFlipper::GetFlipperStepAngle(float dt, float* dst) const { if (!MessageField) return 0; auto deltaAngle = FlipperEdge->flipper_angle_delta(dt); - auto distance = std::fabs(std::ceil(FlipperEdge->DistanceDiv * deltaAngle * FlipperEdge->InvT1Radius)); - if (distance > 3.0f) - distance = 3.0f; - if (distance >= 2.0f) + auto step = std::fabs(std::ceil(FlipperEdge->DistanceDiv * deltaAngle * FlipperEdge->InvT1Radius)); + if (step > 3.0f) + step = 3.0f; + if (step >= 2.0f) { - *dst = deltaAngle / distance; - return static_cast(distance); + *dst = deltaAngle / step; + return static_cast(step); } *dst = deltaAngle; @@ -152,7 +152,6 @@ void TFlipper::FlipperCollision(float deltaAngle) ray_type ray{}, rayDst{}; ray.MinDistance = 0.002f; - auto deltaAngleNeg = -deltaAngle; bool collisionFlag = false; for (auto ball : pb::MainTable->BallList) { @@ -167,7 +166,7 @@ void TFlipper::FlipperCollision(float deltaAngle) float sin, cos; auto ballPosRot = ray.Origin; - maths::SinCos(deltaAngleNeg, sin, cos); + maths::SinCos(-deltaAngle, sin, cos); maths::RotatePt(ballPosRot, sin, cos, FlipperEdge->RotOrigin); ray.Direction.X = ballPosRot.X - ray.Origin.X; 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); FlipperEdge->CurrentAngle -= 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 { FlipperEdge->CurrentAngle += 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; } diff --git a/SpaceCadetPinball/TFlipper.h b/SpaceCadetPinball/TFlipper.h index f6a6218..d894bdb 100644 --- a/SpaceCadetPinball/TFlipper.h +++ b/SpaceCadetPinball/TFlipper.h @@ -14,7 +14,7 @@ public: void Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge) override; void UpdateSprite(); - int GetFlipperAngleDistance(float dt, float* dst) const; + int GetFlipperStepAngle(float dt, float* dst) const; void FlipperCollision(float deltaAngle); int BmpIndex; diff --git a/SpaceCadetPinball/TFlipperEdge.cpp b/SpaceCadetPinball/TFlipperEdge.cpp index 9545e7b..1f5c18c 100644 --- a/SpaceCadetPinball/TFlipperEdge.cpp +++ b/SpaceCadetPinball/TFlipperEdge.cpp @@ -133,23 +133,24 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float distance) return; } - auto someProduct = (NextBallPosition.Y - T1.Y) * (RotOrigin.X - T1.X) - - (NextBallPosition.X - T1.X) * (RotOrigin.Y - T1.Y); + vector2 t1NextPos{NextBallPosition.X - T1.X, NextBallPosition.Y - T1.Y}, + t1RotOrigin{RotOrigin.X - T1.X, RotOrigin.Y - T1.Y}; + auto crossProduct = maths::cross(t1RotOrigin, t1NextPos); - bool someFlag = false; - if (someProduct <= 0) + bool frontCollision = false; + if (crossProduct <= 0) { if (AngleMax > 0) - someFlag = true; + frontCollision = true; } else if (AngleMax <= 0) { - someFlag = true; + frontCollision = true; } if (FlipperFlag == MessageCode::TFlipperRetract) { - someFlag ^= true; + frontCollision ^= true; CollisionLinePerp = LineB.PerpendicularC; } else @@ -160,7 +161,7 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float distance) auto dx = NextBallPosition.X - RotOrigin.X; auto dy = NextBallPosition.Y - RotOrigin.Y; auto distanceSq = dy * dy + dx * dx; - if (someFlag) + if (frontCollision) { float boost = 0; 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); - auto offset = 1.0f / InvT1Radius + pb::ball_min_smth; + auto offset = 1.0f / InvT1Radius + pb::BallHalfRadius; XMin = xMin - offset; YMin = yMin - offset; XMax = xMax + offset; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 5b494ea..28c73b4 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -611,7 +611,7 @@ TBall* TPinballTable::AddBall(float x, float y) if (ball != nullptr) { ball->ActiveFlag = 1; - ball->Position.Z = ball->Offset; + ball->Position.Z = ball->Radius; ball->Direction = {}; ball->Speed = 0; ball->TimeDelta = 0; @@ -632,8 +632,8 @@ TBall* TPinballTable::AddBall(float x, float y) ball->Position.X = x; ball->Position.Y = y; ball->PrevPosition = ball->Position; - ball->SomeCounter1 = 0; - ball->time_ticks1 = ball->time_ticks2 = pb::time_ticks; + ball->StuckCounter = 0; + ball->LastActiveTime = pb::time_ticks; return ball; } diff --git a/SpaceCadetPinball/TRamp.cpp b/SpaceCadetPinball/TRamp.cpp index fc5adad..795235d 100644 --- a/SpaceCadetPinball/TRamp.cpp +++ b/SpaceCadetPinball/TRamp.cpp @@ -144,7 +144,7 @@ void TRamp::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl ball->RampFieldForce.X = plane->FieldForce.X; ball->RampFieldForce.Y = plane->FieldForce.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; return; } @@ -164,13 +164,13 @@ void TRamp::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl { ball->CollisionMask = Wall1CollisionGroup; if (BallZOffsetFlag) - ball->Position.Z = ball->Offset + Wall1BallOffset; + ball->Position.Z = ball->Radius + Wall1BallOffset; } else { ball->CollisionMask = Wall2CollisionGroup; if (BallZOffsetFlag) - ball->Position.Z = ball->Offset + Wall2BallOffset; + ball->Position.Z = ball->Radius + Wall2BallOffset; } } } diff --git a/SpaceCadetPinball/TSink.cpp b/SpaceCadetPinball/TSink.cpp index 295906b..244896b 100644 --- a/SpaceCadetPinball/TSink.cpp +++ b/SpaceCadetPinball/TSink.cpp @@ -7,6 +7,7 @@ #include "render.h" #include "TPinballTable.h" #include "TBall.h" +#include "TDrain.h" #include "timer.h" 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) { - maths::basic_collision(ball, nextPosition, direction, Elasticity, Smoothness, 1000000000.0, 0.0); + PinballTable->Drain->Collision(ball, nextPosition, direction, distance, edge); } else { diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index b9f5d94..72b1dfc 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -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) && !CheckBallInControlBounds(ball, *flip2) && !CheckBallInControlBounds(ball, *plunger)) { - if (ball.SomeCounter1 <= 20) + if (ball.StuckCounter <= 20) { vector3 throwDir{0.0f, -1.0f, 0.0f}; ball.throw_ball(&throwDir, 90.0f, 1.0f, 0.0f); diff --git a/SpaceCadetPinball/control.h b/SpaceCadetPinball/control.h index 3d2bd3c..c64811c 100644 --- a/SpaceCadetPinball/control.h +++ b/SpaceCadetPinball/control.h @@ -89,7 +89,7 @@ public: static void table_set_multiball(float time); static void table_bump_ball_sink_lock(); 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 void cheat_bump_rank(); static int SpecialAddScore(int score); diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 708f34d..2c3107c 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -222,6 +222,11 @@ float maths::magnitudeSq(const vector2& vec) 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) { vec1Dst.X += vec2.X; diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index f230eeb..420777b 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -53,7 +53,6 @@ struct ray_type float MaxDistance; float MinDistance; float TimeNow; - float TimeDelta; int CollisionMask; }; @@ -115,6 +114,7 @@ public: static float cross(const vector2& vec1, const vector2& vec2); static float magnitude(const vector3& vec); static float magnitudeSq(const vector2& vec); + static int magnitudeSq(const vector2i& vec); static void vector_add(vector2& vec1Dst, const vector2& vec2); static vector2 vector_sub(const vector2& vec1, const vector2& vec2); static vector3 vector_sub(const vector3& vec1, const vector3& vec2); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index e199da7..7288e12 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -33,7 +33,7 @@ DatFile* pb::record_table = nullptr; int pb::time_ticks = 0; GameModes pb::game_mode = GameModes::GameOver; 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; std::string pb::DatFileName, pb::BasePath; ImU32 pb::TextBoxColor; @@ -104,10 +104,9 @@ int pb::init() high_score::read(); auto ball = MainTable->BallList.at(0); - ball_speed_limit = ball->Offset * 200.0f; - ball_min_smth = ball->Offset * 0.5f; - ball_inv_smth = 1.0f / ball_min_smth; - ball_collision_dist = (ball->Offset + ball_min_smth) * 2.0f; + BallMaxSpeed = ball->Radius * 200.0f; + BallHalfRadius = ball->Radius * 0.5f; + ball_collision_dist = (ball->Radius + BallHalfRadius) * 2.0f; int red = 255, green = 255, blue = 255; 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.Y = dy * sensitivity; 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) { - vector2 vec1{}, vec2{}; - for (auto ball : MainTable->BallList) { 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}; - auto offsetX2 = ball->Offset * 2.0f; - if (offsetX2 * offsetX2 < maths::magnitudeSq(dxy)) - ball->SomeCounter1 = 0; + vector2 dist{ball->Position.X - ball->PrevPosition.X, ball->Position.Y - ball->PrevPosition.Y}; + auto radiusX2 = ball->Radius * 2.0f; + if (radiusX2 * radiusX2 < maths::magnitudeSq(dist)) + 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}; - auto offsetD2 = ball->Offset / 2.0f; + vector2 dist{ball->Position.X - ball->PrevPosition.X, ball->Position.Y - ball->PrevPosition.Y}; + auto radiusD2 = ball->Radius / 2.0f; ball->PrevPosition = ball->Position; - if (offsetD2 * offsetD2 < maths::magnitudeSq(dxy)) - ball->SomeCounter1 = 0; + if (radiusD2 * radiusD2 < maths::magnitudeSq(dist)) + ball->StuckCounter = 0; else - ball->SomeCounter1++; - control::BallThrowOrDisable(*ball, time_ticks - ball->time_ticks1); + ball->StuckCounter++; + control::UnstuckBall(*ball, time_ticks - ball->LastActiveTime); } } - int distanceCoefArray[20]{-1}; - float distanceArray[20]{}, distanceArrayX[20]{}, distanceArrayY[20]{}; - int minDistanceCoef = -1; + int ballSteps[20]{-1}; + float ballStepsDistance[20]{}; + int maxStep = -1; for (auto index = 0u; index < MainTable->BallList.size(); index++) { auto ball = MainTable->BallList[index]; if (ball->ActiveFlag != 0) { + vector2 vecDst{}; ball->TimeDelta = timeDelta; if (ball->TimeDelta > 0.01f && ball->Speed < 0.8f) ball->TimeDelta = 0.01f; ball->AsEdgeCollisionFlag = false; if (ball->CollisionComp) { - ball->CollisionComp->FieldEffect(ball, &vec1); + ball->CollisionComp->FieldEffect(ball, &vecDst); } else { - if (MainTable->ActiveFlag) - { - vec2.X = 0.0; - vec2.Y = 0.0; - TTableLayer::edge_manager->FieldEffects(ball, &vec2); - vec2.X = vec2.X * timeDelta; - vec2.Y = vec2.Y * timeDelta; - ball->Direction.X = ball->Speed * ball->Direction.X; - ball->Direction.Y = ball->Speed * ball->Direction.Y; - maths::vector_add(ball->Direction, vec2); - ball->Speed = maths::normalize_2d(ball->Direction); - if (ball->Speed > ball_speed_limit) - ball->Speed = ball_speed_limit; + TTableLayer::edge_manager->FieldEffects(ball, &vecDst); + vecDst.X *= timeDelta; + vecDst.Y *= timeDelta; + ball->Direction.X *= ball->Speed; + ball->Direction.Y *= ball->Speed; + maths::vector_add(ball->Direction, vecDst); + ball->Speed = maths::normalize_2d(ball->Direction); + if (ball->Speed > BallMaxSpeed) + ball->Speed = BallMaxSpeed; - distanceArray[index] = ball->Speed * ball->TimeDelta; - auto distanceCoef = static_cast(std::ceil(distanceArray[index] * ball_inv_smth)) - 1; - distanceCoefArray[index] = distanceCoef; - if (distanceCoef >= 0) - { - distanceArrayX[index] = ball->Direction.X * ball_min_smth; - distanceArrayY[index] = ball->Direction.Y * ball_min_smth; - if (distanceCoef > minDistanceCoef) - minDistanceCoef = distanceCoef; - } - } + ballStepsDistance[index] = ball->Speed * ball->TimeDelta; + auto ballStep = static_cast(std::ceil(ballStepsDistance[index] / BallHalfRadius)) - 1; + ballSteps[index] = ballStep; + if (ballStep > maxStep) + maxStep = ballStep; } } } float deltaAngle[4]{}; + int flipperSteps[4]{}; for (auto index = 0u; index < MainTable->FlipperList.size(); index++) { - auto distanceCoef = MainTable->FlipperList[index]->GetFlipperAngleDistance(timeDelta, &deltaAngle[index]) - 1; - distanceArrayY[index] = static_cast(distanceCoef); - if (distanceCoef > minDistanceCoef) - minDistanceCoef = distanceCoef; + auto flipStep = MainTable->FlipperList[index]->GetFlipperStepAngle(timeDelta, &deltaAngle[index]) - 1; + flipperSteps[index] = flipStep; + if (flipStep > maxStep) + maxStep = flipStep; } ray_type ray{}; 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]; - if (!ball->AsEdgeCollisionFlag && index4 <= distanceCoefArray[index5]) + auto ball = MainTable->BallList[ballIndex]; + if (!ball->AsEdgeCollisionFlag && step <= ballSteps[ballIndex]) { - float distanceSum = 0.0f; ray.CollisionMask = ball->CollisionMask; 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.Direction = ball->Direction; - if (index4 >= distanceCoefArray[index5]) - { - ray.MaxDistance = distanceArray[index5] - distanceCoefArray[index5] * ball_min_smth; - } - else - { - ray.MaxDistance = ball_min_smth; - } - ray.TimeNow = ball->TimeNow; + ray.MaxDistance = ballStepsDistance[ballIndex] - ballSteps[ballIndex] * BallHalfRadius; + } + else + { + ray.MaxDistance = BallHalfRadius; + } + ray.TimeNow = ball->TimeNow; - TEdgeSegment* edge = nullptr; - auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge); - if (distance > 0.0f) - { - // Todo: ball to ball collision - //distance = ball_to_ball_collision(); - } - if (ball->EdgeCollisionResetFlag) - { - ball->EdgeCollisionResetFlag = false; - } - else - { - ball->EdgeCollisionCount = 0; - ball->EdgeCollisionResetFlag = true; - } - if (distance >= 1e9f) - { - ball->Position.X += ray.MaxDistance * ray.Direction.X; - 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; - } + TEdgeSegment* edge = nullptr; + auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge); + if (distance > 0.0f) + { + // Todo: ball to ball collision + //distance = ball_to_ball_collision(); + } + if (ball->EdgeCollisionResetFlag) + { + ball->EdgeCollisionResetFlag = false; + } + else + { + ball->EdgeCollisionCount = 0; + ball->EdgeCollisionResetFlag = true; + } + if (distance >= 1e9f) + { + ball->Position.X += ray.MaxDistance * ray.Direction.X; + ball->Position.Y += ray.MaxDistance * ray.Direction.Y; 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) - MainTable->FlipperList[index]->FlipperCollision(deltaAngle[index]); + if (flipperSteps[flipIndex] >= step) + MainTable->FlipperList[flipIndex]->FlipperCollision(deltaAngle[flipIndex]); } } @@ -744,50 +727,6 @@ bool pb::chk_highscore() 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) { for (auto ch : cheat) diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index c1bc8ff..3e79e56 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -43,7 +43,7 @@ class pb public: static int time_ticks; 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 bool cheat_mode; static DatFile* record_table; @@ -74,7 +74,6 @@ public: static void high_scores(); static void tilt_no_more(); static bool chk_highscore(); - static float collide(float timeNow, float timeDelta, TBall* ball); static void PushCheat(const std::string& cheat); static LPCSTR get_rc_string(Msg uID); static int get_rc_int(Msg uID, int* dst); diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index a253d71..5113065 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -786,6 +786,7 @@ void winmain::RenderUi() ShowExitPopup = false; pause(false); ImGui::OpenPopup(exitText); + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); } if (ImGui::BeginPopupModal(exitText, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {