1
0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-24 19:52: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 "TCircle.h"
#include "TBall.h"
#include "TCollisionComponent.h"
#include "TTableLayer.h"
TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, vector_type* center,
float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag)
{
@ -24,3 +28,8 @@ void TCircle::EdgeCollision(TBall* ball, float coef)
maths::normalize_2d(&direction);
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 FindCollisionDistance(ray_type* ray) 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 "TCollisionComponent.h"
#include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "TEdgeSegment.h"
#include "TPinballTable.h"

View File

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

View File

@ -1,7 +1,12 @@
#include "pch.h"
#include "TEdgeManager.h"
#include "maths.h"
#include "objlist_class.h"
#include "TBall.h"
#include "TEdgeBox.h"
#include "TEdgeSegment.h"
#include "TTableLayer.h"
TEdgeManager::TEdgeManager(float posX, float posY, float width, float height)
@ -137,129 +142,126 @@ float TEdgeManager::FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegme
}
}
}
else
else if (rayBoxX == rayEndBoxX)
{
if (rayBoxX == rayEndBoxX)
if (rayDirY == 1)
{
if (rayDirY == 1)
for (auto indexY = rayBoxY; indexY <= rayEndBoxY; indexY++)
{
for (auto indexY = rayBoxY; indexY <= rayEndBoxY; indexY++)
{
edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex);
}
}
else
{
for (auto indexY = rayBoxY; indexY >= rayEndBoxY; indexY--)
{
edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex);
}
edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex);
}
}
else
{
auto rayDyDX = (rayY - rayEndY) / (rayX - rayEndX);
auto indexX = rayBoxX;
auto indexY = rayBoxY;
auto bresIndexX = rayBoxX + 1;
auto bresIndexY = rayBoxY + 1;
auto bresXAdd = rayY - rayDyDX * rayX;
edgeIndex = TestGridBox(rayBoxX, rayBoxY, &distance, edge, ray, ball, 0);
if (rayDirX == 1)
for (auto indexY = rayBoxY; indexY >= rayEndBoxY; indexY--)
{
if (rayDirY == 1)
{
do
{
auto yCoord = bresIndexY * AdvanceY + Y;
auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord >= yCoord)
{
if (xCoord == yCoord)
{
++indexX;
++bresIndexX;
}
++indexY;
++bresIndexY;
}
else
{
++indexX;
++bresIndexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
}
while (indexX < rayEndBoxX || indexY < rayEndBoxY);
}
else
edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex);
}
}
}
else
{
auto rayDyDX = (rayY - rayEndY) / (rayX - rayEndX);
auto indexX = rayBoxX;
auto indexY = rayBoxY;
auto bresIndexX = rayBoxX + 1;
auto bresIndexY = rayBoxY + 1;
auto bresXAdd = rayY - rayDyDX * rayX;
edgeIndex = TestGridBox(rayBoxX, rayBoxY, &distance, edge, ray, ball, 0);
if (rayDirX == 1)
{
if (rayDirY == 1)
{
do
{
do
auto yCoord = bresIndexY * AdvanceY + Y;
auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord >= yCoord)
{
auto yCoord = indexY * AdvanceY + Y;
auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord <= yCoord)
{
if (xCoord == yCoord)
{
++indexX;
++bresIndexX;
}
--indexY;
}
else
if (xCoord == yCoord)
{
++indexX;
++bresIndexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
++indexY;
++bresIndexY;
}
while (indexX < rayEndBoxX || indexY > rayEndBoxY);
else
{
++indexX;
++bresIndexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
}
while (indexX < rayEndBoxX || indexY < rayEndBoxY);
}
else
{
if (rayDirY == 1)
do
{
do
auto yCoord = indexY * AdvanceY + Y;
auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord <= yCoord)
{
auto yCoord = bresIndexY * AdvanceY + Y;
auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord >= yCoord)
if (xCoord == yCoord)
{
if (xCoord == yCoord)
--indexX;
++indexY;
++bresIndexY;
++indexX;
++bresIndexX;
}
else
{
--indexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
--indexY;
}
while (indexX > rayEndBoxX || indexY < rayEndBoxY);
else
{
++indexX;
++bresIndexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
}
else
while (indexX < rayEndBoxX || indexY > rayEndBoxY);
}
}
else
{
if (rayDirY == 1)
{
do
{
do
auto yCoord = bresIndexY * AdvanceY + Y;
auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord >= yCoord)
{
auto yCoord = indexY * AdvanceY + Y;
auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord <= yCoord)
{
if (xCoord == yCoord)
--indexX;
--indexY;
}
else
{
if (xCoord == yCoord)
--indexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
++indexY;
++bresIndexY;
}
while (indexX > rayEndBoxX || indexY > rayEndBoxY);
else
{
--indexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
}
while (indexX > rayEndBoxX || indexY < rayEndBoxY);
}
else
{
do
{
auto yCoord = indexY * AdvanceY + Y;
auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord <= yCoord)
{
if (xCoord == yCoord)
--indexX;
--indexY;
}
else
{
--indexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
}
while (indexX > rayEndBoxX || indexY > rayEndBoxY);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,2 +1,86 @@
#include "pch.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
#include "TCollisionComponent.h"
class TOneway :
public TCollisionComponent
class TLine;
class TOneway : public TCollisionComponent
{
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;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,2 +1,99 @@
#include "pch.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 :
public TCollisionComponent
{
protected:
TRollover(TPinballTable* table, int groupIndex, bool createWall);
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 "loader.h"
#include "objlist_class.h"
#include "proj.h"
#include "render.h"
#include "TBall.h"
#include "TLine.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,
field_effect_type* field)
{
float widthM = edge_manager->AdvanceX * 0.001f;
float heightM = edge_manager->AdvanceY * 0.001f;
float widthM = static_cast<float>(static_cast<int>(edge_manager->AdvanceX * 0.001f)); // Sic
float heightM = static_cast<float>(static_cast<int>(edge_manager->AdvanceY * 0.001f));
float xMin = x0 - widthM;
float xMax = x1 + widthM;
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);
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)
{
float boxY = static_cast<float>(yMinBox) * edge_manager->AdvanceY + edge_manager->Y;
for (int indexY = yMinBox; indexY <= yMaxBox; ++indexY)
{
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;
}
}
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"
struct circle_type;
class TPinballTable;
class TEdgeManager;
struct gdrv_bitmap8;
@ -10,14 +11,15 @@ struct gdrv_bitmap8;
class TTableLayer :
public TCollisionComponent
{
public:
public:
TTableLayer(TPinballTable* table);
~TTableLayer() override;
int FieldEffect(TBall* ball, vector_type* vecDst) override;
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;
float Unknown1F;
float Unknown2F;

View File

@ -1,2 +1,25 @@
#include "pch.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:
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)
{
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)
{
if (code == 63)
control_skill_shot_lights_tag.Component->Message(20, 0.0);
}
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;
}
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

@ -42,7 +42,7 @@ struct __declspec(align(4)) line_type
float PreComp1;
float OriginX;
float OriginY;
vector_type RayIntersect;
vector_type RayIntersect;
};
@ -59,5 +59,7 @@ public:
static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec);
static float magnitude(vector_type* vec);
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 "midi.h"
#include "nudge.h"
#include "objlist_class.h"
#include "options.h"
#include "timer.h"
#include "winmain.h"
#include "resource.h"
#include "TBall.h"
#include "TDemo.h"
#include "TEdgeSegment.h"
#include "TLightGroup.h"
#include "TPlunger.h"
#include "TTableLayer.h"
@ -623,6 +625,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball)
TEdgeSegment* edge = nullptr;
auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge);
ball->EdgeCollisionCount = 0;
if (distance >= 1000000000.0)
{
maxDistance = timeDelta * ball->Speed;