1
0
Fork 0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-23 17:30:18 +01:00

Compare commits

..

No commits in common. "43e2ab896b90ef09526080790b71ea337e0083b5" and "c5acdcd5246a7dbd7ad1fc065c16333856c5823d" have entirely different histories.

15 changed files with 110 additions and 76 deletions

View file

@ -17,6 +17,7 @@ TBall::TBall(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
visualStruct visual{}; visualStruct visual{};
char ballGroupName[10]{"ball"}; char ballGroupName[10]{"ball"};
TimeNow = 0.0;
RayMaxDistance = 0.0; RayMaxDistance = 0.0;
ActiveFlag = 1; ActiveFlag = 1;
CollisionComp = nullptr; CollisionComp = nullptr;
@ -107,11 +108,11 @@ void TBall::not_again(TEdgeSegment* edge)
EdgeCollisionResetFlag = true; EdgeCollisionResetFlag = true;
} }
bool TBall::already_hit(const TEdgeSegment& edge) const bool TBall::already_hit(TEdgeSegment* edge)
{ {
for (int i = 0; i < EdgeCollisionCount; i++) for (int i = 0; i < EdgeCollisionCount; i++)
{ {
if (Collisions[i] == &edge) if (Collisions[i] == edge)
return true; return true;
} }
@ -151,29 +152,35 @@ void TBall::throw_ball(vector3* direction, float angleMult, float speedMult1, fl
void TBall::EdgeCollision(TBall* ball, float distance) void TBall::EdgeCollision(TBall* ball, float distance)
{ {
ball->CollisionDisabledFlag = true; ball->AsEdgeCollisionFlag = true;
ball->Position.X += ball->Direction.X * distance; vector2 nextPos{
ball->Position.Y += ball->Direction.Y * distance; 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->Direction.X *= ball->Speed; ball->Direction.X *= ball->Speed;
ball->Direction.Y *= ball->Speed; ball->Direction.Y *= ball->Speed;
Direction.X *= Speed; Direction.X *= Speed;
Direction.Y *= Speed; Direction.Y *= Speed;
// AB - vector from ball to this, BA - from this to ball; collision direction auto coef = -maths::DotProduct(ball->Direction, collDir);
vector2 AB{ball->Position.X - Position.X, ball->Position.Y - Position.Y}; vector2 v44{collDir.X * coef, collDir.Y * coef};
maths::normalize_2d(AB); vector2 v13{ball->Direction.X + v44.X, ball->Direction.Y + v44.Y};
vector2 BA{-AB.X, -AB.Y};
// Projection = difference between ball directions and collision direction coef = -maths::DotProduct(Direction, invCollDir);
auto projAB = -maths::DotProduct(ball->Direction, AB); vector2 v11{invCollDir.X * coef, invCollDir.Y * coef};
auto projBA = -maths::DotProduct(Direction, BA); vector2 v10{Direction.X + v11.X, Direction.Y + v11.Y};
vector2 delta{AB.X * projAB - BA.X * projBA, AB.Y * projAB - BA.Y * projBA};
ball->Direction.X += delta.X; ball->Direction.X = -v11.X + v13.X;
ball->Direction.Y += delta.Y; ball->Direction.Y = -v11.Y + v13.Y;
ball->Speed = maths::normalize_2d(ball->Direction); ball->Speed = maths::normalize_2d(ball->Direction);
Direction.X -= delta.X; Direction.X = -v44.X + v10.X;
Direction.Y -= delta.Y; Direction.Y = -v44.Y + v10.Y;
Speed = maths::normalize_2d(Direction); Speed = maths::normalize_2d(Direction);
} }
@ -192,6 +199,6 @@ vector2 TBall::get_coordinates()
void TBall::Disable() void TBall::Disable()
{ {
ActiveFlag = false; ActiveFlag = false;
CollisionDisabledFlag = true; AsEdgeCollisionFlag = true;
SpriteSet(-1); SpriteSet(-1);
} }

View file

@ -9,7 +9,7 @@ public :
TBall(TPinballTable* table, int groupIndex); TBall(TPinballTable* table, int groupIndex);
void Repaint(); void Repaint();
void not_again(TEdgeSegment* edge); void not_again(TEdgeSegment* edge);
bool already_hit(const TEdgeSegment& edge) const; bool already_hit(TEdgeSegment* edge);
int Message(MessageCode code, float value) override; int Message(MessageCode code, float value) override;
vector2 get_coordinates() override; vector2 get_coordinates() override;
void Disable(); void Disable();
@ -24,6 +24,7 @@ public :
float Speed; float Speed;
float RayMaxDistance; float RayMaxDistance;
float TimeDelta; float TimeDelta;
float TimeNow;
vector2 RampFieldForce{}; vector2 RampFieldForce{};
TCollisionComponent* CollisionComp; TCollisionComponent* CollisionComp;
int CollisionMask; int CollisionMask;
@ -37,5 +38,5 @@ public :
int StuckCounter = 0; int StuckCounter = 0;
int LastActiveTime{}; int LastActiveTime{};
float VisualZArray[50]{}; float VisualZArray[50]{};
bool CollisionDisabledFlag{}; bool AsEdgeCollisionFlag{};
}; };

View file

@ -125,7 +125,7 @@ void TDemo::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
case 1404: case 1404:
if (!PlungerFlag) if (!PlungerFlag)
{ {
PinballTable->Message(MessageCode::PlungerInputPressed, 0); PinballTable->Message(MessageCode::PlungerInputPressed, ball->TimeNow);
float time = RandFloat() + 2.0f; float time = RandFloat() + 2.0f;
PlungerFlag = timer::set(time, this, PlungerRelease); PlungerFlag = timer::set(time, this, PlungerRelease);
} }

View file

@ -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) for (auto it = edgeBox->EdgeList.rbegin(); it != edgeBox->EdgeList.rend(); ++it)
{ {
auto edge = *it; auto edge = *it;
if (!edge->ProcessedFlag && *edge->ActiveFlagPtr && (edge->CollisionGroup & ray->CollisionMask) != 0) if (!edge->ProcessedFlag && *edge->ActiveFlagPtr && (edge->CollisionGroup & ray->CollisionMask))
{ {
if (!ball->already_hit(*edge)) if (!ball->already_hit(edge))
{ {
++edgeIndex; ++edgeIndex;
*edgePtr = edge; *edgePtr = edge;

View file

@ -18,7 +18,7 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
Unknown4 = 0.050000001f; Unknown4 = 0.050000001f;
MessageField = 0; MessageField = 0;
Timer = 0; Timer = 0;
BallCapturedFlag = false; BallCapturedFlag = 0;
Unknown3 = loader::query_float_attribute(groupIndex, 0, 407, 0.25f); Unknown3 = loader::query_float_attribute(groupIndex, 0, 407, 0.25f);
GravityMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f); GravityMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f);
GravityPull = *loader::query_float_attribute(groupIndex, 0, 305); GravityPull = *loader::query_float_attribute(groupIndex, 0, 305);
@ -33,15 +33,18 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup, auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup,
reinterpret_cast<vector3*>(visual.FloatArr), reinterpret_cast<vector3*>(visual.FloatArr),
Circle.RadiusSq); Circle.RadiusSq);
if (tCircle)
{
tCircle->place_in_grid(&AABB); tCircle->place_in_grid(&AABB);
EdgeList.push_back(tCircle); EdgeList.push_back(tCircle);
}
ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2]; ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2];
CollisionMask = static_cast<int>(floor(*loader::query_float_attribute(groupIndex, 0, 1304))); CollisionMask = static_cast<int>(floor(*loader::query_float_attribute(groupIndex, 0, 1304)));
// CollisionMask difference: 3DPB - value given as is, FT: mask = 1 << value // Full tilt hack - CollisionMask should be 1
if (pb::FullTiltMode) if (pb::FullTiltMode)
CollisionMask = 1 << CollisionMask; CollisionMask = 1;
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2]; Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
circle.RadiusSq = Circle.RadiusSq; circle.RadiusSq = Circle.RadiusSq;
@ -61,7 +64,7 @@ int THole::Message(MessageCode code, float value)
if (Timer) if (Timer)
timer::kill(Timer); timer::kill(Timer);
Timer = 0; Timer = 0;
BallCapturedSecondStage = true; BallCapturedSecondStage = 1;
} }
return 0; return 0;
} }
@ -70,14 +73,14 @@ void THole::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
{ {
if (!BallCapturedFlag) if (!BallCapturedFlag)
{ {
BallCapturedSecondStage = false; BallCapturedSecondStage = 0;
Threshold = 1e9f; Threshold = 1000000000.0;
BallCapturedFlag = true; BallCapturedFlag = 1;
ball->CollisionComp = this; ball->CollisionComp = this;
ball->Position.X = Circle.Center.X; ball->Position.X = Circle.Center.X;
ball->Position.Y = Circle.Center.Y; ball->Position.Y = Circle.Center.Y;
ball->Direction.Z = 0.0; ball->Direction.Z = 0.0;
ball->CollisionDisabledFlag = true; ball->AsEdgeCollisionFlag = true;
// Ramp hole has no delay in FT. // Ramp hole has no delay in FT.
auto captureTime = pb::FullTiltMode ? 0 : 0.5f; auto captureTime = pb::FullTiltMode ? 0 : 0.5f;
@ -108,13 +111,15 @@ int THole::FieldEffect(TBall* ball, vector2* vecDst)
ball->Position.Z += ball->Direction.Z; ball->Position.Z += ball->Direction.Z;
if (ball->Position.Z <= ZSetValue) if (ball->Position.Z <= ZSetValue)
{ {
BallCapturedFlag = false; BallCapturedFlag = 0;
BallCapturedSecondStage = false; BallCapturedSecondStage = 0;
ball->Position.Z = ZSetValue; ball->Position.Z = ZSetValue;
ball->Direction.Z = 0.0;
ball->CollisionMask = CollisionMask; ball->CollisionMask = CollisionMask;
ball->Direction.Y = 0.0;
ball->CollisionComp = nullptr; ball->CollisionComp = nullptr;
ball->Direction = {}; ball->Direction.X = 0.0;
ball->Speed = 0.0f; ball->Speed = 0.0;
loader::play_sound(SoftHitSoundId, ball, "THole2"); loader::play_sound(SoftHitSoundId, ball, "THole2");
control::handler(MessageCode::ControlBallReleased, this); control::handler(MessageCode::ControlBallReleased, this);
} }
@ -144,5 +149,5 @@ void THole::TimerExpired(int timerId, void* caller)
{ {
auto hole = static_cast<THole*>(caller); auto hole = static_cast<THole*>(caller);
hole->Timer = 0; hole->Timer = 0;
hole->BallCapturedSecondStage = true; hole->BallCapturedSecondStage = 1;
} }

View file

@ -15,8 +15,8 @@ public:
static void TimerExpired(int timerId, void* caller); static void TimerExpired(int timerId, void* caller);
bool BallCapturedFlag{}; int BallCapturedFlag;
bool BallCapturedSecondStage{}; int BallCapturedSecondStage{};
int Timer; int Timer;
float Unknown3; float Unknown3;
float Unknown4; float Unknown4;

View file

@ -105,7 +105,7 @@ void TKickout::Collision(TBall* ball, vector2* nextPosition, vector2* direction,
ball->Position.Y = Circle.Center.Y; ball->Position.Y = Circle.Center.Y;
OriginalBallZ = ball->Position.Z; OriginalBallZ = ball->Position.Z;
ball->Position.Z = CollisionBallSetZ; ball->Position.Z = CollisionBallSetZ;
ball->CollisionDisabledFlag = true; ball->AsEdgeCollisionFlag = true;
if (PinballTable->TiltLockFlag) if (PinballTable->TiltLockFlag)
{ {
Message(MessageCode::TKickoutRestartTimer, 0.1f); Message(MessageCode::TKickoutRestartTimer, 0.1f);

View file

@ -59,7 +59,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
MultiballFlag = false; MultiballFlag = false;
PlayerCount = 0; PlayerCount = 0;
auto ball = AddBall({0.0f, 0.0f}); auto ball = AddBall(0.0f, 0.0f);
ball->Disable(); ball->Disable();
new TTableLayer(this); new TTableLayer(this);
@ -595,7 +595,7 @@ int TPinballTable::Message(MessageCode code, float value)
return 0; return 0;
} }
TBall* TPinballTable::AddBall(vector2 position) TBall* TPinballTable::AddBall(float x, float y)
{ {
TBall* ball = nullptr; TBall* ball = nullptr;
@ -615,6 +615,7 @@ TBall* TPinballTable::AddBall(vector2 position)
ball->Direction = {}; ball->Direction = {};
ball->Speed = 0; ball->Speed = 0;
ball->TimeDelta = 0; ball->TimeDelta = 0;
ball->TimeNow = 0;
ball->EdgeCollisionCount = 0; ball->EdgeCollisionCount = 0;
ball->CollisionFlag = 0; ball->CollisionFlag = 0;
ball->CollisionMask = 1; ball->CollisionMask = 1;
@ -628,8 +629,8 @@ TBall* TPinballTable::AddBall(vector2 position)
BallList.push_back(ball); BallList.push_back(ball);
} }
ball->Position.X = position.X; ball->Position.X = x;
ball->Position.Y = position.Y; ball->Position.Y = y;
ball->PrevPosition = ball->Position; ball->PrevPosition = ball->Position;
ball->StuckCounter = 0; ball->StuckCounter = 0;
ball->LastActiveTime = pb::time_ticks; ball->LastActiveTime = pb::time_ticks;

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "maths.h"
#include "TPinballComponent.h" #include "TPinballComponent.h"
class TBall; class TBall;
@ -10,6 +9,7 @@ class TPlunger;
class TDrain; class TDrain;
class TDemo; class TDemo;
class TLightGroup; class TLightGroup;
struct RectF;
struct score_struct_super struct score_struct_super
{ {
@ -35,7 +35,7 @@ public:
void tilt(float time); void tilt(float time);
void port_draw() override; void port_draw() override;
int Message(MessageCode code, float value) override; int Message(MessageCode code, float value) override;
TBall* AddBall(vector2 position); TBall* AddBall(float x, float y);
int BallCountInRect(const RectF& rect); int BallCountInRect(const RectF& rect);
int BallCountInRect(const vector2& pos, float margin); int BallCountInRect(const vector2& pos, float margin);
@ -77,7 +77,8 @@ public:
float GravityAngleX{}; float GravityAngleX{};
float GravityAnglY{}; float GravityAnglY{};
float CollisionCompOffset{}; float CollisionCompOffset{};
vector2 PlungerPosition{}; float PlungerPositionX{};
float PlungerPositionY{};
int ScoreMultiplier{}; int ScoreMultiplier{};
int ScoreAdded{}; int ScoreAdded{};
int ScoreSpecial1{}; int ScoreSpecial1{};

View file

@ -35,7 +35,8 @@ TPlunger::TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(t
PullbackIncrement = MaxPullback / (ListBitmap->size() * 8.0f); PullbackIncrement = MaxPullback / (ListBitmap->size() * 8.0f);
PullbackDelay = 0.025f; PullbackDelay = 0.025f;
float* floatArr = loader::query_float_attribute(groupIndex, 0, 601); float* floatArr = loader::query_float_attribute(groupIndex, 0, 601);
table->PlungerPosition = {floatArr[0], floatArr[1]}; table->PlungerPositionX = floatArr[0];
table->PlungerPositionY = floatArr[1];
} }
void TPlunger::Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge) void TPlunger::Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge)
@ -71,13 +72,18 @@ int TPlunger::Message(MessageCode code, float value)
break; break;
case MessageCode::PlungerFeedBall: case MessageCode::PlungerFeedBall:
{ {
if (PinballTable->BallCountInRect(PinballTable->PlungerPosition, PinballTable->CollisionCompOffset * 1.2f)) 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))
{ {
timer::set(1.0f, this, BallFeedTimer); timer::set(1.0f, this, BallFeedTimer);
} }
else else
{ {
auto ball = PinballTable->AddBall(PinballTable->PlungerPosition); auto ball = PinballTable->AddBall(PinballTable->PlungerPositionX, PinballTable->PlungerPositionY);
assertm(ball, "Failure to create ball in plunger"); assertm(ball, "Failure to create ball in plunger");
PinballTable->MultiballCount++; PinballTable->MultiballCount++;
PinballTable->BallInDrainFlag = 0; PinballTable->BallInDrainFlag = 0;

View file

@ -72,17 +72,24 @@ void TSink::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
void TSink::TimerExpired(int timerId, void* caller) void TSink::TimerExpired(int timerId, void* caller)
{ {
RectF rect{};
auto sink = static_cast<TSink*>(caller); auto sink = static_cast<TSink*>(caller);
auto table = sink->PinballTable; auto table = sink->PinballTable;
if (table->BallCountInRect(sink->BallPosition, table->CollisionCompOffset * 2.0f))
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))
{ {
timer::set(0.5f, sink, TimerExpired); timer::set(0.5f, sink, TimerExpired);
} }
else else
{ {
auto ball = table->AddBall(sink->BallPosition); auto ball = table->AddBall(sink->BallPosition.X, sink->BallPosition.Y);
assertm(ball, "Failure to create ball in sink"); assertm(ball, "Failure to create ball in sink");
ball->CollisionDisabledFlag = true; ball->AsEdgeCollisionFlag = true;
ball->throw_ball(&sink->BallThrowDirection, sink->ThrowAngleMult, sink->ThrowSpeedMult1, ball->throw_ball(&sink->BallThrowDirection, sink->ThrowAngleMult, sink->ThrowSpeedMult1,
sink->ThrowSpeedMult2); sink->ThrowSpeedMult2);
if (sink->SoundIndex3) if (sink->SoundIndex3)

View file

@ -251,8 +251,8 @@ vector2 maths::vector_mul(const vector2& vec1, float val)
float maths::basic_collision(TBall* ball, vector2* nextPosition, vector2* direction, float elasticity, float smoothness, float maths::basic_collision(TBall* ball, vector2* nextPosition, vector2* direction, float elasticity, float smoothness,
float threshold, float boost) float threshold, float boost)
{ {
ball->Position.X = nextPosition->X + direction->X * 0.0005f; ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y + direction->Y * 0.0005f; ball->Position.Y = nextPosition->Y;
// Project ball direction on collision rebound direction // Project ball direction on collision rebound direction
auto reboundProj = -DotProduct(*direction, ball->Direction); auto reboundProj = -DotProduct(*direction, ball->Direction);

View file

@ -52,6 +52,7 @@ struct ray_type
vector2 Direction; vector2 Direction;
float MaxDistance; float MaxDistance;
float MinDistance; float MinDistance;
float TimeNow;
int CollisionMask; int CollisionMask;
}; };

View file

@ -285,7 +285,7 @@ void pb::frame(float dtMilliSec)
float dtSec = dtMilliSec * 0.001f; float dtSec = dtMilliSec * 0.001f;
time_next = time_now + dtSec; time_next = time_now + dtSec;
timed_frame(dtSec); timed_frame(time_now, dtSec, true);
time_now = time_next; time_now = time_next;
dtMilliSec += time_ticks_remainder; dtMilliSec += time_ticks_remainder;
@ -318,7 +318,7 @@ void pb::frame(float dtMilliSec)
} }
} }
void pb::timed_frame(float timeDelta) void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
{ {
for (auto ball : MainTable->BallList) for (auto ball : MainTable->BallList)
{ {
@ -346,20 +346,19 @@ void pb::timed_frame(float timeDelta)
} }
} }
int ballSteps[20]{}; int ballSteps[20]{-1};
float ballStepsDistance[20]{}; float ballStepsDistance[20]{};
int maxStep = -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];
ballSteps[index] = -1;
if (ball->ActiveFlag != 0) if (ball->ActiveFlag != 0)
{ {
vector2 vecDst{}; 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->CollisionDisabledFlag = false; ball->AsEdgeCollisionFlag = false;
if (ball->CollisionComp) if (ball->CollisionComp)
{ {
ball->CollisionComp->FieldEffect(ball, &vecDst); ball->CollisionComp->FieldEffect(ball, &vecDst);
@ -367,8 +366,8 @@ void pb::timed_frame(float timeDelta)
else else
{ {
TTableLayer::edge_manager->FieldEffects(ball, &vecDst); TTableLayer::edge_manager->FieldEffects(ball, &vecDst);
vecDst.X *= ball->TimeDelta; vecDst.X *= timeDelta;
vecDst.Y *= ball->TimeDelta; vecDst.Y *= timeDelta;
ball->Direction.X *= ball->Speed; ball->Direction.X *= ball->Speed;
ball->Direction.Y *= ball->Speed; ball->Direction.Y *= ball->Speed;
maths::vector_add(ball->Direction, vecDst); maths::vector_add(ball->Direction, vecDst);
@ -402,15 +401,16 @@ void pb::timed_frame(float timeDelta)
for (auto ballIndex = 0u; ballIndex < MainTable->BallList.size(); ballIndex++) for (auto ballIndex = 0u; ballIndex < MainTable->BallList.size(); ballIndex++)
{ {
auto ball = MainTable->BallList[ballIndex]; auto ball = MainTable->BallList[ballIndex];
if (!ball->CollisionDisabledFlag && ballSteps[ballIndex] >= step) if (!ball->AsEdgeCollisionFlag && step <= ballSteps[ballIndex])
{ {
ray.CollisionMask = ball->CollisionMask; ray.CollisionMask = ball->CollisionMask;
ball->TimeNow = timeNow;
for (auto distanceSum = 0.0f; distanceSum < BallHalfRadius;) for (auto distanceSum = 0.0f; distanceSum < BallHalfRadius;)
{ {
ray.Origin = ball->Position; ray.Origin = ball->Position;
ray.Direction = ball->Direction; ray.Direction = ball->Direction;
if (ballSteps[ballIndex] <= step) if (step >= ballSteps[ballIndex])
{ {
ray.MaxDistance = ballStepsDistance[ballIndex] - ballSteps[ballIndex] * BallHalfRadius; ray.MaxDistance = ballStepsDistance[ballIndex] - ballSteps[ballIndex] * BallHalfRadius;
} }
@ -418,6 +418,7 @@ void pb::timed_frame(float timeDelta)
{ {
ray.MaxDistance = BallHalfRadius; ray.MaxDistance = BallHalfRadius;
} }
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);
@ -442,7 +443,7 @@ void pb::timed_frame(float timeDelta)
} }
edge->EdgeCollision(ball, distance); edge->EdgeCollision(ball, distance);
if (distance <= 0.0f || ball->CollisionDisabledFlag) if (distance <= 0.0f || ball->AsEdgeCollisionFlag)
break; break;
distanceSum += distance; distanceSum += distance;
} }
@ -461,12 +462,15 @@ void pb::timed_frame(float timeDelta)
flipper->UpdateSprite(); flipper->UpdateSprite();
} }
if (drawBalls)
{
for (auto ball : MainTable->BallList) for (auto ball : MainTable->BallList)
{ {
if (ball->ActiveFlag) if (ball->ActiveFlag)
ball->Repaint(); ball->Repaint();
} }
} }
}
void pb::pause_continue() void pb::pause_continue()
{ {
@ -602,7 +606,8 @@ void pb::InputDown(GameInput input)
case 'b': case 'b':
{ {
vector2 pos{6.0f, 7.0f}; vector2 pos{6.0f, 7.0f};
if (!MainTable->BallCountInRect(pos, MainTable->CollisionCompOffset * 1.2f) && MainTable->AddBall(pos)) if (!MainTable->BallCountInRect(pos, MainTable->CollisionCompOffset * 1.2f) && MainTable->AddBall(
pos.X, pos.Y))
MainTable->MultiballCount++; MainTable->MultiballCount++;
break; break;
} }
@ -755,9 +760,9 @@ void pb::ShowMessageBox(Uint32 flags, LPCSTR title, LPCSTR message)
float pb::BallToBallCollision(const ray_type& ray, const TBall& ball, TEdgeSegment** edge, float collisionDistance) float pb::BallToBallCollision(const ray_type& ray, const TBall& ball, TEdgeSegment** edge, float collisionDistance)
{ {
for (const auto curBall : MainTable->BallList) for (auto curBall : MainTable->BallList)
{ {
if (curBall->ActiveFlag && curBall != &ball && (curBall->CollisionMask & ball.CollisionMask) != 0 && if (curBall->ActiveFlagPtr && curBall != &ball && (curBall->CollisionMask & ball.CollisionMask) != 0 &&
std::abs(curBall->Position.X - ball.Position.X) < BallToBallCollisionDistance && std::abs(curBall->Position.X - ball.Position.X) < BallToBallCollisionDistance &&
std::abs(curBall->Position.Y - ball.Position.Y) < BallToBallCollisionDistance) std::abs(curBall->Position.Y - ball.Position.Y) < BallToBallCollisionDistance)
{ {
@ -765,7 +770,7 @@ float pb::BallToBallCollision(const ray_type& ray, const TBall& ball, TEdgeSegme
if (distance < 1e9f) if (distance < 1e9f)
{ {
distance = std::max(0.0f, distance - 0.002f); distance = std::max(0.0f, distance - 0.002f);
if (distance < collisionDistance) if (collisionDistance > distance)
{ {
collisionDistance = distance; collisionDistance = distance;
*edge = curBall; *edge = curBall;

View file

@ -66,7 +66,7 @@ public:
static void replay_level(bool demoMode); static void replay_level(bool demoMode);
static void ballset(float dx, float dy); static void ballset(float dx, float dy);
static void frame(float dtMilliSec); static void frame(float dtMilliSec);
static void timed_frame(float timeDelta); static void timed_frame(float timeNow, float timeDelta, bool drawBalls);
static void pause_continue(); static void pause_continue();
static void loose_focus(); static void loose_focus();
static void InputUp(GameInput input); static void InputUp(GameInput input);