1
0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-25 04:02:30 +01:00

TRollover, TOneway, TLightRollover, TTripwire, TEdgeManager ready.

This commit is contained in:
oz 2021-01-08 18:50:12 +03:00
parent 9bd064bf15
commit d19fb0476a
29 changed files with 632 additions and 160 deletions

Binary file not shown.

View File

@ -1,6 +1,10 @@
#include "pch.h" #include "pch.h"
#include "TCircle.h" #include "TCircle.h"
#include "TBall.h"
#include "TCollisionComponent.h"
#include "TTableLayer.h"
TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, vector_type* center, TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, vector_type* center,
float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag) float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag)
{ {
@ -24,3 +28,8 @@ void TCircle::EdgeCollision(TBall* ball, float coef)
maths::normalize_2d(&direction); maths::normalize_2d(&direction);
CollisionComponent->Collision(ball, &nextPosition, &direction, coef, this); CollisionComponent->Collision(ball, &nextPosition, &direction, coef, this);
} }
void TCircle::place_in_grid()
{
TTableLayer::edges_insert_circle(&Circle, this, nullptr);
}

View File

@ -12,8 +12,5 @@ public:
float radius); float radius);
float FindCollisionDistance(ray_type* ray) override; float FindCollisionDistance(ray_type* ray) override;
void EdgeCollision(TBall* ball, float coef) override; void EdgeCollision(TBall* ball, float coef) override;
void place_in_grid() override;
void place_in_grid() override
{
}
}; };

View File

@ -1,6 +1,8 @@
#include "pch.h" #include "pch.h"
#include "TCollisionComponent.h" #include "TCollisionComponent.h"
#include "loader.h" #include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "TEdgeSegment.h" #include "TEdgeSegment.h"
#include "TPinballTable.h" #include "TPinballTable.h"

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "objlist_class.h"
#include "TPinballComponent.h" #include "TPinballComponent.h"
class objlist_class;
struct vector_type; struct vector_type;
class TEdgeSegment; class TEdgeSegment;
class TBall; class TBall;
@ -20,7 +20,7 @@ public:
int SoundIndex1; int SoundIndex1;
TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall); TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall);
~TCollisionComponent(); ~TCollisionComponent() override;
void port_draw() override; void port_draw() override;
virtual void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, virtual void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge); TEdgeSegment* edge);

View File

@ -1,7 +1,12 @@
#include "pch.h" #include "pch.h"
#include "TEdgeManager.h" #include "TEdgeManager.h"
#include "maths.h"
#include "objlist_class.h"
#include "TBall.h"
#include "TEdgeBox.h" #include "TEdgeBox.h"
#include "TEdgeSegment.h"
#include "TTableLayer.h" #include "TTableLayer.h"
TEdgeManager::TEdgeManager(float posX, float posY, float width, float height) TEdgeManager::TEdgeManager(float posX, float posY, float width, float height)
@ -137,9 +142,7 @@ float TEdgeManager::FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegme
} }
} }
} }
else else if (rayBoxX == rayEndBoxX)
{
if (rayBoxX == rayEndBoxX)
{ {
if (rayDirY == 1) if (rayDirY == 1)
{ {
@ -262,7 +265,6 @@ float TEdgeManager::FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegme
} }
} }
} }
}
for (auto edgePtr = EdgeArray; edgeIndex > 0; --edgeIndex, ++edgePtr) for (auto edgePtr = EdgeArray; edgeIndex > 0; --edgeIndex, ++edgePtr)

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "TCollisionComponent.h" #include "TCollisionComponent.h"
#include "TEdgeSegment.h"
struct ray_type;
class TEdgeBox; class TEdgeBox;
struct field_effect_type struct field_effect_type

View File

