mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-23 17:30:18 +01:00
Compare commits
2 commits
c5acdcd524
...
43e2ab896b
Author | SHA1 | Date | |
---|---|---|---|
|
43e2ab896b | ||
|
e0424bed65 |
15 changed files with 76 additions and 110 deletions
|
@ -17,7 +17,6 @@ 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;
|
||||||
|
@ -108,11 +107,11 @@ void TBall::not_again(TEdgeSegment* edge)
|
||||||
EdgeCollisionResetFlag = true;
|
EdgeCollisionResetFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TBall::already_hit(TEdgeSegment* edge)
|
bool TBall::already_hit(const TEdgeSegment& edge) const
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,35 +151,29 @@ 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->AsEdgeCollisionFlag = true;
|
ball->CollisionDisabledFlag = true;
|
||||||
vector2 nextPos{
|
ball->Position.X += ball->Direction.X * distance;
|
||||||
ball->Position.X + ball->Direction.X * distance,
|
ball->Position.Y += ball->Direction.Y * 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;
|
||||||
|
|
||||||
auto coef = -maths::DotProduct(ball->Direction, collDir);
|
// AB - vector from ball to this, BA - from this to ball; collision direction
|
||||||
vector2 v44{collDir.X * coef, collDir.Y * coef};
|
vector2 AB{ball->Position.X - Position.X, ball->Position.Y - Position.Y};
|
||||||
vector2 v13{ball->Direction.X + v44.X, ball->Direction.Y + v44.Y};
|
maths::normalize_2d(AB);
|
||||||
|
vector2 BA{-AB.X, -AB.Y};
|
||||||
|
|
||||||
coef = -maths::DotProduct(Direction, invCollDir);
|
// Projection = difference between ball directions and collision direction
|
||||||
vector2 v11{invCollDir.X * coef, invCollDir.Y * coef};
|
auto projAB = -maths::DotProduct(ball->Direction, AB);
|
||||||
vector2 v10{Direction.X + v11.X, Direction.Y + v11.Y};
|
auto projBA = -maths::DotProduct(Direction, BA);
|
||||||
|
vector2 delta{AB.X * projAB - BA.X * projBA, AB.Y * projAB - BA.Y * projBA};
|
||||||
|
|
||||||
ball->Direction.X = -v11.X + v13.X;
|
ball->Direction.X += delta.X;
|
||||||
ball->Direction.Y = -v11.Y + v13.Y;
|
ball->Direction.Y += delta.Y;
|
||||||
ball->Speed = maths::normalize_2d(ball->Direction);
|
ball->Speed = maths::normalize_2d(ball->Direction);
|
||||||
Direction.X = -v44.X + v10.X;
|
Direction.X -= delta.X;
|
||||||
Direction.Y = -v44.Y + v10.Y;
|
Direction.Y -= delta.Y;
|
||||||
Speed = maths::normalize_2d(Direction);
|
Speed = maths::normalize_2d(Direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +192,6 @@ vector2 TBall::get_coordinates()
|
||||||
void TBall::Disable()
|
void TBall::Disable()
|
||||||
{
|
{
|
||||||
ActiveFlag = false;
|
ActiveFlag = false;
|
||||||
AsEdgeCollisionFlag = true;
|
CollisionDisabledFlag = true;
|
||||||
SpriteSet(-1);
|
SpriteSet(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(TEdgeSegment* edge);
|
bool already_hit(const TEdgeSegment& edge) const;
|
||||||
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,7 +24,6 @@ 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;
|
||||||
|
@ -38,5 +37,5 @@ public :
|
||||||
int StuckCounter = 0;
|
int StuckCounter = 0;
|
||||||
int LastActiveTime{};
|
int LastActiveTime{};
|
||||||
float VisualZArray[50]{};
|
float VisualZArray[50]{};
|
||||||
bool AsEdgeCollisionFlag{};
|
bool CollisionDisabledFlag{};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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, ball->TimeNow);
|
PinballTable->Message(MessageCode::PlungerInputPressed, 0);
|
||||||
float time = RandFloat() + 2.0f;
|
float time = RandFloat() + 2.0f;
|
||||||
PlungerFlag = timer::set(time, this, PlungerRelease);
|
PlungerFlag = timer::set(time, this, PlungerRelease);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
if (!edge->ProcessedFlag && *edge->ActiveFlagPtr && (edge->CollisionGroup & ray->CollisionMask) != 0)
|
||||||
{
|
{
|
||||||
if (!ball->already_hit(edge))
|
if (!ball->already_hit(*edge))
|
||||||
{
|
{
|
||||||
++edgeIndex;
|
++edgeIndex;
|
||||||
*edgePtr = edge;
|
*edgePtr = edge;
|
||||||
|
|
|
@ -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 = 0;
|
BallCapturedFlag = false;
|
||||||
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,18 +33,15 @@ 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)));
|
||||||
|
|
||||||
// Full tilt hack - CollisionMask should be 1
|
// CollisionMask difference: 3DPB - value given as is, FT: mask = 1 << value
|
||||||
if (pb::FullTiltMode)
|
if (pb::FullTiltMode)
|
||||||
CollisionMask = 1;
|
CollisionMask = 1 << CollisionMask;
|
||||||
|
|
||||||
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
|
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
|
||||||
circle.RadiusSq = Circle.RadiusSq;
|
circle.RadiusSq = Circle.RadiusSq;
|
||||||
|
@ -64,7 +61,7 @@ int THole::Message(MessageCode code, float value)
|
||||||
if (Timer)
|
if (Timer)
|
||||||
timer::kill(Timer);
|
timer::kill(Timer);
|
||||||
Timer = 0;
|
Timer = 0;
|
||||||
BallCapturedSecondStage = 1;
|
BallCapturedSecondStage = true;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -73,14 +70,14 @@ void THole::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
|
||||||
{
|
{
|
||||||
if (!BallCapturedFlag)
|
if (!BallCapturedFlag)
|
||||||
{
|
{
|
||||||
BallCapturedSecondStage = 0;
|
BallCapturedSecondStage = false;
|
||||||
Threshold = 1000000000.0;
|
Threshold = 1e9f;
|
||||||
BallCapturedFlag = 1;
|
BallCapturedFlag = true;
|
||||||
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->AsEdgeCollisionFlag = true;
|
ball->CollisionDisabledFlag = 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;
|
||||||
|
@ -111,15 +108,13 @@ 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 = 0;
|
BallCapturedFlag = false;
|
||||||
BallCapturedSecondStage = 0;
|
BallCapturedSecondStage = false;
|
||||||
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.X = 0.0;
|
ball->Direction = {};
|
||||||
ball->Speed = 0.0;
|
ball->Speed = 0.0f;
|
||||||
loader::play_sound(SoftHitSoundId, ball, "THole2");
|
loader::play_sound(SoftHitSoundId, ball, "THole2");
|
||||||
control::handler(MessageCode::ControlBallReleased, this);
|
control::handler(MessageCode::ControlBallReleased, this);
|
||||||
}
|
}
|
||||||
|
@ -149,5 +144,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 = 1;
|
hole->BallCapturedSecondStage = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ public:
|
||||||
|
|
||||||
static void TimerExpired(int timerId, void* caller);
|
static void TimerExpired(int timerId, void* caller);
|
||||||
|
|
||||||
int BallCapturedFlag;
|
bool BallCapturedFlag{};
|
||||||
int BallCapturedSecondStage{};
|
bool BallCapturedSecondStage{};
|
||||||
int Timer;
|
int Timer;
|
||||||
float Unknown3;
|
float Unknown3;
|
||||||
float Unknown4;
|
float Unknown4;
|
||||||
|
|
|
@ -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->AsEdgeCollisionFlag = true;
|
ball->CollisionDisabledFlag = true;
|
||||||
if (PinballTable->TiltLockFlag)
|
if (PinballTable->TiltLockFlag)
|
||||||
{
|
{
|
||||||
Message(MessageCode::TKickoutRestartTimer, 0.1f);
|
Message(MessageCode::TKickoutRestartTimer, 0.1f);
|
||||||
|
|
|
@ -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(float x, float y)
|
TBall* TPinballTable::AddBall(vector2 position)
|
||||||
{
|
{
|
||||||
TBall* ball = nullptr;
|
TBall* ball = nullptr;
|
||||||
|
|
||||||
|
@ -615,7 +615,6 @@ TBall* TPinballTable::AddBall(float x, float y)
|
||||||
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;
|
||||||
|
@ -629,8 +628,8 @@ TBall* TPinballTable::AddBall(float x, float y)
|
||||||
BallList.push_back(ball);
|
BallList.push_back(ball);
|
||||||
}
|
}
|
||||||
|
|
||||||
ball->Position.X = x;
|
ball->Position.X = position.X;
|
||||||
ball->Position.Y = y;
|
ball->Position.Y = position.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;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "maths.h"
|
||||||
#include "TPinballComponent.h"
|
#include "TPinballComponent.h"
|
||||||
|
|
||||||
class TBall;
|
class TBall;
|
||||||
|
@ -9,7 +10,6 @@ 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(float x, float y);
|
TBall* AddBall(vector2 position);
|
||||||
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,8 +77,7 @@ public:
|
||||||
float GravityAngleX{};
|
float GravityAngleX{};
|
||||||
float GravityAnglY{};
|
float GravityAnglY{};
|
||||||
float CollisionCompOffset{};
|
float CollisionCompOffset{};
|
||||||
float PlungerPositionX{};
|
vector2 PlungerPosition{};
|
||||||
float PlungerPositionY{};
|
|
||||||
int ScoreMultiplier{};
|
int ScoreMultiplier{};
|
||||||
int ScoreAdded{};
|
int ScoreAdded{};
|
||||||
int ScoreSpecial1{};
|
int ScoreSpecial1{};
|
||||||
|
|
|
@ -35,8 +35,7 @@ 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->PlungerPositionX = floatArr[0];
|
table->PlungerPosition = {floatArr[0], floatArr[1]};
|
||||||
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)
|
||||||
|
@ -72,18 +71,13 @@ int TPlunger::Message(MessageCode code, float value)
|
||||||
break;
|
break;
|
||||||
case MessageCode::PlungerFeedBall:
|
case MessageCode::PlungerFeedBall:
|
||||||
{
|
{
|
||||||
RectF rect{};
|
if (PinballTable->BallCountInRect(PinballTable->PlungerPosition, PinballTable->CollisionCompOffset * 1.2f))
|
||||||
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->PlungerPositionX, PinballTable->PlungerPositionY);
|
auto ball = PinballTable->AddBall(PinballTable->PlungerPosition);
|
||||||
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;
|
||||||
|
|
|
@ -72,24 +72,17 @@ 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.X, sink->BallPosition.Y);
|
auto ball = table->AddBall(sink->BallPosition);
|
||||||
assertm(ball, "Failure to create ball in sink");
|
assertm(ball, "Failure to create ball in sink");
|
||||||
ball->AsEdgeCollisionFlag = true;
|
ball->CollisionDisabledFlag = 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)
|
||||||
|
|
|
@ -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;
|
ball->Position.X = nextPosition->X + direction->X * 0.0005f;
|
||||||
ball->Position.Y = nextPosition->Y;
|
ball->Position.Y = nextPosition->Y + direction->Y * 0.0005f;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
|
@ -52,7 +52,6 @@ struct ray_type
|
||||||
vector2 Direction;
|
vector2 Direction;
|
||||||
float MaxDistance;
|
float MaxDistance;
|
||||||
float MinDistance;
|
float MinDistance;
|
||||||
float TimeNow;
|
|
||||||
int CollisionMask;
|
int CollisionMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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(time_now, dtSec, true);
|
timed_frame(dtSec);
|
||||||
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 timeNow, float timeDelta, bool drawBalls)
|
void pb::timed_frame(float timeDelta)
|
||||||
{
|
{
|
||||||
for (auto ball : MainTable->BallList)
|
for (auto ball : MainTable->BallList)
|
||||||
{
|
{
|
||||||
|
@ -346,19 +346,20 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ballSteps[20]{-1};
|
int ballSteps[20]{};
|
||||||
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->AsEdgeCollisionFlag = false;
|
ball->CollisionDisabledFlag = false;
|
||||||
if (ball->CollisionComp)
|
if (ball->CollisionComp)
|
||||||
{
|
{
|
||||||
ball->CollisionComp->FieldEffect(ball, &vecDst);
|
ball->CollisionComp->FieldEffect(ball, &vecDst);
|
||||||
|
@ -366,8 +367,8 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TTableLayer::edge_manager->FieldEffects(ball, &vecDst);
|
TTableLayer::edge_manager->FieldEffects(ball, &vecDst);
|
||||||
vecDst.X *= timeDelta;
|
vecDst.X *= ball->TimeDelta;
|
||||||
vecDst.Y *= timeDelta;
|
vecDst.Y *= ball->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);
|
||||||
|
@ -401,16 +402,15 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
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->AsEdgeCollisionFlag && step <= ballSteps[ballIndex])
|
if (!ball->CollisionDisabledFlag && ballSteps[ballIndex] >= step)
|
||||||
{
|
{
|
||||||
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 (step >= ballSteps[ballIndex])
|
if (ballSteps[ballIndex] <= step)
|
||||||
{
|
{
|
||||||
ray.MaxDistance = ballStepsDistance[ballIndex] - ballSteps[ballIndex] * BallHalfRadius;
|
ray.MaxDistance = ballStepsDistance[ballIndex] - ballSteps[ballIndex] * BallHalfRadius;
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,6 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
@ -443,7 +442,7 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
edge->EdgeCollision(ball, distance);
|
edge->EdgeCollision(ball, distance);
|
||||||
if (distance <= 0.0f || ball->AsEdgeCollisionFlag)
|
if (distance <= 0.0f || ball->CollisionDisabledFlag)
|
||||||
break;
|
break;
|
||||||
distanceSum += distance;
|
distanceSum += distance;
|
||||||
}
|
}
|
||||||
|
@ -462,14 +461,11 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
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()
|
||||||
|
@ -606,8 +602,7 @@ 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(
|
if (!MainTable->BallCountInRect(pos, MainTable->CollisionCompOffset * 1.2f) && MainTable->AddBall(pos))
|
||||||
pos.X, pos.Y))
|
|
||||||
MainTable->MultiballCount++;
|
MainTable->MultiballCount++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -760,9 +755,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 (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.X - ball.Position.X) < BallToBallCollisionDistance &&
|
||||||
std::abs(curBall->Position.Y - ball.Position.Y) < BallToBallCollisionDistance)
|
std::abs(curBall->Position.Y - ball.Position.Y) < BallToBallCollisionDistance)
|
||||||
{
|
{
|
||||||
|
@ -770,7 +765,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 (collisionDistance > distance)
|
if (distance < collisionDistance)
|
||||||
{
|
{
|
||||||
collisionDistance = distance;
|
collisionDistance = distance;
|
||||||
*edge = curBall;
|
*edge = curBall;
|
||||||
|
|
|
@ -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 timeNow, float timeDelta, bool drawBalls);
|
static void timed_frame(float timeDelta);
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue