diff --git a/Doodler.cpp b/Doodler.cpp index a0365c5..614debc 100644 --- a/Doodler.cpp +++ b/Doodler.cpp @@ -20,34 +20,38 @@ Doodler::Doodler() void Doodler::updatePosition(const float deltaTime) { - checkCollision(); - setVerticalPosition(MOVE_SPEED, deltaTime); - m_timeAccumulator += deltaTime * TIME_ACCELERATOR; - double nextY = m_position.y - m_initialSpeed * m_timeAccumulator + 0.5 * G * std::pow(m_timeAccumulator, 2); - const sf::Vector2f nextPosition = {m_position.x, static_cast(nextY)}; - m_shape.setPosition(nextPosition); - setFallingState(static_cast(nextY)); - setPosition(nextPosition); + const float dtPhysics = deltaTime / MAX_PRECISION_COUNT; + for (unsigned i = 0; i < MAX_PRECISION_COUNT; ++i) + { + setVerticalPosition(MOVE_SPEED, dtPhysics); + m_timeAccumulator += dtPhysics * TIME_ACCELERATOR; + const float nextY = getNextY(); + const sf::Vector2f nextPosition = {m_position.x, nextY}; + m_shape.setPosition(nextPosition); + setFallingState(nextY); + setPosition(nextPosition); + checkCollision(); + } } void Doodler::checkCollision() { - const float currentBottomPosition = m_shape.getPosition().y + m_size.x / 2 + m_outlineThickness; + const float currentBottomPosition = getBounds().height; const bool isAtZeroLevel = m_areFuzzyEqual(currentBottomPosition, m_floor); - const bool isGameOverLevel = m_floor == WINDOW_HEIGHT; + const bool isGameOverLevel = m_areFuzzyEqual(m_floor, WINDOW_HEIGHT); if (isAtZeroLevel && m_isFalling && !isGameOverLevel) { - printf("%f\n", m_floor); + setNextY(); m_timeAccumulator = 0; } } -// TODO: fix side collision check void Doodler::setVerticalPosition(const float nextX, const float deltaTime) { const KeysMap &keysMap = m_p_keyboardState->getKeysMap(); - const bool isMaxRightPosition = m_position.x + m_size.x / 2 + m_outlineThickness < WINDOW_WIDTH; - const bool isMaxLeftPosition = m_position.x - m_size.x / 2 - m_outlineThickness > 0; + const sf::FloatRect bounds = getBounds(); + const bool isMaxRightPosition = bounds.width < WINDOW_WIDTH; + const bool isMaxLeftPosition = bounds.left > 0; if (keysMap.at(sf::Keyboard::Right) && isMaxRightPosition) { m_position.x += nextX * deltaTime; @@ -62,7 +66,7 @@ Types Doodler::getType() const return Types::Doodler; } -const sf::Vector2f &Doodler::getBounds() const +const sf::Vector2f &Doodler::getSize() const { return m_size; } @@ -74,7 +78,6 @@ void Doodler::setFloor(const float nextFloor) return; } m_floor = nextFloor; - m_position.y = m_floor - m_size.x / 2 - m_outlineThickness; } void Doodler::setFallingState(float nextY) @@ -82,7 +85,7 @@ void Doodler::setFallingState(float nextY) m_isFalling = getPosition().y - nextY <= 0; } -void Doodler::addKeyboardState(const std::shared_ptr p_keyboardState) +void Doodler::addKeyboardState(const std::shared_ptr &p_keyboardState) { m_p_keyboardState = p_keyboardState; } @@ -91,3 +94,25 @@ bool Doodler::getFallingState() const { return m_isFalling; } + +void Doodler::setNextY() +{ + m_position.y = m_floor - m_size.y / 2 - m_outlineThickness; +} + +float Doodler::getNextY() const +{ + const float lhs = m_initialSpeed * m_timeAccumulator; + const auto rhs = static_cast(0.5 * G * std::pow(m_timeAccumulator, 2)); + return m_position.y - lhs + rhs; +} + +sf::FloatRect Doodler::getBounds() const +{ + const sf::Vector2f position = m_shape.getPosition(); + const float left = position.x - m_size.x / 2 - m_outlineThickness; + const float right = position.x + m_size.x / 2 + m_outlineThickness; + const float top = position.y - m_size.y / 2 - m_outlineThickness; + const float bottom = position.y + m_size.y / 2 + m_outlineThickness; + return sf::FloatRect(left, top, right, bottom); +} diff --git a/Doodler.h b/Doodler.h index b0916c5..83d3ab0 100644 --- a/Doodler.h +++ b/Doodler.h @@ -19,9 +19,9 @@ class Doodler : public IEntity Types getType() const override; - const sf::Vector2f &getBounds() const override; + const sf::Vector2f &getSize() const override; - void addKeyboardState(std::shared_ptr p_keyboardState); + void addKeyboardState(const std::shared_ptr &p_keyboardState); bool getFallingState() const override; @@ -65,6 +65,12 @@ class Doodler : public IEntity void checkCollision() override; void setVerticalPosition(float nextX, float deltaTime); + + void setNextY(); + + sf::FloatRect getBounds() const; + + float getNextY() const; }; #endif //DOODLE_JUMP_DOODLER_H diff --git a/Engine.cpp b/Engine.cpp index 97eaafc..5537a1d 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -21,14 +21,13 @@ void Engine::processCollision(const std::shared_ptr &p_entity) if (doesIntersect(p_entity) && m_p_doodler->getFallingState() && !m_shouldSetFloor) { m_shouldSetFloor = true; - m_floor = p_entity->getPosition().y - p_entity->getBounds().y; + m_floor = p_entity->getPosition().y - p_entity->getSize().y; } } -// TODO: adjust intersection check bool Engine::doesIntersect(const std::shared_ptr &p_entity) const { - sf::Rect rhs(p_entity->getPosition(), p_entity->getBounds()); - sf::Rect lhs(m_p_doodler->getPosition(), m_p_doodler->getBounds()); + sf::Rect rhs(p_entity->getPosition(), p_entity->getSize()); + sf::Rect lhs(m_p_doodler->getPosition(), m_p_doodler->getSize()); return lhs.intersects(rhs); } diff --git a/EventLoop.cpp b/EventLoop.cpp index cf741ca..c335037 100644 --- a/EventLoop.cpp +++ b/EventLoop.cpp @@ -63,12 +63,12 @@ const sf::RenderWindow &EventLoop::getWindow() const return m_window; } -void EventLoop::addKeyboardState(const std::shared_ptr p_keyboardState) +void EventLoop::addKeyboardState(const std::shared_ptr &p_keyboardState) { m_p_keyboardState = p_keyboardState; } -void EventLoop::addView(const std::shared_ptr p_view) +void EventLoop::addView(const std::shared_ptr &p_view) { m_p_view = p_view; } diff --git a/EventLoop.h b/EventLoop.h index 3026cf4..4b75d91 100644 --- a/EventLoop.h +++ b/EventLoop.h @@ -21,9 +21,9 @@ class EventLoop void redrawFrame(const Entities &entities); - void addKeyboardState(std::shared_ptr p_keyboardState); + void addKeyboardState(const std::shared_ptr &p_keyboardState); - void addView(std::shared_ptr p_view); + void addView(const std::shared_ptr &p_view); const sf::RenderWindow &getWindow() const; diff --git a/IPhysicsObject.h b/IPhysicsObject.h index 5b5771a..1299025 100644 --- a/IPhysicsObject.h +++ b/IPhysicsObject.h @@ -7,9 +7,11 @@ class IPhysicsObject { public: - virtual const sf::Vector2f &getBounds() const = 0; + virtual const sf::Vector2f &getSize() const = 0; virtual Types getType() const = 0; + + virtual sf::FloatRect getBounds() const = 0; }; #endif //DOODLE_JUMP_IPHYSICSOBJECT_H diff --git a/Platform.cpp b/Platform.cpp index 80d056e..0c2b77d 100644 --- a/Platform.cpp +++ b/Platform.cpp @@ -11,8 +11,10 @@ Platform::Platform() m_position.x = rand() % WINDOW_WIDTH; m_position.y = rand() % WINDOW_HEIGHT; - const bool isOverRightSide = m_position.x + m_size.x > WINDOW_WIDTH; - const bool isOverLeftSide = m_position.x - m_size.x < 0; + const sf::FloatRect bounds = getBounds(); + const bool isOverRightSide = bounds.width > WINDOW_WIDTH; + const bool isOverLeftSide = bounds.left < 0; + if (isOverRightSide) { m_position.x -= m_size.x; @@ -44,7 +46,17 @@ Types Platform::getType() const return Types::Platform; } -const sf::Vector2f &Platform::getBounds() const +const sf::Vector2f &Platform::getSize() const { return m_size; } + +sf::FloatRect Platform::getBounds() const +{ + const sf::Vector2f position = m_shape.getPosition(); + const float left = position.x - m_size.x / 2 - m_outlineThickness; + const float right = position.x + m_size.x / 2 + m_outlineThickness; + const float top = position.y - m_size.y / 2 - m_outlineThickness; + const float bottom = position.y + m_size.y / 2 + m_outlineThickness; + return sf::FloatRect(left, top, right, bottom); +} diff --git a/Platform.h b/Platform.h index 4d80c37..3adf080 100644 --- a/Platform.h +++ b/Platform.h @@ -18,7 +18,7 @@ class Platform : public IEntity Types getType() const override; - const sf::Vector2f &getBounds() const override; + const sf::Vector2f &getSize() const override; private: sf::RectangleShape m_shape; @@ -28,6 +28,8 @@ class Platform : public IEntity const unsigned m_outlineThickness = 2; void draw(sf::RenderTarget &target, sf::RenderStates states) const override; + + sf::FloatRect getBounds() const; }; #endif //DOODLE_JUMP_PLATFORM_H diff --git a/View.cpp b/View.cpp index 20807e8..374a6ec 100644 --- a/View.cpp +++ b/View.cpp @@ -7,7 +7,7 @@ View::View() m_view.setViewport(sf::FloatRect(0, 0, 1, 1)); } -void View::followTo(const std::shared_ptr p_doodler) +void View::followTo(const std::shared_ptr &p_doodler) { m_view.setCenter(WINDOW_WIDTH / 2, p_doodler->getPosition().y); } diff --git a/View.h b/View.h index be0a64c..22612b5 100644 --- a/View.h +++ b/View.h @@ -11,7 +11,7 @@ class View const sf::View &getView() const; - void followTo(std::shared_ptr p_doodler); + void followTo(const std::shared_ptr &p_doodler); private: sf::View m_view; diff --git a/consts.h b/consts.h index d8b0f9c..da48389 100644 --- a/consts.h +++ b/consts.h @@ -17,9 +17,10 @@ static const sf::Vector2u ICON_SIZE = {32, 32}; /// Game params static const float G = 9.8f; -static const float TIME_ACCELERATOR = 15.f; +static const float TIME_ACCELERATOR = 7.5f; static const float MOVE_SPEED = 500.f; static const size_t PLATFORM_COUNT = 30; +static const unsigned MAX_PRECISION_COUNT = 128; template using Lambda = std::function;