TFlipper, TFlipperEdge ready.

This commit is contained in:
oz 2021-01-10 15:22:06 +03:00
parent 87b4aa27e7
commit 61fe0410b0
8 changed files with 510 additions and 266 deletions

Binary file not shown.

View file

@ -220,7 +220,7 @@
<Filter>Header Files\TPinballComponent</Filter> <Filter>Header Files\TPinballComponent</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="TFlipperEdge.h"> <ClInclude Include="TFlipperEdge.h">
<Filter>Header Files</Filter> <Filter>Header Files\TEdgeSegment</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -408,7 +408,7 @@
<Filter>Source Files\TPinballComponent</Filter> <Filter>Source Files\TPinballComponent</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="TFlipperEdge.cpp"> <ClCompile Include="TFlipperEdge.cpp">
<Filter>Source Files</Filter> <Filter>Source Files\TEdgeSegment</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,2 +1,188 @@
#include "pch.h" #include "pch.h"
#include "TFlipper.h" #include "TFlipper.h"
#include "control.h"
#include "loader.h"
#include "pb.h"
#include "render.h"
#include "TFlipperEdge.h"
#include "timer.h"
#include "TZmapList.h"
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
visualStruct visual{};
loader::query_visual(groupIndex, 0, &visual);
SoundIndex1 = visual.SoundIndex4;
SoundIndex2 = visual.SoundIndex3;
UnknownC4F = visual.Unknown2F;
Timer = 0;
UnknownC5F = visual.Unknown1F;
auto floatArr = loader::query_float_attribute(groupIndex, 0, 803);
auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 805);
auto floatArr3 = loader::query_float_attribute(groupIndex, 0, 804);
auto collMult = *floatArr;
auto bmpCoef2 = *floatArr2;
auto bmpCoef1 = *floatArr3;
auto vecT2 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 802));
auto vecT1 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 801));
auto origin = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 800));
auto flipperEdge = new TFlipperEdge(
this,
&UnknownBaseFlag2,
visual.Flag,
table,
origin,
vecT1,
vecT2,
bmpCoef1,
bmpCoef2,
collMult,
UnknownC4F,
UnknownC5F);
FlipperEdge = flipperEdge;
if (flipperEdge)
{
BmpCoef1 = flipperEdge->BmpCoef1 / static_cast<float>(ListBitmap->Count() - 1);
BmpCoef2 = flipperEdge->BmpCoef2 / static_cast<float>(ListBitmap->Count() - 1);
}
BmpIndex = 0;
InputTime = 0.0;
}
TFlipper::~TFlipper()
{
delete FlipperEdge;
}
int TFlipper::Message(int code, float value)
{
if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022)
{
float timerTime;
int soundIndex = 0, code2 = code;
if (code == 1)
{
control::handler(1, this);
TimerTime = BmpCoef1;
soundIndex = SoundIndex1;
}
else if (code == 2)
{
TimerTime = BmpCoef2;
soundIndex = SoundIndex2;
}
else
{
code2 = 2;
TimerTime = BmpCoef2;
}
if (soundIndex)
loader::play_sound(soundIndex);
if (Timer)
{
timer::kill(Timer);
Timer = 0;
}
if (MessageField)
{
auto v10 = value - FlipperEdge->InputTime;
timerTime = v10 - floor(v10 / TimerTime) * TimerTime;
if (timerTime < 0.0)
timerTime = 0.0;
}
else
{
timerTime = TimerTime;
}
MessageField = code2;
InputTime = value;
Timer = timer::set(timerTime, this, TimerExpired);
FlipperEdge->SetMotion(code2, value);
}
if (code == 1020 || code == 1024)
{
if (MessageField)
{
if (Timer)
timer::kill(Timer);
BmpIndex = -1;
MessageField = 2;
TimerExpired(Timer, this);
FlipperEdge->SetMotion(code, value);
}
}
return 0;
}
void TFlipper::port_draw()
{
FlipperEdge->port_draw();
}
void TFlipper::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
}
void TFlipper::TimerExpired(int timerId, void* caller)
{
auto flip = static_cast<TFlipper*>(caller);
int timer; // eax
bool bmpIndexOutOfBounds = false;
auto bmpIndexAdvance = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime + 0.5f));
int bmpCount = flip->ListBitmap->Count();
if (bmpIndexAdvance > bmpCount)
bmpIndexAdvance = bmpCount;
if (bmpIndexAdvance < 0)
bmpIndexAdvance = 0;
if (!bmpIndexAdvance)
bmpIndexAdvance = 1;
if (flip->MessageField == 1)
{
flip->BmpIndex += bmpIndexAdvance;
int countSub1 = flip->ListBitmap->Count() - 1;
if (flip->BmpIndex >= countSub1)
{
flip->BmpIndex = countSub1;
bmpIndexOutOfBounds = true;
}
}
if (flip->MessageField == 2)
{
flip->BmpIndex -= bmpIndexAdvance;
timer = 0;
if (flip->BmpIndex <= 0)
{
flip->BmpIndex = 0;
bmpIndexOutOfBounds = true;
}
}
else
{
timer = 0;
}
if (bmpIndexOutOfBounds)
flip->MessageField = 0;
else
timer = timer::set(flip->TimerTime, flip, TimerExpired);
flip->Timer = timer;
auto bmp = static_cast<gdrv_bitmap8*>(flip->ListBitmap->Get(flip->BmpIndex));
auto zMap = static_cast<zmap_header_type*>(flip->ListZMap->Get(flip->BmpIndex));
render::sprite_set(
flip->RenderSprite,
bmp,
zMap,
bmp->XPosition - flip->PinballTable->XOffset,
bmp->YPosition - flip->PinballTable->YOffset);
}