@ -1,14 +1,17 @@
#include "pch.h" #include "pch.h"
#include "TEdgeSegment.h" #include "TEdgeSegment.h"
#include "objlist_class.h"
#include "TCircle.h" #include "TCircle.h"
#include "TCollisionComponent.h"
#include "TLine.h" #include "TLine.h"
TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned visualFlag) TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned visualFlag)
{ {
this->CollisionComponent = collComp; CollisionComponent = collComp;
this->PinbCompFlag2Ptr = someFlag; PinbCompFlag2Ptr = someFlag;
this->VisualFlag = visualFlag; VisualFlag = visualFlag;
this->ProcessedFlag = 0; ProcessedFlag = 0;
} }
void TEdgeSegment::port_draw() void TEdgeSegment::port_draw()

View File

@ -1,7 +1,8 @@
#pragma once #pragma once
#include "TCollisionComponent.h"
#include "maths.h" class TBall;
#include "TBall.h" class TCollisionComponent;
struct ray_type;
enum class wall_type : int enum class wall_type : int
{ {

View File

@ -1,2 +1,71 @@
#include "pch.h" #include "pch.h"
#include "TLightRollover.h" #include "TLightRollover.h"
#include "control.h"
#include "loader.h"
#include "render.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TLightRollover::TLightRollover(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, false)
{
RolloverFlag = 0;
Timer = 0;
if (ListBitmap != nullptr)
render::sprite_set_bitmap(RenderSprite, nullptr);
build_walls(groupIndex);
FloatArr = *loader::query_float_attribute(groupIndex, 0, 407);
}
int TLightRollover::Message(int code, float value)
{
if (code == 1024)
{
UnknownBaseFlag2 = 1;
RolloverFlag = 0;
if (Timer)
timer::kill(Timer);
Timer = 0;
if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, nullptr);
}
return 0;
}
void TLightRollover::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge)
{
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
ball->RayMaxDistance -= coef;
ball->not_again(edge);
if (!PinballTable->TiltLockFlag)
{
if (RolloverFlag)
{
timer::set(0.1f, this, TimerExpired);
UnknownBaseFlag2 = 0;
RolloverFlag = RolloverFlag == 0;
if (Timer == 0)
Timer = timer::set(FloatArr, this, delay_expired);
}
else
{
loader::play_sound(SoundIndex2);
control::handler(63, this);
RolloverFlag = RolloverFlag == 0;
if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
}
}
}
void TLightRollover::delay_expired(int timerId, void* caller)
{
auto roll = static_cast<TLightRollover*>(caller);
render::sprite_set_bitmap(roll->RenderSprite, nullptr);
roll->Timer = 0;
}

View File

@ -5,7 +5,14 @@ class TLightRollover :
public TRollover public TRollover
{ {
public: public:
TLightRollover(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex) TLightRollover(TPinballTable* table, int groupIndex);
{ ~TLightRollover() override = default;
} int Message(int code, float value) override;
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
static void delay_expired(int timerId, void* caller);
float FloatArr;
int Timer;
}; };

View File

