From d19fb0476aeb2cf2e34da7432d593a13a909f45e Mon Sep 17 00:00:00 2001 From: oz Date: Fri, 8 Jan 2021 18:50:12 +0300 Subject: [PATCH] TRollover, TOneway, TLightRollover, TTripwire, TEdgeManager ready. --- Doc/FuncStats.xlsx | Bin 38203 -> 38440 bytes SpaceCadetPinball/TCircle.cpp | 9 ++ SpaceCadetPinball/TCircle.h | 5 +- SpaceCadetPinball/TCollisionComponent.cpp | 2 + SpaceCadetPinball/TCollisionComponent.h | 4 +- SpaceCadetPinball/TEdgeManager.cpp | 188 +++++++++++----------- SpaceCadetPinball/TEdgeManager.h | 2 +- SpaceCadetPinball/TEdgeSegment.cpp | 11 +- SpaceCadetPinball/TEdgeSegment.h | 7 +- SpaceCadetPinball/TLightRollover.cpp | 69 ++++++++ SpaceCadetPinball/TLightRollover.h | 13 +- SpaceCadetPinball/TLine.cpp | 47 +++--- SpaceCadetPinball/TOneway.cpp | 84 ++++++++++ SpaceCadetPinball/TOneway.h | 17 +- SpaceCadetPinball/TPinballComponent.cpp | 4 +- SpaceCadetPinball/TPinballComponent.h | 4 +- SpaceCadetPinball/TPinballTable.cpp | 1 + SpaceCadetPinball/TPinballTable.h | 2 +- SpaceCadetPinball/TPlunger.h | 1 + SpaceCadetPinball/TRollover.cpp | 97 +++++++++++ SpaceCadetPinball/TRollover.h | 18 ++- SpaceCadetPinball/TTableLayer.cpp | 133 ++++++++++++++- SpaceCadetPinball/TTableLayer.h | 8 +- SpaceCadetPinball/TTripwire.cpp | 23 +++ SpaceCadetPinball/TTripwire.h | 7 +- SpaceCadetPinball/control.cpp | 22 +++ SpaceCadetPinball/maths.cpp | 5 + SpaceCadetPinball/maths.h | 6 +- SpaceCadetPinball/pb.cpp | 3 + 29 files changed, 632 insertions(+), 160 deletions(-) diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index 31388c38e3087233252b48ddf9e51eba504cd591..bd26638bd8cee3183f2a90adf2cac35e947f71e5 100644 GIT binary patch delta 31770 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 Y7~MK1zBxe+Z8x4ck?Ce}9O{?<58&$oI{*Lx delta 31520 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 diff --git a/SpaceCadetPinball/TCircle.cpp b/SpaceCadetPinball/TCircle.cpp index 8800cdc..3d51e94 100644 --- a/SpaceCadetPinball/TCircle.cpp +++ b/SpaceCadetPinball/TCircle.cpp @@ -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); +} diff --git a/SpaceCadetPinball/TCircle.h b/SpaceCadetPinball/TCircle.h index 779128c..a919a77 100644 --- a/SpaceCadetPinball/TCircle.h +++ b/SpaceCadetPinball/TCircle.h @@ -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; }; diff --git a/SpaceCadetPinball/TCollisionComponent.cpp b/SpaceCadetPinball/TCollisionComponent.cpp index efb9aff..b4f2156 100644 --- a/SpaceCadetPinball/TCollisionComponent.cpp +++ b/SpaceCadetPinball/TCollisionComponent.cpp @@ -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" diff --git a/SpaceCadetPinball/TCollisionComponent.h b/SpaceCadetPinball/TCollisionComponent.h index ba097e7..db891ad 100644 --- a/SpaceCadetPinball/TCollisionComponent.h +++ b/SpaceCadetPinball/TCollisionComponent.h @@ -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); diff --git a/SpaceCadetPinball/TEdgeManager.cpp b/SpaceCadetPinball/TEdgeManager.cpp index 0d98a37..a0353e7 100644 --- a/SpaceCadetPinball/TEdgeManager.cpp +++ b/SpaceCadetPinball/TEdgeManager.cpp @@ -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); } } } diff --git a/SpaceCadetPinball/TEdgeManager.h b/SpaceCadetPinball/TEdgeManager.h index d203862..00fb1b2 100644 --- a/SpaceCadetPinball/TEdgeManager.h +++ b/SpaceCadetPinball/TEdgeManager.h @@ -1,7 +1,7 @@ #pragma once #include "TCollisionComponent.h" -#include "TEdgeSegment.h" +struct ray_type; class TEdgeBox; struct field_effect_type diff --git a/SpaceCadetPinball/TEdgeSegment.cpp b/SpaceCadetPinball/TEdgeSegment.cpp index 2ab031a..da1cfbf 100644 --- a/SpaceCadetPinball/TEdgeSegment.cpp +++ b/SpaceCadetPinball/TEdgeSegment.cpp @@ -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() diff --git a/SpaceCadetPinball/TEdgeSegment.h b/SpaceCadetPinball/TEdgeSegment.h index cf2ac91..4cec022 100644 --- a/SpaceCadetPinball/TEdgeSegment.h +++ b/SpaceCadetPinball/TEdgeSegment.h @@ -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 { diff --git a/SpaceCadetPinball/TLightRollover.cpp b/SpaceCadetPinball/TLightRollover.cpp index 71e40f3..1b2cbe9 100644 --- a/SpaceCadetPinball/TLightRollover.cpp +++ b/SpaceCadetPinball/TLightRollover.cpp @@ -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(ListBitmap->Get(0))); + } + } +} + +void TLightRollover::delay_expired(int timerId, void* caller) +{ + auto roll = static_cast(caller); + render::sprite_set_bitmap(roll->RenderSprite, nullptr); + roll->Timer = 0; +} diff --git a/SpaceCadetPinball/TLightRollover.h b/SpaceCadetPinball/TLightRollover.h index 886e1ac..52a8d5b 100644 --- a/SpaceCadetPinball/TLightRollover.h +++ b/SpaceCadetPinball/TLightRollover.h @@ -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; }; diff --git a/SpaceCadetPinball/TLine.cpp b/SpaceCadetPinball/TLine.cpp index e67707b..71f45e9 100644 --- a/SpaceCadetPinball/TLine.cpp +++ b/SpaceCadetPinball/TLine.cpp @@ -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); } diff --git a/SpaceCadetPinball/TOneway.cpp b/SpaceCadetPinball/TOneway.cpp index 6ead957..5454756 100644 --- a/SpaceCadetPinball/TOneway.cpp +++ b/SpaceCadetPinball/TOneway.cpp @@ -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; +} diff --git a/SpaceCadetPinball/TOneway.h b/SpaceCadetPinball/TOneway.h index fa20778..ea9f316 100644 --- a/SpaceCadetPinball/TOneway.h +++ b/SpaceCadetPinball/TOneway.h @@ -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]; }; diff --git a/SpaceCadetPinball/TPinballComponent.cpp b/SpaceCadetPinball/TPinballComponent.cpp index 9ceb066..e312144 100644 --- a/SpaceCadetPinball/TPinballComponent.cpp +++ b/SpaceCadetPinball/TPinballComponent.cpp @@ -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; } diff --git a/SpaceCadetPinball/TPinballComponent.h b/SpaceCadetPinball/TPinballComponent.h index c5db926..25daaa5 100644 --- a/SpaceCadetPinball/TPinballComponent.h +++ b/SpaceCadetPinball/TPinballComponent.h @@ -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; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index aebcbc5..1805ff8 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -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" diff --git a/SpaceCadetPinball/TPinballTable.h b/SpaceCadetPinball/TPinballTable.h index 1b538b3..11d4bbf 100644 --- a/SpaceCadetPinball/TPinballTable.h +++ b/SpaceCadetPinball/TPinballTable.h @@ -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); diff --git a/SpaceCadetPinball/TPlunger.h b/SpaceCadetPinball/TPlunger.h index 5ce1bdc..9419239 100644 --- a/SpaceCadetPinball/TPlunger.h +++ b/SpaceCadetPinball/TPlunger.h @@ -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; diff --git a/SpaceCadetPinball/TRollover.cpp b/SpaceCadetPinball/TRollover.cpp index 2dd2273..f1f3faa 100644 --- a/SpaceCadetPinball/TRollover.cpp +++ b/SpaceCadetPinball/TRollover.cpp @@ -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(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(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(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(caller); + roll->UnknownBaseFlag2 = 1; +} diff --git a/SpaceCadetPinball/TRollover.h b/SpaceCadetPinball/TRollover.h index cf993a5..b6ac262 100644 --- a/SpaceCadetPinball/TRollover.h +++ b/SpaceCadetPinball/TRollover.h @@ -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]; }; diff --git a/SpaceCadetPinball/TTableLayer.cpp b/SpaceCadetPinball/TTableLayer.cpp index f3bd644..ce0b8ff 100644 --- a/SpaceCadetPinball/TTableLayer.cpp +++ b/SpaceCadetPinball/TTableLayer.cpp @@ -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(static_cast(edge_manager->AdvanceX * 0.001f)); // Sic + float heightM = static_cast(static_cast(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(xMinBox) * edge_manager->AdvanceX + edge_manager->X; - float boxY = static_cast(yMinBox) * edge_manager->AdvanceY + edge_manager->Y; - for (int indexX = xMinBox; indexX <= xMaxBox; ++indexX) { + float boxY = static_cast(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(dirX) * edge_manager->AdvanceX + edge_manager->X; + for (auto indexX = dirX; indexX <= xMaxBox; ++indexX) + { + vec1.Y = static_cast(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; + } +} diff --git a/SpaceCadetPinball/TTableLayer.h b/SpaceCadetPinball/TTableLayer.h index d8bf9a9..d858ab0 100644 --- a/SpaceCadetPinball/TTableLayer.h +++ b/SpaceCadetPinball/TTableLayer.h @@ -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; diff --git a/SpaceCadetPinball/TTripwire.cpp b/SpaceCadetPinball/TTripwire.cpp index ae80677..0e4dfc0 100644 --- a/SpaceCadetPinball/TTripwire.cpp +++ b/SpaceCadetPinball/TTripwire.cpp @@ -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); + } +} diff --git a/SpaceCadetPinball/TTripwire.h b/SpaceCadetPinball/TTripwire.h index 3b156e3..d886ec8 100644 --- a/SpaceCadetPinball/TTripwire.h +++ b/SpaceCadetPinball/TTripwire.h @@ -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; }; diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index d6735df..26ad38d 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -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(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(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) diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 317eb0f..3591832 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -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); +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index ed5752f..a1fd4a1 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -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); }; diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 371e460..1bcb665 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -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;