View file

@ -1,11 +1,26 @@
#pragma once #pragma once
#include "TCollisionComponent.h" #include "TCollisionComponent.h"
class TFlipperEdge;
class TFlipper : class TFlipper :
public TCollisionComponent public TCollisionComponent
{ {
public: public:
TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false) TFlipper(TPinballTable* table, int groupIndex);
{ ~TFlipper() override;
} int Message(int code, float value) override;
void port_draw() override;
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
static void TimerExpired(int timerId, void* caller);
int BmpIndex;
TFlipperEdge* FlipperEdge;
int Timer;
float BmpCoef1;
float BmpCoef2;
float TimerTime;
float InputTime;
}; };

View file

@ -12,8 +12,8 @@ line_type TFlipperEdge::lineA, TFlipperEdge::lineB;
circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1; circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1;
TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table, TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table,
vector_type* origin, vector_type* vecT, vector_type* vec3, float bmpCoef1, float bmpCoef2, vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2,
float a11, float c4F, float c5F): TEdgeSegment(collComp, someFlag, visualFlag) float collMult, float c4F, float c5F): TEdgeSegment(collComp, someFlag, visualFlag)
{ {
vector_type crossProd{}, vecDir1{}, vecDir2{}; vector_type crossProd{}, vecDir1{}, vecDir2{};
@ -21,10 +21,10 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
CollisionC5F = c5F; CollisionC5F = c5F;
BmpCoef1 = bmpCoef1; BmpCoef1 = bmpCoef1;
BmpCoef2 = bmpCoef2; BmpCoef2 = bmpCoef2;
Unknown32F = a11; CollisionMult = collMult;
T1Src = *vecT; T1Src = *vecT1;
Unknown36V = *vec3; T2Src = *vecT2;
RotOrigin.X = origin->X; RotOrigin.X = origin->X;
RotOrigin.Y = origin->Y; RotOrigin.Y = origin->Y;
@ -32,17 +32,17 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
CirclebaseRadiusMSq = CirclebaseRadius * 1.01f * (CirclebaseRadius * 1.01f); CirclebaseRadiusMSq = CirclebaseRadius * 1.01f * (CirclebaseRadius * 1.01f);
CirclebaseRadiusSq = CirclebaseRadius * CirclebaseRadius; CirclebaseRadiusSq = CirclebaseRadius * CirclebaseRadius;
CircleT1Radius = vecT->Z + table->CollisionCompOffset; CircleT1Radius = vecT1->Z + table->CollisionCompOffset;
CircleT1RadiusMSq = CircleT1Radius * 1.01f * (CircleT1Radius * 1.01f); CircleT1RadiusMSq = CircleT1Radius * 1.01f * (CircleT1Radius * 1.01f);
CircleT1RadiusSq = CircleT1Radius * CircleT1Radius; CircleT1RadiusSq = CircleT1Radius * CircleT1Radius;
vecDir1.X = vecT->X - origin->X; vecDir1.X = vecT1->X - origin->X;
vecDir1.Y = vecT->Y - origin->Y; vecDir1.Y = vecT1->Y - origin->Y;
vecDir1.Z = 0.0; vecDir1.Z = 0.0;
maths::normalize_2d(&vecDir1); maths::normalize_2d(&vecDir1);
vecDir2.X = vec3->X - origin->X; vecDir2.X = vecT2->X - origin->X;
vecDir2.Y = vec3->Y - origin->Y; vecDir2.Y = vecT2->Y - origin->Y;
vecDir2.Z = 0.0; vecDir2.Z = 0.0;
maths::normalize_2d(&vecDir2); maths::normalize_2d(&vecDir2);
@ -57,15 +57,15 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
auto dirY1 = -vecDir1.Y; auto dirY1 = -vecDir1.Y;
A2Src.X = dirY1 * CirclebaseRadius + origin->X; A2Src.X = dirY1 * CirclebaseRadius + origin->X;
A2Src.Y = dirX1 * CirclebaseRadius + origin->Y; A2Src.Y = dirX1 * CirclebaseRadius + origin->Y;
A1Src.X = dirY1 * CircleT1Radius + vecT->X; A1Src.X = dirY1 * CircleT1Radius + vecT1->X;
A1Src.Y = dirX1 * CircleT1Radius + vecT->Y; A1Src.Y = dirX1 * CircleT1Radius + vecT1->Y;
dirX1 = -dirX1; dirX1 = -dirX1;
dirY1 = -dirY1; dirY1 = -dirY1;
B1Src.X = dirY1 * CirclebaseRadius + origin->X; B1Src.X = dirY1 * CirclebaseRadius + origin->X;
B1Src.Y = dirX1 * CirclebaseRadius + origin->Y; B1Src.Y = dirX1 * CirclebaseRadius + origin->Y;
B2Src.X = dirY1 * CircleT1Radius + vecT->X; B2Src.X = dirY1 * CircleT1Radius + vecT1->X;
B2Src.Y = dirX1 * CircleT1Radius + vecT->Y; B2Src.Y = dirX1 * CircleT1Radius + vecT1->Y;
if (AngleMax < 0.0) if (AngleMax < 0.0)
{ {
@ -73,261 +73,239 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
maths::vswap(&A2Src, &B2Src); maths::vswap(&A2Src, &B2Src);
} }
auto dx = vecT->X - RotOrigin.X; auto dx = vecT1->X - RotOrigin.X;
auto dy = vecT->Y - RotOrigin.Y; auto dy = vecT1->Y - RotOrigin.Y;
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT->Z; auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
DistanceDivSq = distance1 * distance1; DistanceDivSq = distance1 * distance1;
float bmpCoef = min(BmpCoef1, BmpCoef2); float bmpCoef = min(BmpCoef1, BmpCoef2);
auto distance = maths::Distance(vecT, vec3); auto distance = maths::Distance(vecT1, vecT2);
Unknown40F = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius); CollisionTimeAdvance = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius);
TFlipperEdge::place_in_grid(); TFlipperEdge::place_in_grid();
Unknown44 = 0; EdgeCollisionFlag = 0;
TimeAngle = 0.0; InputTime = 0.0;
Unknown15 = 0; CollisionFlag1 = 0;
Unknown46F = 0.0; AngleStopTime = 0.0;
AngleMult = 0.0; AngleMult = 0.0;
} }
void TFlipperEdge::port_draw() void TFlipperEdge::port_draw()
{ {
set_control_points(TimeAngle); set_control_points(InputTime);
build_edges_in_motion(); build_edges_in_motion();
} }
float TFlipperEdge::FindCollisionDistance(ray_type* ray) float TFlipperEdge::FindCollisionDistance(ray_type* ray)
{ {
auto ogRay = ray; auto ogRay = ray;
ray_type dstRay{}, srcRay{};
if (ogRay->TimeNow > AngleStopTime)
float* pfVar2; {
short uVar3; FlipperFlag = 0;
int iVar4;
int uVar5;
vector_type* prVar6;
vector_type* plVar6;
vector_type* pvVar7;
float fVar8;
ray_type ray2;
ray_type ray1;
float local_1c;
float local_18;
float local_14;
float local_10;
float local_c;
float local_8;
if (ogRay->TimeNow > this->Unknown46F) {
this->FlipperFlag = 0;
} }
if (this->Unknown44 == 0) { if (EdgeCollisionFlag == 0)
if (this->FlipperFlag == 0) { {
this->Unknown44 = 0; if (FlipperFlag == 0)
this->Unknown15 = 0; {
this->Unknown16 = 0; EdgeCollisionFlag = 0;
CollisionFlag1 = 0;
CollisionFlag2 = 0;
set_control_points(ogRay->TimeNow); set_control_points(ogRay->TimeNow);
build_edges_in_motion(); build_edges_in_motion();
iVar4 = is_ball_inside( (ogRay->Origin).X, (ogRay->Origin).Y); auto ballInside = is_ball_inside(ogRay->Origin.X, ogRay->Origin.Y);
ray1.MinDistance = ogRay->MinDistance; srcRay.MinDistance = ogRay->MinDistance;
if (iVar4 == 0) { if (ballInside == 0)
ray1.Direction.X = (ogRay->Direction).X; {
ray1.Direction.Y = (ogRay->Direction).Y; srcRay.Direction = ogRay->Direction;
ray1.Direction.Z = (ogRay->Direction).Z; srcRay.MaxDistance = ogRay->MaxDistance;
ray1.MaxDistance = ogRay->MaxDistance; srcRay.Origin = ogRay->Origin;
ray1.Origin.X = (ogRay->Origin).X; auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
ray1.Origin.Y = (ogRay->Origin).Y; if (distance == 0.0)
ray1.Origin.Z = (ogRay->Origin).Z; {
fVar8 = maths::distance_to_flipper(&ray1, &ray2); NextBallPosition = dstRay.Origin;
plVar6 = &ray2.Origin; NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
if (fVar8 == 0.0) { NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
pvVar7 = &this->NextBallPosition;
pvVar7->X = ray2.Origin.X;
(this->NextBallPosition).Y = ray2.Origin.Y;
(this->NextBallPosition).Z = ray2.Origin.Z;
pvVar7->X = pvVar7->X - ray1.Direction.X * 1e-05f;
pfVar2 = &(this->NextBallPosition).Y;
*pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05f;
} }
else { else
pvVar7 = &this->NextBallPosition; {
LAB_0101bab7: NextBallPosition = dstRay.Origin;
pvVar7->X = (plVar6)->X;
pvVar7->Y = (plVar6)->Y;
pvVar7->Z = (plVar6)->Z;
} }
(this->CollisionDirection).X = ray2.Direction.X; CollisionDirection = dstRay.Direction;
(this->CollisionDirection).Y = ray2.Direction.Y; return distance;
(this->CollisionDirection).Z = ray2.Direction.Z;
return fVar8;
} }
fVar8 = maths::Distance_Squared(ogRay->Origin, this->RotOrigin);
if (this->CirclebaseRadiusMSq <= fVar8) { if (maths::Distance_Squared(ogRay->Origin, RotOrigin) >= CirclebaseRadiusMSq)
fVar8 = maths::Distance_Squared(ogRay->Origin, T1); {
if (this->CircleT1RadiusMSq <= fVar8) { if (maths::Distance_Squared(ogRay->Origin, T1) >= CircleT1RadiusMSq)
ray1.Direction.Y = lineB.PerpendicularL.Y; {
ray1.Direction.X = lineB.PerpendicularL.X; srcRay.Direction.Y = lineB.PerpendicularL.Y;
if (iVar4 == 4) { srcRay.Direction.X = lineB.PerpendicularL.X;
ray1.Direction.Y = lineA.PerpendicularL.Y; if (ballInside == 4)
ray1.Direction.X = lineA.PerpendicularL.X; {
srcRay.Direction.Y = lineA.PerpendicularL.Y;
srcRay.Direction.X = lineA.PerpendicularL.X;
} }
ray1.Direction.X = -ray1.Direction.X; srcRay.Direction.X = -srcRay.Direction.X;
ray1.Direction.Y = -ray1.Direction.Y; srcRay.Direction.Y = -srcRay.Direction.Y;
} }
else { else
ray1.Direction.X = T1.X - (ogRay->Origin).X; {
ray1.Direction.Y = T1.Y - (ogRay->Origin).Y; srcRay.Direction.X = T1.X - ogRay->Origin.X;
maths::normalize_2d(&ray1.Direction); srcRay.Direction.Y = T1.Y - ogRay->Origin.Y;
maths::normalize_2d(&srcRay.Direction);
} }
} }
else { else
ray1.Direction.X = (this->RotOrigin).X - (ogRay->Origin).X; {
ray1.Direction.Y = (this->RotOrigin).Y - (ogRay->Origin).Y; srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X;
maths::normalize_2d(&ray1.Direction); srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
maths::normalize_2d(&srcRay.Direction);
} }
ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f;
ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f; srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
ray1.MaxDistance = ogRay->MaxDistance + 10.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
fVar8 = maths::distance_to_flipper(&ray1, &ray2); srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
if (1e+09 <= fVar8) { if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
ray1.Direction.X = (this->RotOrigin).X - (ogRay->Origin).X; {
ray1.Direction.Y = (this->RotOrigin).Y - (ogRay->Origin).Y; srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X;
maths::normalize_2d(&ray1.Direction); srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f; maths::normalize_2d(&srcRay.Direction);
ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f; srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
fVar8 = maths::distance_to_flipper(&ray1, &ray2); srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
if (1e+09 <= fVar8) { if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
{
return 1e+09; return 1e+09;
} }
} }
LAB_0101ba1a:
(this->NextBallPosition).X = ray2.Origin.X; NextBallPosition = dstRay.Origin;
(this->NextBallPosition).Y = ray2.Origin.Y; CollisionDirection = dstRay.Direction;
(this->NextBallPosition).Z = ray2.Origin.Z; NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
pvVar7 = &this->CollisionDirection; NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
prVar6 = &ray2.Direction;
LAB_0101bc82:
pvVar7->X = prVar6->X;
pvVar7->Y = prVar6->Y;
pvVar7->Z = prVar6->Z;
(this->NextBallPosition).X = (this->NextBallPosition).X - ray1.Direction.X * 1e-05;
pfVar2 = &(this->NextBallPosition).Y;
*pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05;
return 0.0; return 0.0;
} }
local_8 = (ogRay->Origin).X;
local_14 = this->Unknown40F * ogRay->MaxDistance; auto posX = ogRay->Origin.X;
local_c = (ogRay->Origin).Y; auto posY = ogRay->Origin.Y;
local_10 = ogRay->TimeNow; auto posXAdvance = ogRay->Direction.X * CollisionTimeAdvance;
local_18 = this->Unknown40F * (ogRay->Direction).X; auto posYAdvance = ogRay->Direction.Y * CollisionTimeAdvance;
local_1c = (ogRay->Direction).Y * this->Unknown40F; auto rayMaxDistance = ogRay->MaxDistance * CollisionTimeAdvance;
fVar8 = ogRay->TimeDelta + ogRay->TimeNow; auto timeNow = ogRay->TimeNow;
uVar3 = fVar8 <= local_10;// fp flag shift auto stopTime = ogRay->TimeDelta + ogRay->TimeNow;
while (uVar3 == 0) { while (timeNow < stopTime)
set_control_points( local_10); {
set_control_points(timeNow);
build_edges_in_motion(); build_edges_in_motion();
iVar4 = is_ball_inside( local_8, local_c); auto ballInside = is_ball_inside(posX, posY);
if (iVar4 != 0) { if (ballInside != 0)
if ((this->FlipperFlag == 1) && (iVar4 != 5)) { {
plVar6 = &lineA.PerpendicularL; vector_type* linePtr;
ray1.Direction.Y = lineA.PerpendicularL.Y; if (FlipperFlag == 1 && ballInside != 5)
ray1.Direction.X = lineA.PerpendicularL.X; {
linePtr = &lineA.PerpendicularL;
srcRay.Direction.Y = lineA.PerpendicularL.Y;
srcRay.Direction.X = lineA.PerpendicularL.X;
} }
else { else
if ((this->FlipperFlag != 2) || (iVar4 == 4)) { {
ray1.Direction.X = (this->RotOrigin).X - local_8; if (FlipperFlag != 2 || ballInside == 4)
this->Unknown15 = 0; {
this->Unknown16 = 1; CollisionFlag1 = 0;
ray1.Direction.Y = (this->RotOrigin).Y - local_c; CollisionFlag2 = 1;
maths::normalize_2d(&ray1.Direction); srcRay.Direction.X = RotOrigin.X - posX;
ray1.Origin.X = local_8 - ray1.Direction.X * 5.0f; srcRay.Direction.Y = RotOrigin.Y - posY;
ray1.Origin.Y = local_c - ray1.Direction.Y * 5.0f; maths::normalize_2d(&srcRay.Direction);
ray1.MaxDistance = ogRay->MaxDistance + 10.0f;
fVar8 = maths::distance_to_flipper(&ray1, &ray2); srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
if (1e+09 <= fVar8) { srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
(this->NextBallPosition).X = local_8; srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
(this->CollisionDirection).X = -ray1.Direction.X; if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
(this->NextBallPosition).Y = local_c; {
(this->CollisionDirection).Y = -ray1.Direction.Y; NextBallPosition.X = posX;
NextBallPosition.Y = posY;
CollisionDirection.X = -srcRay.Direction.X;
CollisionDirection.Y = -srcRay.Direction.Y;
return 0.0; return 0.0;
} }
goto LAB_0101ba1a;
NextBallPosition = dstRay.Origin;
CollisionDirection = dstRay.Direction;
NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
return 0.0;
} }
plVar6 = &lineB.PerpendicularL; linePtr = &lineB.PerpendicularL;
ray1.Direction.Y = lineB.PerpendicularL.Y; srcRay.Direction.Y = lineB.PerpendicularL.Y;
ray1.Direction.X = lineB.PerpendicularL.X; srcRay.Direction.X = lineB.PerpendicularL.X;
} }
ray1.Direction.X = -ray1.Direction.X;
ray1.Direction.Y = -ray1.Direction.Y; CollisionLinePerp = *linePtr;
(this->Unknown17V).X = plVar6->X; CollisionFlag2 = 0;
(this->Unknown17V).Y = plVar6->Y; CollisionFlag1 = 1;
(this->Unknown17V).Z = plVar6->Z; srcRay.Direction.X = -srcRay.Direction.X;
this->Unknown16 = 0; srcRay.Direction.Y = -srcRay.Direction.Y;
this->Unknown15 = 1; srcRay.MinDistance = 0.002f;
ray1.MinDistance = 0.002; srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f; srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f; srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
ray1.MaxDistance = ogRay->MaxDistance + 10.0f; auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
fVar8 = maths::distance_to_flipper(&ray1, &ray2); CollisionDirection = dstRay.Direction;
(this->CollisionDirection).X = ray2.Direction.X; if (distance >= 1e+09)
(this->CollisionDirection).Y = ray2.Direction.Y; {
(this->CollisionDirection).Z = ray2.Direction.Z;
if (1e+09 <= fVar8) {
return 1e+09; return 1e+09;
} }
pvVar7 = &this->NextBallPosition; NextBallPosition = dstRay.Origin;
prVar6 = &ray2.Origin; NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
goto LAB_0101bc82; NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
return 0.0;
} }
ray1.Direction.X = (ogRay->Direction).X;
ray1.Direction.Y = (ogRay->Direction).Y; srcRay.Direction = ogRay->Direction;
ray1.Direction.Z = (ogRay->Direction).Z; srcRay.MinDistance = ogRay->MinDistance;
ray1.MinDistance = ogRay->MinDistance; srcRay.Origin = ogRay->Origin;
ray1.Origin.X = (ogRay->Origin).X; srcRay.MaxDistance = rayMaxDistance;
ray1.Origin.Y = (ogRay->Origin).Y; auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
ray1.Origin.Z = (ogRay->Origin).Z; if (distance < 1e+09)
ray1.MaxDistance = local_14; {
fVar8 = maths::distance_to_flipper(&ray1, &ray2); NextBallPosition = dstRay.Origin;
if (fVar8 < 1e+09) { NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
pvVar7 = &this->NextBallPosition; NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
pvVar7->X = ray2.Origin.X; vector_type* linePtr;
(this->NextBallPosition).Y = ray2.Origin.Y; if (FlipperFlag == 2)
(this->NextBallPosition).Z = ray2.Origin.Z; {
pvVar7->X = pvVar7->X - ray1.Direction.X * 1e-05f; linePtr = &lineB.PerpendicularL;
pfVar2 = &(this->NextBallPosition).Y; CollisionFlag1 = AngleMax <= 0.0;
*pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05f;
uVar5 = this->AngleMax > 0.0;
pvVar7 = &this->Unknown17V;
if (this->FlipperFlag == 2) {
plVar6 = &lineB.PerpendicularL;
this->Unknown15 = (uVar5 == 0);
} }
else { else
this->Unknown15 = uVar5; {
plVar6 = &lineA.PerpendicularL; CollisionFlag1 = AngleMax > 0.0;
linePtr = &lineA.PerpendicularL;
} }
goto LAB_0101bab7; CollisionLinePerp = *linePtr;
CollisionDirection = dstRay.Direction;
return distance;
} }
local_10 = local_10 + this->Unknown40F; timeNow = timeNow + CollisionTimeAdvance;
local_8 = local_8 + local_18; posX = posX + posXAdvance;
local_c = local_c + local_1c; posY = posY + posYAdvance;
fVar8 = ogRay->TimeDelta + ogRay->TimeNow;
uVar3 = fVar8 <= local_10;
} }
} }
else { else
this->Unknown44 = 0; {
EdgeCollisionFlag = 0;
} }
return 1e+09; return 1e+09;
} }
void TFlipperEdge::EdgeCollision(TBall* ball, float coef) void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
{ {
Unknown44 = 1; EdgeCollisionFlag = 1;
if (!FlipperFlag || !Unknown16 || Unknown15) if (!FlipperFlag || !CollisionFlag2 || CollisionFlag1)
{ {
float collMult = 0.0; float collMult = 0.0;
if (Unknown15) if (CollisionFlag1)
{ {
float dx = NextBallPosition.X - RotOrigin.X; float dx = NextBallPosition.X - RotOrigin.X;
float dy = NextBallPosition.Y - RotOrigin.Y; float dy = NextBallPosition.Y - RotOrigin.Y;
@ -336,12 +314,12 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
{ {
float v11; float v11;
float v20 = sqrt(distance / DistanceDivSq) * (fabs(AngleMax) / AngleMult); float v20 = sqrt(distance / DistanceDivSq) * (fabs(AngleMax) / AngleMult);
float dot1 = maths::DotProduct(&Unknown17V, &CollisionDirection); float dot1 = maths::DotProduct(&CollisionLinePerp, &CollisionDirection);
if (dot1 >= 0.0) if (dot1 >= 0.0)
v11 = dot1 * v20; v11 = dot1 * v20;
else else
v11 = 0.0; v11 = 0.0;
collMult = v11 * Unknown32F; collMult = v11 * CollisionMult;
} }
} }
@ -372,9 +350,9 @@ void TFlipperEdge::place_in_grid()
{ {
float x0 = RotOrigin.X - CirclebaseRadius; float x0 = RotOrigin.X - CirclebaseRadius;
float y0 = RotOrigin.Y - CirclebaseRadius; float y0 = RotOrigin.Y - CirclebaseRadius;
float x1 = CirclebaseRadius + RotOrigin.X; float x1 = RotOrigin.X + CirclebaseRadius;
float y1 = RotOrigin.Y + CirclebaseRadius;
float v1 = RotOrigin.Y + CirclebaseRadius;
float v2 = T1Src.X - CircleT1Radius; float v2 = T1Src.X - CircleT1Radius;
if (v2 < x0) if (v2 < x0)
x0 = v2; x0 = v2;
@ -383,31 +361,30 @@ void TFlipperEdge::place_in_grid()
if (v3 < y0) if (v3 < y0)
y0 = v3; y0 = v3;
float v4 = CircleT1Radius + T1Src.X; float v4 = T1Src.X + CircleT1Radius;
if (v4 > x1) if (v4 > x1)
x1 = v4; x1 = v4;
float v5 = T1Src.Y + CircleT1Radius; float v5 = T1Src.Y + CircleT1Radius;
if (v5 > v1) if (v5 > y1)
v1 = v5; y1 = v5;
float v6 = Unknown36V.X - CircleT1Radius; float v6 = T2Src.X - CircleT1Radius;
if (v6 < x0) if (v6 < x0)
x0 = v6; x0 = v6;
float v7 = Unknown36V.Y - CircleT1Radius; float v7 = T2Src.Y - CircleT1Radius;
if (v7 < y0) if (v7 < y0)
y0 = v7; y0 = v7;
float v8 = Unknown36V.X + CircleT1Radius; float v8 = T2Src.X + CircleT1Radius;
if (v8 > x1) if (v8 > x1)
x1 = v8; x1 = v8;
float v9 = CircleT1Radius + Unknown36V.Y; float v9 = T2Src.Y + CircleT1Radius;
if (v9 > v1) if (v9 > y1)
v1 = v9; y1 = v9;
float y1 = v1;
TTableLayer::edges_insert_square(y0, x0, y1, x1, this, nullptr); TTableLayer::edges_insert_square(y0, x0, y1, x1, this, nullptr);
} }
@ -447,7 +424,7 @@ float TFlipperEdge::flipper_angle(float timeNow)
angle = -angle; angle = -angle;
if (angle >= 0.0000001) if (angle >= 0.0000001)
angle = (timeNow - TimeAngle) / angle; angle = (timeNow - InputTime) / angle;
else else
angle = 1.0; angle = 1.0;
@ -459,7 +436,7 @@ float TFlipperEdge::flipper_angle(float timeNow)
int TFlipperEdge::is_ball_inside(float x, float y) int TFlipperEdge::is_ball_inside(float x, float y)
{ {
vector_type ptTest{}; vector_type testPoint{};
float dx = RotOrigin.X - x; float dx = RotOrigin.X - x;
float dy = RotOrigin.Y - y; float dy = RotOrigin.Y - y;
if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0 && if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0 &&
@ -469,15 +446,16 @@ int TFlipperEdge::is_ball_inside(float x, float y)
dy * dy + dx * dx <= CirclebaseRadiusSq || dy * dy + dx * dx <= CirclebaseRadiusSq ||
(T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq) (T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq)
{ {
float flipperLR = AngleMax < 0.0 ? -1 : 1;
if (FlipperFlag == 1) if (FlipperFlag == 1)
ptTest = AngleMax < 0.0 ? B1 : B2; testPoint = AngleMax < 0.0 ? B1 : B2;
else if (FlipperFlag == 2) else if (FlipperFlag == 2)
ptTest = AngleMax < 0.0 ? A2 : A1; testPoint = AngleMax < 0.0 ? A2 : A1;
else else
ptTest = T1; testPoint = T1;
if ((y - ptTest.Y) * (RotOrigin.X - ptTest.X) - if (((y - testPoint.Y) * (RotOrigin.X - testPoint.X) -
(x - ptTest.X) * (RotOrigin.Y - ptTest.Y) >= 0.0f) (x - testPoint.X) * (RotOrigin.Y - testPoint.Y)) * flipperLR < 0.0)
return 4; return 4;
return 5; return 5;
} }
@ -489,24 +467,24 @@ void TFlipperEdge::SetMotion(int code, float value)
switch (code) switch (code)
{ {
case 1: case 1:
this->Angle2 = flipper_angle(value); Angle2 = flipper_angle(value);
this->Angle1 = this->AngleMax; Angle1 = AngleMax;
this->AngleMult = this->BmpCoef1; AngleMult = BmpCoef1;
break; break;
case 2: case 2:
this->Angle2 = flipper_angle(value); Angle2 = flipper_angle(value);
this->Angle1 = 0.0; Angle1 = 0.0;
this->AngleMult = this->BmpCoef2; AngleMult = BmpCoef2;
break; break;
case 1024: case 1024:
this->FlipperFlag = 0; FlipperFlag = 0;
this->Angle1 = 0.0; Angle1 = 0.0;
return; return;
default: break; default: break;
} }
if (!this->FlipperFlag) if (!FlipperFlag)
this->TimeAngle = value; InputTime = value;
this->FlipperFlag = code; FlipperFlag = code;
this->Unknown46F = this->AngleMult + this->TimeAngle; AngleStopTime = AngleMult + InputTime;
} }

View file

@ -8,7 +8,7 @@ class TFlipperEdge : public TEdgeSegment
{ {
public: public:
TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table, TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table,
vector_type* origin, vector_type* vecT, vector_type* vec3, float bmpCoef1, float bmpCoef2, float a11, vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, float collMult,
float c4F, float c5F); float c4F, float c5F);
void port_draw() override; void port_draw() override;
float FindCollisionDistance(ray_type* ray) override; float FindCollisionDistance(ray_type* ray) override;
@ -33,22 +33,22 @@ public:
float AngleMax; float AngleMax;
float Angle2; float Angle2;
float Angle1; float Angle1;
int Unknown15; int CollisionFlag1;
int Unknown16; int CollisionFlag2;
vector_type Unknown17V; vector_type CollisionLinePerp;
vector_type A1Src; vector_type A1Src;
vector_type A2Src; vector_type A2Src;
vector_type B1Src; vector_type B1Src;
vector_type B2Src; vector_type B2Src;
float Unknown32F; float CollisionMult;
vector_type T1Src; vector_type T1Src;
vector_type Unknown36V; vector_type T2Src;
float DistanceDivSq; float DistanceDivSq;
float Unknown40F; float CollisionTimeAdvance;
vector_type CollisionDirection; vector_type CollisionDirection;
int Unknown44; int EdgeCollisionFlag;
float TimeAngle; float InputTime;
float Unknown46F; float AngleStopTime;
float AngleMult; float AngleMult;
float BmpCoef1; float BmpCoef1;
float BmpCoef2; float BmpCoef2;

View file

@ -2,6 +2,7 @@
#include "maths.h" #include "maths.h"
#include "TBall.h" #include "TBall.h"
#include "TFlipperEdge.h"
void maths::enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) void maths::enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect)
@ -341,5 +342,69 @@ void maths::RotatePt(vector_type* point, float sin, float cos, vector_type* orig
float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2) float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2)
{ {
return 0; auto distance = 1000000000.0f;
auto distanceType = -1;
auto newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineA);
if (newDistance < 1000000000.0)
{
distance = newDistance;
distanceType = 0;
}
newDistance = ray_intersect_circle(ray1, &TFlipperEdge::circlebase);
if (newDistance < distance)
{
distance = newDistance;
distanceType = 2;
}
newDistance = ray_intersect_circle(ray1, &TFlipperEdge::circleT1);
if (newDistance < distance)
{
distance = newDistance;
distanceType = 3;
}
newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineB);
if (newDistance < distance)
{
distance = newDistance;
distanceType = 1;
}
if (!ray2 || distance >= 1000000000.0)
return distance;
if (distanceType != -1)
{
vector_type* nextOrigin;
if (distanceType)
{
if (distanceType != 1)
{
float dirY;
ray2->Origin.X = distance * ray1->Direction.X + ray1->Origin.X;
ray2->Origin.Y = distance * ray1->Direction.Y + ray1->Origin.Y;
if (distanceType == 2)
{
ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circlebase.Center.X;
dirY = ray2->Origin.Y - TFlipperEdge::circlebase.Center.Y;
}
else
{
ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circleT1.Center.X;
dirY = ray2->Origin.Y - TFlipperEdge::circleT1.Center.Y;
}
ray2->Direction.Y = dirY;
normalize_2d(&ray2->Direction);
return distance;
}
ray2->Direction = TFlipperEdge::lineB.PerpendicularL;
nextOrigin = &TFlipperEdge::lineB.RayIntersect;
}
else
{
ray2->Direction = TFlipperEdge::lineA.PerpendicularL;
nextOrigin = &TFlipperEdge::lineA.RayIntersect;
}
ray2->Origin = *nextOrigin;
return distance;
}
return 1000000000.0;
} }

View file

@ -9,7 +9,7 @@ class pb
{ {
public: public:
static int time_ticks; static int time_ticks;
static float ball_speed_limit; static float ball_speed_limit, time_now;
static int cheat_mode, game_mode; static int cheat_mode, game_mode;
static datFileStruct* record_table; static datFileStruct* record_table;
static TPinballTable* MainTable; static TPinballTable* MainTable;
@ -39,7 +39,7 @@ public:
static float collide(float timeNow, float timeDelta, TBall* ball); static float collide(float timeNow, float timeDelta, TBall* ball);
private : private :
static int demo_mode, mode_countdown_; static int demo_mode, mode_countdown_;
static float time_now, time_next; static float time_next;
static high_score_struct highscore_table[5]; static high_score_struct highscore_table[5];
static int state; static int state;
}; };