@ -53,10 +53,11 @@ void TLine::EdgeCollision(TBall* ball, float coef)
void TLine::place_in_grid() void TLine::place_in_grid()
{ {
auto xBox0 = TTableLayer::edge_manager->box_x(X0); auto edgeMan = TTableLayer::edge_manager;
auto yBox0 = TTableLayer::edge_manager->box_y(Y0); auto xBox0 = edgeMan->box_x(X0);
auto xBox1 = TTableLayer::edge_manager->box_x(X1); auto yBox0 = edgeMan->box_y(Y0);
auto yBox1 = TTableLayer::edge_manager->box_y(Y1); auto xBox1 = edgeMan->box_x(X1);
auto yBox1 = edgeMan->box_y(Y1);
int dirX = X0 >= X1 ? -1 : 1; int dirX = X0 >= X1 ? -1 : 1;
int dirY = Y0 >= Y1 ? -1 : 1; int dirY = Y0 >= Y1 ? -1 : 1;
@ -66,12 +67,12 @@ void TLine::place_in_grid()
if (dirX == 1) if (dirX == 1)
{ {
while (xBox0 <= xBox1) while (xBox0 <= xBox1)
TTableLayer::edge_manager->add_edge_to_box(xBox0++, yBox0, this); edgeMan->add_edge_to_box(xBox0++, yBox0, this);
} }
else else
{ {
while (xBox0 >= xBox1) while (xBox0 >= xBox1)
TTableLayer::edge_manager->add_edge_to_box(xBox0--, yBox0, this); edgeMan->add_edge_to_box(xBox0--, yBox0, this);
} }
} }
else if (xBox0 == xBox1) else if (xBox0 == xBox1)
@ -81,14 +82,14 @@ void TLine::place_in_grid()
if (yBox0 <= yBox1) if (yBox0 <= yBox1)
{ {
do do
TTableLayer::edge_manager->add_edge_to_box(xBox0, yBox0++, this); edgeMan->add_edge_to_box(xBox0, yBox0++, this);
while (yBox0 <= yBox1); while (yBox0 <= yBox1);
} }
} }
else if (yBox0 >= yBox1) else if (yBox0 >= yBox1)
{ {
do do
TTableLayer::edge_manager->add_edge_to_box(xBox0, yBox0--, this); edgeMan->add_edge_to_box(xBox0, yBox0--, this);
while (yBox0 >= yBox1); while (yBox0 >= yBox1);
} }
} }
@ -99,16 +100,15 @@ void TLine::place_in_grid()
int bresIndexX = xBox0 + 1, bresIndexY = yBox0 + 1; int bresIndexX = xBox0 + 1, bresIndexY = yBox0 + 1;
auto bresDyDx = (Y0 - Y1) / (X0 - X1); auto bresDyDx = (Y0 - Y1) / (X0 - X1);
auto bresXAdd = Y0 - bresDyDx * X0; auto bresXAdd = Y0 - bresDyDx * X0;
TTableLayer::edge_manager->add_edge_to_box(xBox0, yBox0, this); edgeMan->add_edge_to_box(xBox0, yBox0, this);
if (dirX == 1) if (dirX == 1)
{ {
if (dirY == 1) if (dirY == 1)
{ {
do do
{ {
yCoord = bresIndexY * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; yCoord = bresIndexY * edgeMan->AdvanceY + edgeMan->Y;
xCoord = (bresIndexX * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * xCoord = (bresIndexX * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd;
bresDyDx + bresXAdd;
if (xCoord >= yCoord) if (xCoord >= yCoord)
{ {
if (xCoord == yCoord) if (xCoord == yCoord)
@ -124,7 +124,7 @@ void TLine::place_in_grid()
++indexX1; ++indexX1;
++bresIndexX; ++bresIndexX;
} }
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); edgeMan->add_edge_to_box(indexX1, indexY1, this);
} }
while (indexX1 != xBox1 || indexY1 != yBox1); while (indexX1 != xBox1 || indexY1 != yBox1);
} }
@ -132,9 +132,8 @@ void TLine::place_in_grid()
{ {
do do
{ {
yCoord = indexY1 * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; yCoord = indexY1 * edgeMan->AdvanceY + edgeMan->Y;
xCoord = (bresIndexX * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * xCoord = (bresIndexX * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd;
bresDyDx + bresXAdd;
if (xCoord <= yCoord) if (xCoord <= yCoord)
{ {
if (xCoord == yCoord) if (xCoord == yCoord)
@ -149,7 +148,7 @@ void TLine::place_in_grid()
++indexX1; ++indexX1;
++bresIndexX; ++bresIndexX;
} }
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); edgeMan->add_edge_to_box(indexX1, indexY1, this);
} }
while (indexX1 != xBox1 || indexY1 != yBox1); while (indexX1 != xBox1 || indexY1 != yBox1);
} }
@ -160,9 +159,8 @@ void TLine::place_in_grid()
{ {
do do
{ {
xCoord = bresIndexY * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; xCoord = bresIndexY * edgeMan->AdvanceY + edgeMan->Y;
yCoord = (indexX1 * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * yCoord = (indexX1 * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd;
bresDyDx + bresXAdd;
if (yCoord >= xCoord) if (yCoord >= xCoord)
{ {
if (yCoord == xCoord) if (yCoord == xCoord)
@ -174,7 +172,7 @@ void TLine::place_in_grid()
{ {
--indexX1; --indexX1;
} }
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); edgeMan->add_edge_to_box(indexX1, indexY1, this);
} }
while (indexX1 != xBox1 || indexY1 != yBox1); while (indexX1 != xBox1 || indexY1 != yBox1);
} }
@ -182,9 +180,8 @@ void TLine::place_in_grid()
{ {
do do
{ {
yCoord = indexY1 * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; yCoord = indexY1 * edgeMan->AdvanceY + edgeMan->Y;
xCoord = (indexX1 * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * xCoord = (indexX1 * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd;
bresDyDx + bresXAdd;
if (xCoord <= yCoord) if (xCoord <= yCoord)
{ {
if (xCoord == yCoord) if (xCoord == yCoord)
@ -195,7 +192,7 @@ void TLine::place_in_grid()
{ {
--indexX1; --indexX1;
} }
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); edgeMan->add_edge_to_box(indexX1, indexY1, this);
} }
while (indexX1 != xBox1 || indexY1 != yBox1); while (indexX1 != xBox1 || indexY1 != yBox1);
} }

View File

@ -1,2 +1,86 @@
#include "pch.h" #include "pch.h"
#include "TOneway.h" #include "TOneway.h"
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "TBall.h"
#include "TLine.h"
#include "TPinballTable.h"
TOneway::TOneway(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
visualStruct visual{};
vector_type linePt1{}, linePt2{};
loader::query_visual(groupIndex, 0, &visual);
if (visual.FloatArrCount == 2)
{
linePt2.X = visual.FloatArr[0];
linePt2.Y = visual.FloatArr[1];
linePt1.X = visual.FloatArr[2];
linePt1.Y = visual.FloatArr[3];
auto line = new TLine(this, &UnknownBaseFlag2, visual.Flag, &linePt2, &linePt1);
if (line)
{
line->Offset(table->CollisionCompOffset);
line->place_in_grid();
EdgeList->Add(line);
}
line = new TLine(this, &UnknownBaseFlag2, visual.Flag, &linePt1, &linePt2);
Line = line;
if (line)
{
line->Offset(-table->CollisionCompOffset * 0.8f);
Line->place_in_grid();
EdgeList->Add(Line);
}
}
}
void TOneway::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
if (edge == Line)
{
ball->not_again(edge);
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
ball->RayMaxDistance -= coef;
if (!PinballTable->TiltLockFlag)
{
if (SoundIndex1)
loader::play_sound(SoundIndex1);
control::handler(63, this);
}
}
else if (PinballTable->TiltLockFlag)
{
maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F, 1000000000.0, 0.0);
}
else if (maths::basic_collision(
ball,
nextPosition,
direction,
UnknownC4F,
UnknownC5F,
MaxCollisionSpeed,
CollisionMultiplier) > 0.2)
{
if (SoundIndex2)
loader::play_sound(SoundIndex2);
}
}
void TOneway::put_scoring(int index, int score)
{
if (index < 6)
Scores[index] = score;
}
int TOneway::get_scoring(int index)
{
return index < 6 ? Scores[index] : 0;
}

View File

@ -1,11 +1,18 @@
#pragma once #pragma once
#include "TCollisionComponent.h" #include "TCollisionComponent.h"
class TOneway : class TLine;
public TCollisionComponent
class TOneway : public TCollisionComponent
{ {
public: public:
TOneway(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false) TOneway(TPinballTable* table, int groupIndex);
{ ~TOneway() override = default;
} void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
void put_scoring(int index, int score) override;
int get_scoring(int index) override;
TLine* Line;
int Scores[6];
}; };

View File

@ -101,11 +101,11 @@ void TPinballComponent::port_draw()
{ {
} }
void TPinballComponent::put_scoring(int scoreId, int value) void TPinballComponent::put_scoring(int index, int score)
{ {
} }
int TPinballComponent::get_scoring(int score1) int TPinballComponent::get_scoring(int index)
{ {
return 0; return 0;
} }

View File

@ -17,8 +17,8 @@ public:
virtual ~TPinballComponent(); virtual ~TPinballComponent();
virtual int Message(int code, float value); virtual int Message(int code, float value);
virtual void port_draw(); virtual void port_draw();
virtual void put_scoring(int scoreId, int value); virtual void put_scoring(int index, int score);
virtual int get_scoring(int score1); virtual int get_scoring(int index);
__int8 UnknownBaseFlag1; __int8 UnknownBaseFlag1;
__int8 UnknownBaseFlag2; __int8 UnknownBaseFlag2;

View File

@ -5,6 +5,7 @@
#include "control.h" #include "control.h"
#include "loader.h" #include "loader.h"
#include "memory.h" #include "memory.h"
#include "objlist_class.h"
#include "pb.h" #include "pb.h"
#include "pinball.h" #include "pinball.h"
#include "render.h" #include "render.h"

View File

@ -26,7 +26,7 @@ class TPinballTable : public TPinballComponent
{ {
public: public:
TPinballTable(); TPinballTable();
~TPinballTable(); ~TPinballTable() override;
TPinballComponent* find_component(LPCSTR componentName); TPinballComponent* find_component(LPCSTR componentName);
TPinballComponent* find_component(int groupIndex); TPinballComponent* find_component(int groupIndex);
int AddScore(int score); int AddScore(int score);

View File

@ -6,6 +6,7 @@ class TPlunger :
{ {
public: public:
TPlunger(TPinballTable* table, int groupIndex); TPlunger(TPinballTable* table, int groupIndex);
~TPlunger() override = default;
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override; TEdgeSegment* edge) override;
int Message(int code, float value) override; int Message(int code, float value) override;

View File

@ -1,2 +1,99 @@
#include "pch.h" #include "pch.h"
#include "TRollover.h" #include "TRollover.h"
#include "control.h"
#include "gdrv.h"
#include "loader.h"
#include "render.h"
#include "TBall.h"
#include "TEdgeSegment.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TRollover::TRollover(TPinballTable* table, int groupIndex, bool createWall) : TCollisionComponent(
table, groupIndex, createWall)
{
}
TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
RolloverFlag = 0;
if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
build_walls(groupIndex);
}
int TRollover::Message(int code, float value)
{
if (code == 1024)
{
this->UnknownBaseFlag2 = 1;
this->RolloverFlag = 0;
if (this->ListBitmap)
render::sprite_set_bitmap(this->RenderSprite, static_cast<gdrv_bitmap8*>(this->ListBitmap->Get(0)));
}
return 0;
}
void TRollover::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge)
{
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
ball->RayMaxDistance -= coef;
ball->not_again(edge);
gdrv_bitmap8* bmp = nullptr;
if (!PinballTable->TiltLockFlag)
{
if (RolloverFlag)
{
timer::set(0.1f, this, TimerExpired);
UnknownBaseFlag2 = 0;
}
else
{
loader::play_sound(SoundIndex2);
control::handler(63, this);
}
RolloverFlag = RolloverFlag == 0;
if (ListBitmap)
{
if (!RolloverFlag)
bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
render::sprite_set_bitmap(RenderSprite, bmp);
}
}
}
void TRollover::put_scoring(int index, int score)
{
if (index < 2)
Scores[index] = score;
}
int TRollover::get_scoring(int index)
{
return index < 2 ? Scores[index] : 0;
}
void TRollover::build_walls(int groupIndex)
{
visualStruct visual{};
loader::query_visual(groupIndex, 0, &visual);
float* arr1 = loader::query_float_attribute(groupIndex, 0, 600);
TEdgeSegment::install_wall(arr1, this, &UnknownBaseFlag2, visual.Flag, 0.0, 600);
float* arr2 = loader::query_float_attribute(groupIndex, 0, 603);
TEdgeSegment::install_wall(arr2, this, &RolloverFlag, visual.Flag, 0.0, 603);
}
void TRollover::TimerExpired(int timerId, void* caller)
{
auto roll = static_cast<TRollover*>(caller);
roll->UnknownBaseFlag2 = 1;
}

View File

@ -4,8 +4,20 @@
class TRollover : class TRollover :
public TCollisionComponent public TCollisionComponent
{ {
protected:
TRollover(TPinballTable* table, int groupIndex, bool createWall);
public: public:
TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true) TRollover(TPinballTable* table, int groupIndex);
{ ~TRollover() override = default;
} int Message(int code, float value) override;
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
void put_scoring(int index, int score) override;
int get_scoring(int index) override;
void build_walls(int groupIndex);
static void TimerExpired(int timerId, void* caller);
char RolloverFlag;
int Scores[2];
}; };

View File

@ -2,8 +2,10 @@
#include "TTableLayer.h" #include "TTableLayer.h"
#include "loader.h" #include "loader.h"
#include "objlist_class.h"
#include "proj.h" #include "proj.h"
#include "render.h" #include "render.h"
#include "TBall.h"
#include "TLine.h" #include "TLine.h"
#include "TPinballTable.h" #include "TPinballTable.h"
@ -114,8 +116,8 @@ int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst)
void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TEdgeSegment* edge, void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TEdgeSegment* edge,
field_effect_type* field) field_effect_type* field)
{ {
float widthM = edge_manager->AdvanceX * 0.001f; float widthM = static_cast<float>(static_cast<int>(edge_manager->AdvanceX * 0.001f)); // Sic
float heightM = edge_manager->AdvanceY * 0.001f; float heightM = static_cast<float>(static_cast<int>(edge_manager->AdvanceY * 0.001f));
float xMin = x0 - widthM; float xMin = x0 - widthM;
float xMax = x1 + widthM; float xMax = x1 + widthM;
float yMin = y0 - heightM; float yMin = y0 - heightM;
@ -127,10 +129,9 @@ void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TE
int yMaxBox = edge_manager->box_y(yMax); int yMaxBox = edge_manager->box_y(yMax);
float boxX = static_cast<float>(xMinBox) * edge_manager->AdvanceX + edge_manager->X; float boxX = static_cast<float>(xMinBox) * edge_manager->AdvanceX + edge_manager->X;
float boxY = static_cast<float>(yMinBox) * edge_manager->AdvanceY + edge_manager->Y;
for (int indexX = xMinBox; indexX <= xMaxBox; ++indexX) for (int indexX = xMinBox; indexX <= xMaxBox; ++indexX)
{ {
float boxY = static_cast<float>(yMinBox) * edge_manager->AdvanceY + edge_manager->Y;
for (int indexY = yMinBox; indexY <= yMaxBox; ++indexY) for (int indexY = yMinBox; indexY <= yMaxBox; ++indexY)
{ {
if (xMax >= boxX && xMin <= boxX + edge_manager->AdvanceX && if (xMax >= boxX && xMin <= boxX + edge_manager->AdvanceX &&
@ -150,3 +151,127 @@ void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TE
boxX += edge_manager->AdvanceX; boxX += edge_manager->AdvanceX;
} }
} }
void TTableLayer::edges_insert_circle(circle_type* circle, TEdgeSegment* edge, field_effect_type* field)
{
ray_type ray{};
vector_type vec1{};
auto radiusM = sqrt(circle->RadiusSq) + edge_manager->AdvanceX * 0.001f;
auto radiusMSq = radiusM * radiusM;
auto xMin = circle->Center.X - radiusM;
auto yMin = circle->Center.Y - radiusM;
auto xMax = radiusM + circle->Center.X;
auto yMax = radiusM + circle->Center.Y;
auto xMinBox = edge_manager->box_x(xMin);
auto yMinBox = edge_manager->box_y(yMin);
auto xMaxBox = edge_manager->box_x(xMax);
auto yMaxBox = edge_manager->box_y(yMax);
auto dirX = xMinBox - 1 <= 0 ? 0 : xMinBox - 1;
auto dirY = yMinBox - 1 <= 0 ? 0 : yMinBox - 1;
xMaxBox = edge_manager->increment_box_x(xMaxBox);
yMaxBox = edge_manager->increment_box_y(yMaxBox);
vec1.X = static_cast<float>(dirX) * edge_manager->AdvanceX + edge_manager->X;
for (auto indexX = dirX; indexX <= xMaxBox; ++indexX)
{
vec1.Y = static_cast<float>(dirY) * edge_manager->AdvanceY + edge_manager->Y;
for (int indexY = dirY; indexY <= yMaxBox; ++indexY)
{
auto vec1XAdv = vec1.X + edge_manager->AdvanceX;
auto vec1YAdv = vec1.Y + edge_manager->AdvanceY;
if (xMax >= vec1.X && xMin <= vec1XAdv &&
yMax >= vec1.Y && yMin <= vec1YAdv)
{
bool collision = true;
do
{
if (circle->Center.X <= vec1XAdv && circle->Center.X >= vec1.X &&
circle->Center.Y <= vec1YAdv && circle->Center.Y >= vec1.Y)
break;
auto vec2 = vec1;
if (maths::Distance_Squared(vec1, circle->Center) <= radiusMSq)
break;
vec2.X = vec2.X + edge_manager->AdvanceX;
if (maths::Distance_Squared(vec2, circle->Center) <= radiusMSq)
break;
vec2.Y = vec2.Y + edge_manager->AdvanceY;
if (maths::Distance_Squared(vec2, circle->Center) <= radiusMSq)
break;
vec2.X = vec2.X - edge_manager->AdvanceX;
if (maths::Distance_Squared(vec2, circle->Center) <= radiusMSq)
break;
ray.Origin = vec1;
ray.Direction.X = 1.0;
ray.Direction.Y = 0.0;
ray.MaxDistance = edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.X = -1.0;
ray.Origin.X = ray.Origin.X + edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.X = 0.0;
ray.Direction.Y = 1.0;
ray.MaxDistance = edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.Y = -1.0;
ray.Origin.Y = ray.Origin.Y + edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.Y = 0.0;
ray.Direction.X = -1.0;
ray.MaxDistance = edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.X = 1.0;
ray.Origin.X = ray.Origin.X - edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.X = 0.0;
ray.Direction.Y = -1.0;
ray.MaxDistance = edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
ray.Direction.Y = 1.0;
ray.Origin.Y = ray.Origin.Y - edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
break;
collision = false;
}
while (false);
if (collision)
{
if (edge)
{
edge_manager->add_edge_to_box(indexX, indexY, edge);
}
if (field)
{
edge_manager->add_field_to_box(indexX, indexY, field);
}
}
}
vec1.Y += edge_manager->AdvanceY;
}
vec1.X += edge_manager->AdvanceX;
}
}

View File

@ -3,6 +3,7 @@
#include "TEdgeManager.h" #include "TEdgeManager.h"
struct circle_type;
class TPinballTable; class TPinballTable;
class TEdgeManager; class TEdgeManager;
struct gdrv_bitmap8; struct gdrv_bitmap8;
@ -17,6 +18,7 @@ public:
static void edges_insert_square(float y0, float x0, float y1, float x1, TEdgeSegment* edge, static void edges_insert_square(float y0, float x0, float y1, float x1, TEdgeSegment* edge,
field_effect_type* field); field_effect_type* field);
static void edges_insert_circle(circle_type* circle, TEdgeSegment* edge, field_effect_type* field);
gdrv_bitmap8* VisBmp; gdrv_bitmap8* VisBmp;
float Unknown1F; float Unknown1F;

View File

@ -1,2 +1,25 @@
#include "pch.h" #include "pch.h"
#include "TTripwire.h" #include "TTripwire.h"
#include "control.h"
#include "loader.h"
#include "TBall.h"
#include "TPinballTable.h"
TTripwire::TTripwire(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, 1)
{
}
void TTripwire::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge)
{
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
ball->RayMaxDistance -= coef;
ball->not_again(edge);
if (!PinballTable->TiltLockFlag)
{
loader::play_sound(SoundIndex2);
control::handler(63, this);
}
}

View File

@ -5,7 +5,8 @@ class TTripwire :
public TRollover public TRollover
{ {
public: public:
TTripwire(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex) TTripwire(TPinballTable* table, int groupIndex);
{ ~TTripwire() override = default;
} void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
}; };

View File

@ -836,10 +836,32 @@ void control::RightKickerGateControl(int code, TPinballComponent* caller)
void control::DeploymentChuteToEscapeChuteOneWayControl(int code, TPinballComponent* caller) void control::DeploymentChuteToEscapeChuteOneWayControl(int code, TPinballComponent* caller)
{ {
char Buffer[64];
if (code == 63)
{
int count = control_skill_shot_lights_tag.Component->Message(37, 0.0);
if (count)
{
static_cast<TSound*>(control_soundwave3_tag.Component)->Play();
int score = TableG->AddScore(caller->get_scoring(count - 1));
sprintf_s(Buffer, pinball::get_rc_string(21, 0), score);
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(Buffer, 2.0);
if (!light_on(&control_lite56_tag))
{
control_l_trek_lights_tag.Component->Message(34, 0.0);
control_l_trek_lights_tag.Component->Message(20, 0.0);
control_r_trek_lights_tag.Component->Message(34, 0.0);
control_r_trek_lights_tag.Component->Message(20, 0.0);
}
control_skill_shot_lights_tag.Component->Message(44, 1.0);
}
}
} }
void control::DeploymentChuteToTableOneWayControl(int code, TPinballComponent* caller) void control::DeploymentChuteToTableOneWayControl(int code, TPinballComponent* caller)
{ {
if (code == 63)
control_skill_shot_lights_tag.Component->Message(20, 0.0);
} }
void control::DrainBallBlockerControl(int code, TPinballComponent* caller) void control::DrainBallBlockerControl(int code, TPinballComponent* caller)

View File

@ -299,3 +299,8 @@ float maths::basic_collision(TBall* ball, vector_type* nextPosition, vector_type
} }
return projSpeed; return projSpeed;
} }
float maths::Distance_Squared(vector_type vec1, vector_type vec2)
{
return (vec1.Y - vec2.Y) * (vec1.Y - vec2.Y) + (vec1.X - vec2.X) * (vec1.X - vec2.X);
}

View File

@ -59,5 +59,7 @@ public:
static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec); static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec);
static float magnitude(vector_type* vec); static float magnitude(vector_type* vec);
static void vector_add(vector_type* vec1Dst, vector_type* vec2); static void vector_add(vector_type* vec1Dst, vector_type* vec2);
static float basic_collision(TBall* ball, struct vector_type* nextPosition, struct vector_type* direction, float a4, float a5, float maxSpeed, float multiplier); static float basic_collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float a4, float a5,
float maxSpeed, float multiplier);
static float Distance_Squared(vector_type vec1, vector_type vec2);
}; };

View File

@ -11,12 +11,14 @@
#include "loader.h" #include "loader.h"
#include "midi.h" #include "midi.h"
#include "nudge.h" #include "nudge.h"
#include "objlist_class.h"
#include "options.h" #include "options.h"
#include "timer.h" #include "timer.h"
#include "winmain.h" #include "winmain.h"
#include "resource.h" #include "resource.h"
#include "TBall.h" #include "TBall.h"
#include "TDemo.h" #include "TDemo.h"
#include "TEdgeSegment.h"
#include "TLightGroup.h" #include "TLightGroup.h"
#include "TPlunger.h" #include "TPlunger.h"
#include "TTableLayer.h" #include "TTableLayer.h"
@ -623,6 +625,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball)
TEdgeSegment* edge = nullptr; TEdgeSegment* edge = nullptr;
auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge); auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge);
ball->EdgeCollisionCount = 0;
if (distance >= 1000000000.0) if (distance >= 1000000000.0)
{ {
maxDistance = timeDelta * ball->Speed; maxDistance = timeDelta * ball->Speed;