diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 212b8b1f..6f294085 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -45,6 +45,8 @@ add_library(CommonFiles STATIC MapList.cpp MapList.h MatchTypes.h + MovingPlatformPaths.h + MovingPlatformPaths.cpp ObjectBase.cpp ObjectBase.h path.cpp diff --git a/src/common/MovingPlatformPaths.cpp b/src/common/MovingPlatformPaths.cpp new file mode 100644 index 00000000..67210dce --- /dev/null +++ b/src/common/MovingPlatformPaths.cpp @@ -0,0 +1,306 @@ +#include "MovingPlatformPaths.h" + +#include "Game.h" +#include "GameValues.h" +#include "movingplatform.h" +#include "ObjectBase.h" +#include "player.h" + +#include + +extern CGameValues game_values; +extern std::vector players; + +//------------------------------------------------------------------------------ +// Moving Platform Path base class +//------------------------------------------------------------------------------ + +MovingPlatformPath::MovingPlatformPath(float vel, float startX, float startY, float endX, float endY, bool preview) +{ + dVelocity = vel; + + for (short type = 0; type < 2; type++) { + dVelX[type] = 0.0f; + dVelY[type] = 0.0f; + } + + dPathPointX[0] = startX; + dPathPointY[0] = startY; + dPathPointX[1] = endX; + dPathPointY[1] = endY; + + if (preview) { + dPathPointX[0] /= 2.0f; + dPathPointY[0] /= 2.0f; + dPathPointX[1] /= 2.0f; + dPathPointY[1] /= 2.0f; + dVelocity /= 2.0f; + } + + pPlatform = NULL; +} + +void MovingPlatformPath::Reset() +{ + //advance the spawn test platform + if (game_values.spawnstyle == SpawnStyle::Door) { + for (short i = 0; i < 36; i++) + Move(1); + } else if (game_values.spawnstyle == SpawnStyle::Swirl) { + for (short i = 0; i < 50; i++) + Move(1); + } +} + + +//------------------------------------------------------------------------------ +// Straight Path +//------------------------------------------------------------------------------ + +StraightPath::StraightPath(float vel, float startX, float startY, float endX, float endY, bool preview) + : MovingPlatformPath(vel, startX, startY, endX, endY, preview) + , iGoalPoint{0, 0} +{ + iType = 0; + + float dWidth = dPathPointX[1] - dPathPointX[0]; + float dHeight = dPathPointY[1] - dPathPointY[0]; + float dLength = 0.0f; + + //Lock angle to vertical + if (dWidth == 0) { + if (dHeight > 0) + dAngle = HALF_PI; + else + dAngle = THREE_HALF_PI; + + dLength = fabs(dHeight); + } else if (dHeight == 0) { //Lock angle to horizontal + if (dWidth > 0) + dAngle = 0.0f; + else + dAngle = PI; + + dLength = fabs(dWidth); + } else { + dAngle = atan2(dHeight, dWidth); + dLength = sqrt(dHeight * dHeight + dWidth * dWidth); + } + + iSteps = (short)(dLength / dVelocity) + 1; + + for (short type = 0; type < 2; type++) + SetVelocity(type); +} + +bool StraightPath::Move(short type) +{ + dCurrentX[type] += dVelX[type]; + dCurrentY[type] += dVelY[type]; + + if (++iOnStep[type] >= iSteps) { + iOnStep[type] = 0; + + dCurrentX[type] = dPathPointX[iGoalPoint[type]]; + dCurrentY[type] = dPathPointY[iGoalPoint[type]]; + + iGoalPoint[type] = 1 - iGoalPoint[type]; + + SetVelocity(type); + } + + return false; +} + +void StraightPath::SetVelocity(short type) +{ + if (iGoalPoint[type] == 1) { + dVelX[type] = dVelocity * cos(dAngle); + dVelY[type] = dVelocity * sin(dAngle); + } else { + dVelX[type] = -dVelocity * cos(dAngle); + dVelY[type] = -dVelocity * sin(dAngle); + } + + //Fix rounding errors + if (dVelX[type] < 0.01f && dVelX[type] > -0.01f) + dVelX[type] = 0.0f; + + if (dVelY[type] < 0.01f && dVelY[type] > -0.01f) + dVelY[type] = 0.0f; +} + +void StraightPath::Reset() +{ + for (short type = 0; type < 2; type++) { + iOnStep[type] = 0; + + dCurrentX[type] = dPathPointX[0]; + dCurrentY[type] = dPathPointY[0]; + + iGoalPoint[type] = 1; + SetVelocity(type); + } + + MovingPlatformPath::Reset(); +} + + +//------------------------------------------------------------------------------ +// Straight Path Continuous +//------------------------------------------------------------------------------ + +StraightPathContinuous::StraightPathContinuous(float vel, float startX, float startY, float angle, bool preview) : + StraightPath(vel, startX, startY, 0.0f, 0.0f, preview) +{ + iType = 1; + + dAngle = angle; + + for (short type = 0; type < 2; type++) { + iGoalPoint[type] = 1; + SetVelocity(type); + } + + dEdgeX = App::screenWidth; + dEdgeY = App::screenHeight; + + if (preview) { + dEdgeX = App::screenWidth/2; + dEdgeY = App::screenHeight/2; + } +} + +bool StraightPathContinuous::Move(short type) +{ + dCurrentX[type] += dVelX[type]; + dCurrentY[type] += dVelY[type]; + + float dx = dCurrentX[type] - (float)pPlatform->iHalfWidth; + if (dx < 0.0f) + dCurrentX[type] += dEdgeX; + else if (dx >= dEdgeX) + dCurrentX[type] -= dEdgeX; + + if (dCurrentY[type] + (float)pPlatform->iHalfHeight < 0.0f) + dCurrentY[type] += dEdgeY + (float)pPlatform->iHeight; + else if (dCurrentY[type] - (float)pPlatform->iHalfHeight >= dEdgeY) + dCurrentY[type] -= dEdgeY + (float)pPlatform->iHeight; + + return false; +} + +void StraightPathContinuous::Reset() +{ + for (short type = 0; type < 2; type++) { + dCurrentX[type] = dPathPointX[0]; + dCurrentY[type] = dPathPointY[0]; + } + + MovingPlatformPath::Reset(); +} + +//------------------------------------------------------------------------------ +// Ellipse Path +//------------------------------------------------------------------------------ +EllipsePath::EllipsePath(float vel, float angle, float radiusx, float radiusy, float centerx, float centery, bool preview) : + MovingPlatformPath(vel, centerx, centery, 0.0f, 0.0f, preview) +{ + iType = 2; + + dStartAngle = angle; + + if (preview) { + dRadiusX = radiusx / 2.0f; + dRadiusY = radiusy / 2.0f; + dVelocity *= 2.0f; + } else { + dRadiusX = radiusx; + dRadiusY = radiusy; + } + + for (short type = 0; type < 2; type++) { + dAngle[type] = angle; + SetPosition(type); + } +} + +bool EllipsePath::Move(short type) +{ + float dOldCurrentX = dCurrentX[type]; + float dOldCurrentY = dCurrentY[type]; + + dAngle[type] += dVelocity; + + if (dVelocity < 0.0f) { + while (dAngle[type] < 0.0f) + dAngle[type] += TWO_PI; + } else { + while (dAngle[type] >= TWO_PI) + dAngle[type] -= TWO_PI; + } + + SetPosition(type); + + dVelX[type] = dCurrentX[type] - dOldCurrentX; + dVelY[type] = dCurrentY[type] - dOldCurrentY; + + return false; +} + +void EllipsePath::SetPosition(short type) +{ + dCurrentX[type] = dRadiusX * cos(dAngle[type]) + dPathPointX[0]; + dCurrentY[type] = dRadiusY * sin(dAngle[type]) + dPathPointY[0]; +} + +void EllipsePath::Reset() +{ + for (short type = 0; type < 2; type++) { + dAngle[type] = dStartAngle; + SetPosition(type); + } + + MovingPlatformPath::Reset(); +} + +//------------------------------------------------------------------------------ +// Falling path (for falling donut blocks) +//------------------------------------------------------------------------------ + +FallingPath::FallingPath(float startX, float startY) : + MovingPlatformPath(0.0f, startX, startY, 0.0f, 0.0f, false) +{} + +bool FallingPath::Move(short type) +{ + dVelY[type] = CapFallingVelocity(dVelY[type] + GRAVITATION); + + if (pPlatform->fy - pPlatform->iHalfHeight >= App::screenHeight) { + //If a player is standing on this platform, clear him off + for (CPlayer* player : players) { + if (player->platform == pPlatform) { + player->platform = NULL; + player->vely = dVelY[type]; + } + } + + pPlatform->fDead = true; + } + + dCurrentY[type] += dVelY[type]; + + return false; +} + +void FallingPath::Reset() +{ + for (short type = 0; type < 2; type++) { + dCurrentX[type] = dPathPointX[0]; + dCurrentY[type] = dPathPointY[0]; + } + + //Skip correctly setting the path "shadow" as a perf optimization + //This does have the risk of a player spawning inside a falling donut block by accident + //MovingPlatformPath::Reset(); +} diff --git a/src/common/MovingPlatformPaths.h b/src/common/MovingPlatformPaths.h new file mode 100644 index 00000000..b56bf500 --- /dev/null +++ b/src/common/MovingPlatformPaths.h @@ -0,0 +1,107 @@ +#pragma once + +class MovingPlatform; + + +class MovingPlatformPath { +public: + MovingPlatformPath(float vel, float startX, float startY, float endX, float endY, bool preview); + virtual ~MovingPlatformPath() = default; + + virtual bool Move(short type) = 0; + virtual void Reset(); + + void SetPlatform(MovingPlatform* platform) { + pPlatform = platform; + } + + short GetType() const { return iType; } + +protected: + MovingPlatform* pPlatform; + + float dVelocity; + float dVelX[2], dVelY[2]; + + float dPathPointX[2], dPathPointY[2]; + + float dCurrentX[2], dCurrentY[2]; + + short iType; + + friend class MovingPlatform; + friend class CMap; + friend void loadcurrentmap(); + friend void insert_platforms_into_map(); +}; + + +class StraightPath : public MovingPlatformPath { +public: + StraightPath(float vel, float startX, float startY, float endX, float endY, bool preview); + + bool Move(short type) override; + void Reset() override; + +protected: + void SetVelocity(short type); + + short iOnStep[2]; + short iSteps; + short iGoalPoint[2]; + + float dAngle; + + friend class MovingPlatform; + friend class CMap; + friend void loadcurrentmap(); + friend void insert_platforms_into_map(); +}; + + +class StraightPathContinuous : public StraightPath { +public: + StraightPathContinuous(float vel, float startX, float startY, float angle, bool preview); + + bool Move(short type) override; + void Reset() override; + +private: + float dEdgeX, dEdgeY; + + friend class MovingPlatform; + friend class CMap; + friend void loadcurrentmap(); + friend void insert_platforms_into_map(); +}; + + +class EllipsePath : public MovingPlatformPath { +public: + EllipsePath(float vel, float dAngle, float dRadiusX, float dRadiusY, float dCenterX, float dCenterY, bool preview); + + bool Move(short type) override; + void SetPosition(short type); + void Reset() override; + +private: + float dRadiusX, dRadiusY; + float dAngle[2], dStartAngle; + + friend class MovingPlatform; + friend class CMap; + friend void loadcurrentmap(); + friend void insert_platforms_into_map(); +}; + + +class FallingPath : public MovingPlatformPath { +public: + FallingPath(float startX, float startY); + + bool Move(short type) override; + void Reset() override; + +private: + friend class MovingPlatform; +}; diff --git a/src/common/movingplatform.cpp b/src/common/movingplatform.cpp index 7d944da4..8f96d483 100644 --- a/src/common/movingplatform.cpp +++ b/src/common/movingplatform.cpp @@ -12,8 +12,6 @@ #include "sdl12wrapper.h" -#include - extern SDL_Surface* screen; extern SDL_Surface* blitdest; @@ -32,298 +30,6 @@ extern CResourceManager* rm; enum CollisionStyle {collision_none, collision_normal, collision_overlap_left, collision_overlap_right}; -//------------------------------------------------------------------------------ -// Moving Platform Path base class -//------------------------------------------------------------------------------ - -MovingPlatformPath::MovingPlatformPath(float vel, float startX, float startY, float endX, float endY, bool preview) -{ - dVelocity = vel; - - for (short type = 0; type < 2; type++) { - dVelX[type] = 0.0f; - dVelY[type] = 0.0f; - } - - dPathPointX[0] = startX; - dPathPointY[0] = startY; - dPathPointX[1] = endX; - dPathPointY[1] = endY; - - if (preview) { - dPathPointX[0] /= 2.0f; - dPathPointY[0] /= 2.0f; - dPathPointX[1] /= 2.0f; - dPathPointY[1] /= 2.0f; - dVelocity /= 2.0f; - } - - pPlatform = NULL; -} - -void MovingPlatformPath::Reset() -{ - //advance the spawn test platform - if (game_values.spawnstyle == SpawnStyle::Door) { - for (short i = 0; i < 36; i++) - Move(1); - } else if (game_values.spawnstyle == SpawnStyle::Swirl) { - for (short i = 0; i < 50; i++) - Move(1); - } -} -//------------------------------------------------------------------------------ -// Straight Path -//------------------------------------------------------------------------------ - -StraightPath::StraightPath(float vel, float startX, float startY, float endX, float endY, bool preview) - : MovingPlatformPath(vel, startX, startY, endX, endY, preview) - , iGoalPoint{0, 0} -{ - iType = 0; - - float dWidth = dPathPointX[1] - dPathPointX[0]; - float dHeight = dPathPointY[1] - dPathPointY[0]; - float dLength = 0.0f; - - //Lock angle to vertical - if (dWidth == 0) { - if (dHeight > 0) - dAngle = HALF_PI; - else - dAngle = THREE_HALF_PI; - - dLength = fabs(dHeight); - } else if (dHeight == 0) { //Lock angle to horizontal - if (dWidth > 0) - dAngle = 0.0f; - else - dAngle = PI; - - dLength = fabs(dWidth); - } else { - dAngle = atan2(dHeight, dWidth); - dLength = sqrt(dHeight * dHeight + dWidth * dWidth); - } - - iSteps = (short)(dLength / dVelocity) + 1; - - for (short type = 0; type < 2; type++) - SetVelocity(type); -} - -bool StraightPath::Move(short type) -{ - dCurrentX[type] += dVelX[type]; - dCurrentY[type] += dVelY[type]; - - if (++iOnStep[type] >= iSteps) { - iOnStep[type] = 0; - - dCurrentX[type] = dPathPointX[iGoalPoint[type]]; - dCurrentY[type] = dPathPointY[iGoalPoint[type]]; - - iGoalPoint[type] = 1 - iGoalPoint[type]; - - SetVelocity(type); - } - - return false; -} - -void StraightPath::SetVelocity(short type) -{ - if (iGoalPoint[type] == 1) { - dVelX[type] = dVelocity * cos(dAngle); - dVelY[type] = dVelocity * sin(dAngle); - } else { - dVelX[type] = -dVelocity * cos(dAngle); - dVelY[type] = -dVelocity * sin(dAngle); - } - - //Fix rounding errors - if (dVelX[type] < 0.01f && dVelX[type] > -0.01f) - dVelX[type] = 0.0f; - - if (dVelY[type] < 0.01f && dVelY[type] > -0.01f) - dVelY[type] = 0.0f; -} - -void StraightPath::Reset() -{ - for (short type = 0; type < 2; type++) { - iOnStep[type] = 0; - - dCurrentX[type] = dPathPointX[0]; - dCurrentY[type] = dPathPointY[0]; - - iGoalPoint[type] = 1; - SetVelocity(type); - } - - MovingPlatformPath::Reset(); -} - - -//------------------------------------------------------------------------------ -// Straight Path Continuous -//------------------------------------------------------------------------------ - -StraightPathContinuous::StraightPathContinuous(float vel, float startX, float startY, float angle, bool preview) : - StraightPath(vel, startX, startY, 0.0f, 0.0f, preview) -{ - iType = 1; - - dAngle = angle; - - for (short type = 0; type < 2; type++) { - iGoalPoint[type] = 1; - SetVelocity(type); - } - - dEdgeX = App::screenWidth; - dEdgeY = App::screenHeight; - - if (preview) { - dEdgeX = App::screenWidth/2; - dEdgeY = App::screenHeight/2; - } -} - -bool StraightPathContinuous::Move(short type) -{ - dCurrentX[type] += dVelX[type]; - dCurrentY[type] += dVelY[type]; - - float dx = dCurrentX[type] - (float)pPlatform->iHalfWidth; - if (dx < 0.0f) - dCurrentX[type] += dEdgeX; - else if (dx >= dEdgeX) - dCurrentX[type] -= dEdgeX; - - if (dCurrentY[type] + (float)pPlatform->iHalfHeight < 0.0f) - dCurrentY[type] += dEdgeY + (float)pPlatform->iHeight; - else if (dCurrentY[type] - (float)pPlatform->iHalfHeight >= dEdgeY) - dCurrentY[type] -= dEdgeY + (float)pPlatform->iHeight; - - return false; -} - -void StraightPathContinuous::Reset() -{ - for (short type = 0; type < 2; type++) { - dCurrentX[type] = dPathPointX[0]; - dCurrentY[type] = dPathPointY[0]; - } - - MovingPlatformPath::Reset(); -} - -//------------------------------------------------------------------------------ -// Ellipse Path -//------------------------------------------------------------------------------ -EllipsePath::EllipsePath(float vel, float angle, float radiusx, float radiusy, float centerx, float centery, bool preview) : - MovingPlatformPath(vel, centerx, centery, 0.0f, 0.0f, preview) -{ - iType = 2; - - dStartAngle = angle; - - if (preview) { - dRadiusX = radiusx / 2.0f; - dRadiusY = radiusy / 2.0f; - dVelocity *= 2.0f; - } else { - dRadiusX = radiusx; - dRadiusY = radiusy; - } - - for (short type = 0; type < 2; type++) { - dAngle[type] = angle; - SetPosition(type); - } -} - -bool EllipsePath::Move(short type) -{ - float dOldCurrentX = dCurrentX[type]; - float dOldCurrentY = dCurrentY[type]; - - dAngle[type] += dVelocity; - - if (dVelocity < 0.0f) { - while (dAngle[type] < 0.0f) - dAngle[type] += TWO_PI; - } else { - while (dAngle[type] >= TWO_PI) - dAngle[type] -= TWO_PI; - } - - SetPosition(type); - - dVelX[type] = dCurrentX[type] - dOldCurrentX; - dVelY[type] = dCurrentY[type] - dOldCurrentY; - - return false; -} - -void EllipsePath::SetPosition(short type) -{ - dCurrentX[type] = dRadiusX * cos(dAngle[type]) + dPathPointX[0]; - dCurrentY[type] = dRadiusY * sin(dAngle[type]) + dPathPointY[0]; -} - -void EllipsePath::Reset() -{ - for (short type = 0; type < 2; type++) { - dAngle[type] = dStartAngle; - SetPosition(type); - } - - MovingPlatformPath::Reset(); -} - -//------------------------------------------------------------------------------ -// Falling path (for falling donut blocks) -//------------------------------------------------------------------------------ - -FallingPath::FallingPath(float startX, float startY) : - MovingPlatformPath(0.0f, startX, startY, 0.0f, 0.0f, false) -{} - -bool FallingPath::Move(short type) -{ - dVelY[type] = CapFallingVelocity(dVelY[type] + GRAVITATION); - - if (pPlatform->fy - pPlatform->iHalfHeight >= App::screenHeight) { - //If a player is standing on this platform, clear him off - for (CPlayer* player : players) { - if (player->platform == pPlatform) { - player->platform = NULL; - player->vely = dVelY[type]; - } - } - - pPlatform->fDead = true; - } - - dCurrentY[type] += dVelY[type]; - - return false; -} - -void FallingPath::Reset() -{ - for (short type = 0; type < 2; type++) { - dCurrentX[type] = dPathPointX[0]; - dCurrentY[type] = dPathPointY[0]; - } - - //Skip correctly setting the path "shadow" as a perf optimization - //This does have the risk of a player spawning inside a falling donut block by accident - //MovingPlatformPath::Reset(); -} - //------------------------------------------------------------------------------ // Moving Platform //------------------------------------------------------------------------------ diff --git a/src/common/movingplatform.h b/src/common/movingplatform.h index 3326747d..d4ddd78b 100644 --- a/src/common/movingplatform.h +++ b/src/common/movingplatform.h @@ -2,123 +2,11 @@ #define MOVINGPLATFORM_H #include "map.h" +#include "MovingPlatformPaths.h" class CPlayer; class IO_MovingObject; -class MovingPlatform; -class MovingPlatformPath -{ - public: - MovingPlatformPath(float vel, float startX, float startY, float endX, float endY, bool preview); - virtual ~MovingPlatformPath() {} - - virtual bool Move(short type) = 0; //Never let this class be instanciated - virtual void Reset(); - - void SetPlatform(MovingPlatform * platform) { - pPlatform = platform; - } - - short GetType() { - return iType; - } - - protected: - - MovingPlatform * pPlatform; - - float dVelocity; - float dVelX[2], dVelY[2]; - - float dPathPointX[2], dPathPointY[2]; - - float dCurrentX[2], dCurrentY[2]; - - short iType; - - friend class MovingPlatform; - friend class CMap; - friend void loadcurrentmap(); - friend void insert_platforms_into_map(); -}; - -class StraightPath : public MovingPlatformPath -{ - public: - StraightPath(float vel, float startX, float startY, float endX, float endY, bool preview); - virtual ~StraightPath() {} - - bool Move(short type); - void Reset(); - - protected: - void SetVelocity(short type); - - short iOnStep[2]; - short iSteps; - short iGoalPoint[2]; - - float dAngle; - - friend class MovingPlatform; - friend class CMap; - friend void loadcurrentmap(); - friend void insert_platforms_into_map(); -}; - -class StraightPathContinuous : public StraightPath -{ - public: - StraightPathContinuous(float vel, float startX, float startY, float angle, bool preview); - virtual ~StraightPathContinuous() {} - - bool Move(short type); - void Reset(); - - private: - float dEdgeX, dEdgeY; - - friend class MovingPlatform; - friend class CMap; - friend void loadcurrentmap(); - friend void insert_platforms_into_map(); -}; - -class EllipsePath : public MovingPlatformPath -{ - public: - EllipsePath(float vel, float dAngle, float dRadiusX, float dRadiusY, float dCenterX, float dCenterY, bool preview); - virtual ~EllipsePath() {} - - bool Move(short type); - void SetPosition(short type); - void Reset(); - - private: - - float dRadiusX, dRadiusY; - float dAngle[2], dStartAngle; - - friend class MovingPlatform; - friend class CMap; - friend void loadcurrentmap(); - friend void insert_platforms_into_map(); -}; - -class FallingPath : public MovingPlatformPath -{ - public: - FallingPath(float startX, float startY); - virtual ~FallingPath() {} - - bool Move(short type); - void Reset(); - - private: - - friend class MovingPlatform; -}; class MovingPlatform {