From e0424bed651c5c2aaead9dadad6be8958ac8bd9a Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Mon, 13 Mar 2023 08:25:49 +0300 Subject: [PATCH] FT collision part5: cleanup. --- SpaceCadetPinball/TBall.cpp | 44 +++++++++++++---------------- SpaceCadetPinball/TBall.h | 4 +-- SpaceCadetPinball/TEdgeManager.cpp | 4 +-- SpaceCadetPinball/THole.cpp | 35 ++++++++++------------- SpaceCadetPinball/THole.h | 4 +-- SpaceCadetPinball/TKickout.cpp | 2 +- SpaceCadetPinball/TPinballTable.cpp | 8 +++--- SpaceCadetPinball/TPinballTable.h | 7 ++--- SpaceCadetPinball/TPlunger.cpp | 14 +++------ SpaceCadetPinball/TSink.cpp | 13 ++------- SpaceCadetPinball/pb.cpp | 15 +++++----- 11 files changed, 62 insertions(+), 88 deletions(-) diff --git a/SpaceCadetPinball/TBall.cpp b/SpaceCadetPinball/TBall.cpp index 9c9493f..bfe6750 100644 --- a/SpaceCadetPinball/TBall.cpp +++ b/SpaceCadetPinball/TBall.cpp @@ -108,11 +108,11 @@ void TBall::not_again(TEdgeSegment* edge) EdgeCollisionResetFlag = true; } -bool TBall::already_hit(TEdgeSegment* edge) +bool TBall::already_hit(const TEdgeSegment& edge) const { for (int i = 0; i < EdgeCollisionCount; i++) { - if (Collisions[i] == edge) + if (Collisions[i] == &edge) return true; } @@ -152,35 +152,29 @@ void TBall::throw_ball(vector3* direction, float angleMult, float speedMult1, fl void TBall::EdgeCollision(TBall* ball, float distance) { - ball->AsEdgeCollisionFlag = true; - vector2 nextPos{ - ball->Position.X + ball->Direction.X * distance, - ball->Position.Y + ball->Direction.Y * distance - }, - collDir{nextPos.X - Position.X, nextPos.Y - Position.Y}; - maths::normalize_2d(collDir); - vector2 invCollDir{ -collDir.X, -collDir.Y }; - - ball->Position.X = nextPos.X; - ball->Position.Y = nextPos.Y; + ball->CollisionDisabledFlag = true; + ball->Position.X += ball->Direction.X * distance; + ball->Position.Y += ball->Direction.Y * distance; ball->Direction.X *= ball->Speed; ball->Direction.Y *= ball->Speed; Direction.X *= Speed; Direction.Y *= Speed; - auto coef = -maths::DotProduct(ball->Direction, collDir); - vector2 v44{collDir.X * coef, collDir.Y * coef}; - vector2 v13{ball->Direction.X + v44.X, ball->Direction.Y + v44.Y}; - - coef = -maths::DotProduct(Direction, invCollDir); - vector2 v11{invCollDir.X * coef, invCollDir.Y * coef}; - vector2 v10{Direction.X + v11.X, Direction.Y + v11.Y}; + // AB - vector from ball to this, BA - from this to ball; collision direction + vector2 AB{ball->Position.X - Position.X, ball->Position.Y - Position.Y}; + maths::normalize_2d(AB); + vector2 BA{-AB.X, -AB.Y}; - ball->Direction.X = -v11.X + v13.X; - ball->Direction.Y = -v11.Y + v13.Y; + // Projection = difference between ball directions and collision direction + auto projAB = -maths::DotProduct(ball->Direction, AB); + auto projBA = -maths::DotProduct(Direction, BA); + vector2 delta{AB.X * projAB - BA.X * projBA, AB.Y * projAB - BA.Y * projBA}; + + ball->Direction.X += delta.X; + ball->Direction.Y += delta.Y; ball->Speed = maths::normalize_2d(ball->Direction); - Direction.X = -v44.X + v10.X; - Direction.Y = -v44.Y + v10.Y; + Direction.X -= delta.X; + Direction.Y -= delta.Y; Speed = maths::normalize_2d(Direction); } @@ -199,6 +193,6 @@ vector2 TBall::get_coordinates() void TBall::Disable() { ActiveFlag = false; - AsEdgeCollisionFlag = true; + CollisionDisabledFlag = true; SpriteSet(-1); } diff --git a/SpaceCadetPinball/TBall.h b/SpaceCadetPinball/TBall.h index 724cf49..e15f213 100644 --- a/SpaceCadetPinball/TBall.h +++ b/SpaceCadetPinball/TBall.h @@ -9,7 +9,7 @@ public : TBall(TPinballTable* table, int groupIndex); void Repaint(); void not_again(TEdgeSegment* edge); - bool already_hit(TEdgeSegment* edge); + bool already_hit(const TEdgeSegment& edge) const; int Message(MessageCode code, float value) override; vector2 get_coordinates() override; void Disable(); @@ -38,5 +38,5 @@ public : int StuckCounter = 0; int LastActiveTime{}; float VisualZArray[50]{}; - bool AsEdgeCollisionFlag{}; + bool CollisionDisabledFlag{}; }; diff --git a/SpaceCadetPinball/TEdgeManager.cpp b/SpaceCadetPinball/TEdgeManager.cpp index 70e5fb7..febce13 100644 --- a/SpaceCadetPinball/TEdgeManager.cpp +++ b/SpaceCadetPinball/TEdgeManager.cpp @@ -76,9 +76,9 @@ int TEdgeManager::TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeD for (auto it = edgeBox->EdgeList.rbegin(); it != edgeBox->EdgeList.rend(); ++it) { auto edge = *it; - if (!edge->ProcessedFlag && *edge->ActiveFlagPtr && (edge->CollisionGroup & ray->CollisionMask)) + if (!edge->ProcessedFlag && *edge->ActiveFlagPtr && (edge->CollisionGroup & ray->CollisionMask) != 0) { - if (!ball->already_hit(edge)) + if (!ball->already_hit(*edge)) { ++edgeIndex; *edgePtr = edge; diff --git a/SpaceCadetPinball/THole.cpp b/SpaceCadetPinball/THole.cpp index 2db2af5..4c930ff 100644 --- a/SpaceCadetPinball/THole.cpp +++ b/SpaceCadetPinball/THole.cpp @@ -18,7 +18,7 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table, Unknown4 = 0.050000001f; MessageField = 0; Timer = 0; - BallCapturedFlag = 0; + BallCapturedFlag = false; Unknown3 = loader::query_float_attribute(groupIndex, 0, 407, 0.25f); GravityMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f); GravityPull = *loader::query_float_attribute(groupIndex, 0, 305); @@ -33,18 +33,15 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table, auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup, reinterpret_cast(visual.FloatArr), Circle.RadiusSq); - if (tCircle) - { - tCircle->place_in_grid(&AABB); - EdgeList.push_back(tCircle); - } + tCircle->place_in_grid(&AABB); + EdgeList.push_back(tCircle); ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2]; CollisionMask = static_cast(floor(*loader::query_float_attribute(groupIndex, 0, 1304))); - // Full tilt hack - CollisionMask should be 1 + // CollisionMask difference: 3DPB - value given as is, FT: mask = 1 << value if (pb::FullTiltMode) - CollisionMask = 1; + CollisionMask = 1 << CollisionMask; Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2]; circle.RadiusSq = Circle.RadiusSq; @@ -64,7 +61,7 @@ int THole::Message(MessageCode code, float value) if (Timer) timer::kill(Timer); Timer = 0; - BallCapturedSecondStage = 1; + BallCapturedSecondStage = true; } return 0; } @@ -73,14 +70,14 @@ void THole::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl { if (!BallCapturedFlag) { - BallCapturedSecondStage = 0; - Threshold = 1000000000.0; - BallCapturedFlag = 1; + BallCapturedSecondStage = false; + Threshold = 1e9f; + BallCapturedFlag = true; ball->CollisionComp = this; ball->Position.X = Circle.Center.X; ball->Position.Y = Circle.Center.Y; ball->Direction.Z = 0.0; - ball->AsEdgeCollisionFlag = true; + ball->CollisionDisabledFlag = true; // Ramp hole has no delay in FT. auto captureTime = pb::FullTiltMode ? 0 : 0.5f; @@ -111,15 +108,13 @@ int THole::FieldEffect(TBall* ball, vector2* vecDst) ball->Position.Z += ball->Direction.Z; if (ball->Position.Z <= ZSetValue) { - BallCapturedFlag = 0; - BallCapturedSecondStage = 0; + BallCapturedFlag = false; + BallCapturedSecondStage = false; ball->Position.Z = ZSetValue; - ball->Direction.Z = 0.0; ball->CollisionMask = CollisionMask; - ball->Direction.Y = 0.0; ball->CollisionComp = nullptr; - ball->Direction.X = 0.0; - ball->Speed = 0.0; + ball->Direction = {}; + ball->Speed = 0.0f; loader::play_sound(SoftHitSoundId, ball, "THole2"); control::handler(MessageCode::ControlBallReleased, this); } @@ -149,5 +144,5 @@ void THole::TimerExpired(int timerId, void* caller) { auto hole = static_cast(caller); hole->Timer = 0; - hole->BallCapturedSecondStage = 1; + hole->BallCapturedSecondStage = true; } diff --git a/SpaceCadetPinball/THole.h b/SpaceCadetPinball/THole.h index b05dc4e..0f616ed 100644 --- a/SpaceCadetPinball/THole.h +++ b/SpaceCadetPinball/THole.h @@ -15,8 +15,8 @@ public: static void TimerExpired(int timerId, void* caller); - int BallCapturedFlag; - int BallCapturedSecondStage{}; + bool BallCapturedFlag{}; + bool BallCapturedSecondStage{}; int Timer; float Unknown3; float Unknown4; diff --git a/SpaceCadetPinball/TKickout.cpp b/SpaceCadetPinball/TKickout.cpp index 73fba06..dd31ce3 100644 --- a/SpaceCadetPinball/TKickout.cpp +++ b/SpaceCadetPinball/TKickout.cpp @@ -105,7 +105,7 @@ void TKickout::Collision(TBall* ball, vector2* nextPosition, vector2* direction, ball->Position.Y = Circle.Center.Y; OriginalBallZ = ball->Position.Z; ball->Position.Z = CollisionBallSetZ; - ball->AsEdgeCollisionFlag = true; + ball->CollisionDisabledFlag = true; if (PinballTable->TiltLockFlag) { Message(MessageCode::TKickoutRestartTimer, 0.1f); diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 58c1416..f82d6ef 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -59,7 +59,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false) MultiballFlag = false; PlayerCount = 0; - auto ball = AddBall(0.0f, 0.0f); + auto ball = AddBall({0.0f, 0.0f}); ball->Disable(); new TTableLayer(this); @@ -595,7 +595,7 @@ int TPinballTable::Message(MessageCode code, float value) return 0; } -TBall* TPinballTable::AddBall(float x, float y) +TBall* TPinballTable::AddBall(vector2 position) { TBall* ball = nullptr; @@ -629,8 +629,8 @@ TBall* TPinballTable::AddBall(float x, float y) BallList.push_back(ball); } - ball->Position.X = x; - ball->Position.Y = y; + ball->Position.X = position.X; + ball->Position.Y = position.Y; ball->PrevPosition = ball->Position; ball->StuckCounter = 0; ball->LastActiveTime = pb::time_ticks; diff --git a/SpaceCadetPinball/TPinballTable.h b/SpaceCadetPinball/TPinballTable.h index 22e76ef..a6d73ed 100644 --- a/SpaceCadetPinball/TPinballTable.h +++ b/SpaceCadetPinball/TPinballTable.h @@ -1,5 +1,6 @@ #pragma once +#include "maths.h" #include "TPinballComponent.h" class TBall; @@ -9,7 +10,6 @@ class TPlunger; class TDrain; class TDemo; class TLightGroup; -struct RectF; struct score_struct_super { @@ -35,7 +35,7 @@ public: void tilt(float time); void port_draw() override; int Message(MessageCode code, float value) override; - TBall* AddBall(float x, float y); + TBall* AddBall(vector2 position); int BallCountInRect(const RectF& rect); int BallCountInRect(const vector2& pos, float margin); @@ -77,8 +77,7 @@ public: float GravityAngleX{}; float GravityAnglY{}; float CollisionCompOffset{}; - float PlungerPositionX{}; - float PlungerPositionY{}; + vector2 PlungerPosition{}; int ScoreMultiplier{}; int ScoreAdded{}; int ScoreSpecial1{}; diff --git a/SpaceCadetPinball/TPlunger.cpp b/SpaceCadetPinball/TPlunger.cpp index e00d051..54d6836 100644 --- a/SpaceCadetPinball/TPlunger.cpp +++ b/SpaceCadetPinball/TPlunger.cpp @@ -35,8 +35,7 @@ TPlunger::TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(t PullbackIncrement = MaxPullback / (ListBitmap->size() * 8.0f); PullbackDelay = 0.025f; float* floatArr = loader::query_float_attribute(groupIndex, 0, 601); - table->PlungerPositionX = floatArr[0]; - table->PlungerPositionY = floatArr[1]; + table->PlungerPosition = {floatArr[0], floatArr[1]}; } void TPlunger::Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge) @@ -72,18 +71,13 @@ int TPlunger::Message(MessageCode code, float value) break; case MessageCode::PlungerFeedBall: { - RectF rect{}; - rect.XMin = PinballTable->CollisionCompOffset * -1.2f + PinballTable->PlungerPositionX; - rect.XMax = PinballTable->CollisionCompOffset * 1.2f + PinballTable->PlungerPositionX; - rect.YMin = PinballTable->CollisionCompOffset * -1.2f + PinballTable->PlungerPositionY; - rect.YMax = PinballTable->CollisionCompOffset * 1.2f + PinballTable->PlungerPositionY; - if(PinballTable->BallCountInRect(rect)) + if (PinballTable->BallCountInRect(PinballTable->PlungerPosition, PinballTable->CollisionCompOffset * 1.2f)) { timer::set(1.0f, this, BallFeedTimer); } - else + else { - auto ball = PinballTable->AddBall(PinballTable->PlungerPositionX, PinballTable->PlungerPositionY); + auto ball = PinballTable->AddBall(PinballTable->PlungerPosition); assertm(ball, "Failure to create ball in plunger"); PinballTable->MultiballCount++; PinballTable->BallInDrainFlag = 0; diff --git a/SpaceCadetPinball/TSink.cpp b/SpaceCadetPinball/TSink.cpp index 244896b..54539bb 100644 --- a/SpaceCadetPinball/TSink.cpp +++ b/SpaceCadetPinball/TSink.cpp @@ -72,24 +72,17 @@ void TSink::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl void TSink::TimerExpired(int timerId, void* caller) { - RectF rect{}; - auto sink = static_cast(caller); auto table = sink->PinballTable; - - rect.XMin = table->CollisionCompOffset * -2.0f + sink->BallPosition.X; - rect.XMax = table->CollisionCompOffset * 2.0f + sink->BallPosition.X; - rect.YMin = table->CollisionCompOffset * -2.0f + sink->BallPosition.Y; - rect.YMax = table->CollisionCompOffset * 2.0f + sink->BallPosition.Y; - if (table->BallCountInRect(rect)) + if (table->BallCountInRect(sink->BallPosition, table->CollisionCompOffset * 2.0f)) { timer::set(0.5f, sink, TimerExpired); } else { - auto ball = table->AddBall(sink->BallPosition.X, sink->BallPosition.Y); + auto ball = table->AddBall(sink->BallPosition); assertm(ball, "Failure to create ball in sink"); - ball->AsEdgeCollisionFlag = true; + ball->CollisionDisabledFlag = true; ball->throw_ball(&sink->BallThrowDirection, sink->ThrowAngleMult, sink->ThrowSpeedMult1, sink->ThrowSpeedMult2); if (sink->SoundIndex3) diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index de33a59..b09ac34 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -358,7 +358,7 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) ball->TimeDelta = timeDelta; if (ball->TimeDelta > 0.01f && ball->Speed < 0.8f) ball->TimeDelta = 0.01f; - ball->AsEdgeCollisionFlag = false; + ball->CollisionDisabledFlag = false; if (ball->CollisionComp) { ball->CollisionComp->FieldEffect(ball, &vecDst); @@ -401,7 +401,7 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) for (auto ballIndex = 0u; ballIndex < MainTable->BallList.size(); ballIndex++) { auto ball = MainTable->BallList[ballIndex]; - if (!ball->AsEdgeCollisionFlag && step <= ballSteps[ballIndex]) + if (!ball->CollisionDisabledFlag && step <= ballSteps[ballIndex]) { ray.CollisionMask = ball->CollisionMask; ball->TimeNow = timeNow; @@ -443,7 +443,7 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) } edge->EdgeCollision(ball, distance); - if (distance <= 0.0f || ball->AsEdgeCollisionFlag) + if (distance <= 0.0f || ball->CollisionDisabledFlag) break; distanceSum += distance; } @@ -606,8 +606,7 @@ void pb::InputDown(GameInput input) case 'b': { vector2 pos{6.0f, 7.0f}; - if (!MainTable->BallCountInRect(pos, MainTable->CollisionCompOffset * 1.2f) && MainTable->AddBall( - pos.X, pos.Y)) + if (!MainTable->BallCountInRect(pos, MainTable->CollisionCompOffset * 1.2f) && MainTable->AddBall(pos)) MainTable->MultiballCount++; break; } @@ -760,9 +759,9 @@ void pb::ShowMessageBox(Uint32 flags, LPCSTR title, LPCSTR message) float pb::BallToBallCollision(const ray_type& ray, const TBall& ball, TEdgeSegment** edge, float collisionDistance) { - for (auto curBall : MainTable->BallList) + for (const auto curBall : MainTable->BallList) { - if (curBall->ActiveFlagPtr && curBall != &ball && (curBall->CollisionMask & ball.CollisionMask) != 0 && + if (curBall->ActiveFlag && curBall != &ball && (curBall->CollisionMask & ball.CollisionMask) != 0 && std::abs(curBall->Position.X - ball.Position.X) < BallToBallCollisionDistance && std::abs(curBall->Position.Y - ball.Position.Y) < BallToBallCollisionDistance) { @@ -770,7 +769,7 @@ float pb::BallToBallCollision(const ray_type& ray, const TBall& ball, TEdgeSegme if (distance < 1e9f) { distance = std::max(0.0f, distance - 0.002f); - if (collisionDistance > distance) + if (distance < collisionDistance) { collisionDistance = distance; *edge = curBall;