diff --git a/Engine/Collision.cpp b/Engine/Collision.cpp new file mode 100644 index 0000000..463e99b --- /dev/null +++ b/Engine/Collision.cpp @@ -0,0 +1,120 @@ +#include "Collision.h" + +#include "utils.h" + +namespace Collision +{ + bool PointVsRect(const Point2f p, const Collision::CollisionRect& r) { + return ( p.x >= r.pos.x && p.y >= r.pos.y && p.x < r.pos.x + r.size.x && p.y < r.pos.y + r.size.y ); + } + + bool RectVsRect(const Collision::CollisionRect& r1, const Collision::CollisionRect r2) { + return ( r1.pos.x < r2.pos.x + r2.size.x && r1.pos.x + r1.size.x > r2.pos.x && r1.pos.y < r2.pos.y + r2.size.y && r1.pos.y + r1.size.y > r2.pos.y ); + } + + bool RayVsRect(const Point2f& rayOrigin, const Point2f& rayDirection, const Collision::CollisionRect target, Point2f& contactPoint, Point2f& contactNormal, + float& t_HitNear) { + contactNormal = Point2f { 0, 0 }; + contactPoint = Point2f { 0, 0 }; + + const Point2f inverseDirection = 1.0f / rayDirection; + + // Calculate intersections with rectangle bounding axes + Point2f t_Near = Point2f{ target.pos.x - rayOrigin.x, target.pos.y - rayOrigin.y } * inverseDirection; + Point2f t_Far = Point2f{ target.pos.x + target.size.x - rayOrigin.x, target.pos.y + target.size.y - rayOrigin.y } * inverseDirection; + + if (std::isnan(t_Far.y) || std::isnan(t_Far.x)) + return false; + if (std::isnan(t_Near.y) || std::isnan(t_Near.x)) + return false; + + // Sort distances + if (t_Near.x > t_Far.x) + std::swap(t_Near.x, t_Far.x); + if (t_Near.y > t_Far.y) + std::swap(t_Near.y, t_Far.y); + + // Early rejection + if (t_Near.x > t_Far.y || t_Near.y > t_Far.x) + return false; + + // Closest 'time' will be the first contact + t_HitNear = std::max(t_Near.x, t_Near.y); + + const float t_HitFar = std::min(t_Far.x, t_Far.y); + + // Reject if ray direction is pointing away from object + if (t_HitFar < 0) + return false; + + // Contact point of collision from parametric line equation + contactPoint = rayOrigin + t_HitNear * rayDirection; + + if (t_Near.x > t_Near.y) { + if (inverseDirection.x < 0) { + contactNormal = Point2f { 1, 0 }; + } + else { + contactNormal = Point2f { -1, 0 }; + } + } + else if (t_Near.x < t_Near.y) { + if (inverseDirection.y < 0) { + contactNormal = Point2f { 0, 1 }; + } + else { + contactNormal = Point2f { 0, -1 }; + } + } + // If t_Near == t_Far, collision is diagonal so pointless + + return true; + } + + bool DynamicRectVsRect(const Collision::CollisionRect& dynamicRectangle, float ElapsedTime, const Collision::CollisionRect& staticRectangle, + Point2f& contactPoint, Point2f& contactNormal, float& contactTime) { + // Check if dynamic rectangle is actually moving - we assume rectangles are NOT in collision to start + if (dynamicRectangle.vel.x == 0 && dynamicRectangle.vel.y == 0) { + return false; + } + + // Expand target rectangle by source dimensions + Collision::CollisionRect expandedTarget; + expandedTarget.pos = Point2f{staticRectangle.pos.x - (dynamicRectangle.size / 2).x, staticRectangle.pos.y - (dynamicRectangle.size / 2).y}; + expandedTarget.size = staticRectangle.size + dynamicRectangle.size; + + Point2f RayOrigin = dynamicRectangle.pos + dynamicRectangle.size / 2; + + if (RayVsRect(RayOrigin, dynamicRectangle.vel * ElapsedTime, expandedTarget, contactPoint, contactNormal, contactTime)) { + return ( contactTime >= 0.0f && contactTime < 1.0f ); + } + else { + return false; + } + return false; + } + + bool ResolveDynamicRectVsRect(Collision::CollisionRect& dynamicRectangle, float ElapsedTime, Collision::CollisionRect* staticRectangle) { + Point2f contactPoint, contactNormal; + float contact_time = 0.0f; + if (DynamicRectVsRect(dynamicRectangle, ElapsedTime, *staticRectangle, contactPoint, contactNormal, contact_time)) { + if (contactNormal.y > 0) { + dynamicRectangle.contact[0] = staticRectangle; + } + if (contactNormal.x < 0) { + dynamicRectangle.contact[1] = staticRectangle; + } + if (contactNormal.y < 0) { + dynamicRectangle.contact[2] = staticRectangle; + } + if (contactNormal.x > 0) { + dynamicRectangle.contact[3] = staticRectangle; + } + + //dynamicRectangle.vel = dynamicRectangle.vel + contactNormal * Point2f(std::abs(dynamicRectangle.vel.x), std::abs(dynamicRectangle.vel.y)) * ( 1 - contact_time ); + dynamicRectangle.vel = dynamicRectangle.vel + contactNormal * -utils::DotProduct(dynamicRectangle.vel, contactNormal) * ( 1 - contact_time ); + return true; + } + return false; + } +} diff --git a/Engine/Collision.h b/Engine/Collision.h new file mode 100644 index 0000000..e0d393c --- /dev/null +++ b/Engine/Collision.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include + +#include "structs.h" +#include "utils.h" + +class WorldTile; + +namespace Collision +{ + + struct CollisionRect + { + + Point2f pos; + Point2f size; + Point2f vel; + + std::array contact; + }; + + struct TileCollisionRect : public CollisionRect + { + TileCollisionRect(const Point2f& pos, const Point2f& size, WorldTile* tile) + : CollisionRect{ pos, size, Point2f{ 0, 0 }, { nullptr, nullptr, nullptr, nullptr } } + , tile{ tile } + {} + WorldTile* tile; + bool Contains(Point2f point2_f) { + return utils::IsPointInRect(point2_f, Rectf{ pos.x, pos.y, size.x, size.y }); + } + }; + + bool PointVsRect(const Point2f p, const CollisionRect& r); + + bool RectVsRect(const CollisionRect& r1, const CollisionRect r2); + + bool RayVsRect(const Point2f& rayOrigin, const Point2f& rayDirection, const Collision::CollisionRect target, Point2f& contactPoint, Point2f& contactNormal, float& t_HitNear); + + bool DynamicRectVsRect(const CollisionRect& dynamicRectangle, float ElapsedTime, const CollisionRect& staticRectangle, Point2f& contactPoint, Point2f& contactNormal, float& contactTime); + + bool ResolveDynamicRectVsRect(CollisionRect& dynamicRectangle, float ElapsedTime, CollisionRect* staticRectangle); +} diff --git a/Engine/Engine.vcxproj b/Engine/Engine.vcxproj index 458bc61..690ea14 100644 --- a/Engine/Engine.vcxproj +++ b/Engine/Engine.vcxproj @@ -20,6 +20,7 @@ + @@ -31,6 +32,7 @@ + diff --git a/Engine/structs.cpp b/Engine/structs.cpp index bac8210..30980e8 100644 --- a/Engine/structs.cpp +++ b/Engine/structs.cpp @@ -23,6 +23,9 @@ Point2f::Point2f(float x, float y) Point2f Point2f::operator+(const Point2f& other) const { return Point2f { x + other.x, y + other.y }; } +Point2f Point2f::operator+=(const Point2f& other) const { + return Point2f { x + other.x, y + other.y }; +} Point2f Point2f::operator*(float other) const { return Point2f { x * other, y * other }; } @@ -35,11 +38,20 @@ Point2f Point2f::operator*(int other) const { Point2f Point2f::operator/(float other) const { return Point2f { x / other, y / other }; } +Point2f Point2f::operator-(const Point2f& other) const { + return Point2f { x - other.x, y - other.y }; +} // Point2f::Point2f(int x, int y) // : x { (float)x }, y { (float)y } { // } +Point2f operator/(float right, const Point2f& left) { + return Point2f { right / left.x, right / left.y }; +} +Point2f operator*(float right, const Point2f& left) { + return Point2f{ right * left.x, right * left.y }; +} //----------------------------------------------------------------- // Rectf Constructors //----------------------------------------------------------------- diff --git a/Engine/structs.h b/Engine/structs.h index fca5aaa..a94ab2f 100644 --- a/Engine/structs.h +++ b/Engine/structs.h @@ -20,16 +20,19 @@ struct Point2f //operator Point2f operator+( const Point2f& other ) const; + Point2f operator+=( const Point2f& other ) const; Point2f operator*( float other ) const; - Point2f operator*( const Point2f& other ) const; Point2f operator*( int other ) const; + Point2f operator*( const Point2f& other ) const; Point2f operator/( float other ) const; - + Point2f operator-( const Point2f& other ) const; + float x; float y; }; - +Point2f operator/(float right, const Point2f& left); +Point2f operator*(float right, const Point2f& left); struct Rectf { diff --git a/Engine/utils.cpp b/Engine/utils.cpp index 349c025..3a0cf96 100644 --- a/Engine/utils.cpp +++ b/Engine/utils.cpp @@ -580,7 +580,7 @@ bool utils::Raycast( const Point2f* vertices, const size_t nrVertices, const Poi HitInfo linesHitInfo{}; linesHitInfo.lambda = lambda1; linesHitInfo.intersectPoint = Point2f{ rayP1.x + ( ( rayP2.x - rayP1.x ) * lambda1 ), rayP1.y + ( ( rayP2.y - rayP1.y ) * lambda1 ) }; - linesHitInfo.normal = Vector2f{ q2 - q1 }.Orthogonal( ).Normalized( ); + linesHitInfo.normal = Vector2f{ q2.x - q1.x, q2.y - q2.y }.Orthogonal( ).Normalized( ); hits.push_back(linesHitInfo); } } @@ -645,7 +645,7 @@ float utils::DistPointLineSegment( const Point2f& p, const Point2f& a, const Po // Closest point is between A and B, calc intersection point Vector2f intersection{ abNorm.DotProduct(ap) * abNorm + Vector2f{ a } }; - return Vector2f{ p - intersection }.Length( ); + return Vector2f{ p.x - intersection.x, p.y - intersection.y }.Length( ); } bool utils::IntersectRectLine(const Rectf& r, const Point2f& p1, const Point2f& p2, float& intersectMin, float& intersectMax) @@ -693,9 +693,12 @@ bool utils::IsRectInRect(const Rectf& r1, const Rectf& r2) { bool utils::RayVsRect(const Point2f& rayOrigin, const Point2f& rayDir, const Rectf& target, Point2f& contactPoint, Point2f& contactNormal, float& t_hit_near) { - Point2f t_near = Point2f{(target.BottomLeft() - rayOrigin).x / rayDir.x, (target.BottomLeft() - rayOrigin).y / rayDir.y}; - Point2f t_far = Point2f{(target.BottomLeft() + Point2f{target.width, target.height} - rayOrigin).x / rayDir.x, (target.BottomLeft() + Point2f{target.width, target.height} - rayOrigin).y / rayDir.y}; + // Point2f t_near = Point2f{(target.BottomLeft() - rayOrigin).x / rayDir.x, (target.BottomLeft() - rayOrigin).y / rayDir.y}; + // Point2f t_far = Point2f{(target.BottomLeft() + Point2f{target.width, target.height} - rayOrigin).x / rayDir.x, (target.BottomLeft() + Point2f{target.width, target.height} - rayOrigin).y / rayDir.y}; + Point2f t_near{}; + Point2f t_far{}; + if(std::isnan(t_far.y) || std::isnan(t_far.x)) return false; if(std::isnan(t_near.y) || std::isnan(t_near.x)) return false; @@ -724,7 +727,6 @@ bool utils::RayVsRect(const Point2f& rayOrigin, const Point2f& rayDir, const Rec contactNormal = Point2f{0, -1}; } } - return true; } diff --git a/Engine/utils.h b/Engine/utils.h index fd7235d..3c9e766 100644 --- a/Engine/utils.h +++ b/Engine/utils.h @@ -1,6 +1,8 @@ #pragma once #include #include "Vector2f.h" +#include "structs.h" +#include "SDL.h" namespace utils { diff --git a/Game/Game.cpp b/Game/Game.cpp index 1788472..f7b3368 100644 --- a/Game/Game.cpp +++ b/Game/Game.cpp @@ -37,7 +37,7 @@ void Game::Update(float elapsedSec) { // m_CameraOffset.y -= 200 * elapsedSec; // } - if(m_IsMouseDown) { + if(m_IsRightMouseDown) { Point2f newCameraPos = m_MousePos + m_MouseOffset; m_Camera.SetPosition(newCameraPos); } else { @@ -83,8 +83,8 @@ void Game::ProcessMouseMotionEvent(const SDL_MouseMotionEvent& e) { } void Game::ProcessMouseDownEvent(const SDL_MouseButtonEvent& e) { - m_IsMouseDown = true; - m_MouseOffset = Point2f(m_Camera.GetPosition() - m_MousePos); + m_IsRightMouseDown = e.button == SDL_BUTTON_RIGHT; + m_MouseOffset = Point2f{m_Camera.GetPosition().x - m_MousePos.x, m_Camera.GetPosition().y - m_MousePos.y}; //std::cout << "MOUSEBUTTONDOWN event: "; @@ -104,7 +104,7 @@ void Game::ProcessMouseDownEvent(const SDL_MouseButtonEvent& e) { } void Game::ProcessMouseUpEvent(const SDL_MouseButtonEvent& e) { - m_IsMouseDown = false; + m_IsRightMouseDown = e.button == SDL_BUTTON_RIGHT; //std::cout << "MOUSEBUTTONUP event: "; //switch ( e.button ) //{ diff --git a/Game/Game.h b/Game/Game.h index 4f8c095..73c6843 100644 --- a/Game/Game.h +++ b/Game/Game.h @@ -38,6 +38,6 @@ private: Point2f m_MousePos{}; Point2f m_MouseOffset{}; - bool m_IsMouseDown{}; + bool m_IsRightMouseDown{}; }; diff --git a/Game/WorldLevel.cpp b/Game/WorldLevel.cpp index 7499881..f15bf2f 100644 --- a/Game/WorldLevel.cpp +++ b/Game/WorldLevel.cpp @@ -5,6 +5,7 @@ #include #include +#include "Collision.h" #include "colors.h" #include "utils.h" @@ -17,20 +18,18 @@ WorldLevel::WorldLevel(Camera* camera) : Level(camera), m_mousePos{ 0, 0 }, m_pl m_worldTiles[x][y] = new WorldTile{ Point2f{ float(actualX * TILE_WIDTH), -float(y * TILE_HEIGHT) - TILE_HEIGHT}, GroundTileTypes::Dirt}; } } - - m_Rects.push_back(utils::MovingRectf{Point2f{20, 40}, 40, 50, Point2f{0,0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{510.0f, 210.0f}, 30.0f, 120.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{450.0f, 150.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{450.0f, 450.0f}, 225.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{510.0f, 150.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{570.0f, 150.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{330.0f, 150.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{150.0f, 390.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{150.0f, 450.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{150.0f, 510.0f}, 60.0f, 60.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{450.0f, 300.0f}, 30.0f, 3.0f, Point2f{0, 0}}); - m_Rects.push_back(utils::MovingRectf{Point2f{600.0f, 300.0f}, 60.0f, 180.0f, Point2f{0, 0}}); - + m_Rects.push_back(Collision::CollisionRect{ Point2f{0.0f, 10.0f}, Point2f{40.0f, 40.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{170.0f, 70.0f}, Point2f{10.0f, 40.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{150.0f, 50.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{150.0f, 150.0f}, Point2f{75.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{170.0f, 50.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{190.0f, 50.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{110.0f, 50.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{50.0f, 130.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{50.0f, 150.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{50.0f, 170.0f}, Point2f{20.0f, 20.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{150.0f, 100.0f}, Point2f{10.0f, 1.0f} }); + m_Rects.push_back(Collision::CollisionRect{ Point2f{200.0f, 100.0f}, Point2f{20.0f, 60.0f} }); // std::string dirtPath = + "tiles/dirt/dirt" + std::to_string(utils::randRange(1, 5)) + ".png"; @@ -47,69 +46,102 @@ void WorldLevel::Update(float elapsedSec) { m_mousePos = m_pCamera->TransformMouse(m_mousePos); //m_player.Update(elapsedSec, *this); - + WorldTile* selectedTile{ nullptr }; + + for (size_t x { 0 }; x < WORLD_WIDTH; ++x) { + for (size_t y { 0 }; y < WORLD_HEIGHT; ++y) { + if(m_worldTiles[x][y]->GetCollisionRect().Contains(m_mousePos)) { + selectedTile = m_worldTiles[x][y]; + } + } + } + if(selectedTile != nullptr) { + selectedTile->SetTileType(GroundTileTypes::Air); + } Point2f RayPoint = Point2f{m_pCamera->Viewport.width, m_pCamera->Viewport.height}; Point2f RayDir = Point2f{m_mousePos.x - RayPoint.x, m_mousePos.y - RayPoint.y}; //wasd movement if(utils::isKeyDown(SDL_SCANCODE_W)) { - m_Rects[0].velocity.y += 10; + m_Rects[0].vel.y += 20; } if(utils::isKeyDown(SDL_SCANCODE_S)) { - m_Rects[0].velocity.y += -10; + m_Rects[0].vel.y += -10; } if(utils::isKeyDown(SDL_SCANCODE_A)) { - m_Rects[0].velocity.x += -10; + m_Rects[0].vel.x += -10; } if(utils::isKeyDown(SDL_SCANCODE_D)) { - m_Rects[0].velocity.x += 10; + m_Rects[0].vel.x += 10; } - - Point2f intersectionPoint, normal; - float contactTime; + m_Rects[0].vel.y -= 9.81f; + m_Rects[0].contact[0] = nullptr; + m_Rects[0].contact[1] = nullptr; + m_Rects[0].contact[2] = nullptr; + m_Rects[0].contact[3] = nullptr; + + float t = 0, min_t = INFINITY; + Point2f intersectionPoint, normal; + std::vector> contactTimes{}; for (size_t i { 1 }; i < m_Rects.size(); ++i) { - Rectf target = Rectf{m_Rects[i].bottomLeft.x, m_Rects[i].bottomLeft.y, m_Rects[i].width, m_Rects[i].height}; - if(utils::DynamicRectVsRect(m_Rects[0], target, intersectionPoint, normal, contactTime, elapsedSec)) { - // m_Rects[0].velocity.x += normal.x * (1 - contactTime) * -utils::DotProduct( m_Rects[0].velocity, normal); - // m_Rects[0].velocity.y += normal.y * (1 - contactTime) * -utils::DotProduct( m_Rects[0].velocity, normal); - // - // //m_Rects[0].velocity = Point2f{0, 0}; + if(Collision::DynamicRectVsRect(m_Rects[0], elapsedSec, m_Rects[i], intersectionPoint, normal, t)) { + contactTimes.push_back(std::pair{i, t}); + } + } + + std::sort(contactTimes.begin(), contactTimes.end(), [](const std::pair& a, const std::pair& b) { + return a.second < b.second; + }); + + for (std::pair contact_time : contactTimes) { + Collision::ResolveDynamicRectVsRect(m_Rects[0], elapsedSec, &m_Rects[contact_time.first]); + } - contactTimes.push_back({i, contactTime}); + contactTimes.clear(); + + //loop over the worldTiles + for (int x {0} ; x < WORLD_WIDTH; ++x) { + for (int y {0}; y < WORLD_HEIGHT; ++y) { + if(m_worldTiles[x][y]->GetTileType() == GroundTileTypes::Dirt) { + if(Collision::DynamicRectVsRect(m_Rects[0], elapsedSec, m_worldTiles[x][y]->GetCollisionRect(), intersectionPoint, normal, t)) { + contactTimes.push_back(std::pair{x + y * WORLD_WIDTH, t}); + } + } } } std::sort(contactTimes.begin(), contactTimes.end(), [](const std::pair& a, const std::pair& b) { return a.second < b.second; }); - - for (std::pair contact : contactTimes) { - Rectf target = Rectf{m_Rects[contact.first].bottomLeft.x, m_Rects[contact.first].bottomLeft.y, m_Rects[contact.first].width, m_Rects[contact.first].height}; - if(utils::DynamicRectVsRect(m_Rects[0], target, intersectionPoint, normal, contactTime, elapsedSec)) { - m_Rects[0].velocity.x += normal.x * (1 - contactTime) * -utils::DotProduct( m_Rects[0].velocity, normal); - m_Rects[0].velocity.y += normal.y * (1 - contactTime) * -utils::DotProduct( m_Rects[0].velocity, normal); - } + + for (std::pair contact_time : contactTimes) { + WorldTile* tile = m_worldTiles[contact_time.first % WORLD_WIDTH][contact_time.first / WORLD_WIDTH]; + Collision::CollisionRect rect = tile->GetCollisionRect(); + Collision::ResolveDynamicRectVsRect(m_Rects[0], elapsedSec, &rect); + //delete tile; + //WorldTile* tileRect = tile->GetCollisionRect().tile; + //tileRect->SetTileType(GroundTileTypes::Air); } - m_Rects[0].bottomLeft.x = m_Rects[0].bottomLeft.x + m_Rects[0].velocity.x * elapsedSec; - m_Rects[0].bottomLeft.y = m_Rects[0].bottomLeft.y + m_Rects[0].velocity.y * elapsedSec; + m_Rects[0].pos = m_Rects[0].pos + m_Rects[0].vel * elapsedSec; + } void WorldLevel::Draw() const { m_pCamera->BeginRendering(); - for (utils::MovingRectf rect : m_Rects) { - utils::DrawRect(rect.bottomLeft, rect.width, rect.height); + for (Collision::CollisionRect rect : m_Rects) { + utils::DrawRect(rect.pos, rect.size.x, rect.size.y); } - Rectf expanded = Rectf{ m_Rects[1].bottomLeft.x - m_Rects[0].width / 2, m_Rects[1].bottomLeft.y - m_Rects[0].height / 2, m_Rects[1].width + m_Rects[0].width, m_Rects[1].height + m_Rects[0].height }; - utils::SetColor(Colors::RED); - utils::DrawRect(expanded); + //Rectf expanded = Rectf{ m_Rects[1].bottomLeft.x - m_Rects[0].width / 2, m_Rects[1].bottomLeft.y - m_Rects[0].height / 2, m_Rects[1].width + m_Rects[0].width, m_Rects[1].height + m_Rects[0].height }; + //utils::SetColor(Colors::RED); + //utils::DrawRect(expanded); Point2f RayPoint = Point2f{m_pCamera->Viewport.width, m_pCamera->Viewport.height}; @@ -120,15 +152,15 @@ void WorldLevel::Draw() const { utils::FillEllipse(m_mousePos, 20, 20); - Point2f intersectionPoint, normal; - float contactTime; - Rectf testRect = Rectf{m_Rects[1].bottomLeft.x, m_Rects[1].bottomLeft.y, m_Rects[1].width, m_Rects[1].height}; - if(utils::RayVsRect(RayPoint, RayDir, testRect, intersectionPoint, normal, contactTime) && contactTime > 0.0f && contactTime < 1.0f) { - utils::SetColor(Colors::GREEN); - utils::FillEllipse(intersectionPoint, 5, 5); - utils::DrawLine(intersectionPoint, Point2f{intersectionPoint.x + normal.x * 50, intersectionPoint.y + normal.y * 50}); - } - + // Point2f intersectionPoint, normal; + // float contactTime; + // Rectf testRect = Rectf{m_Rects[1].bottomLeft.x, m_Rects[1].bottomLeft.y, m_Rects[1].width, m_Rects[1].height}; + // if(utils::RayVsRect(RayPoint, RayDir, testRect, intersectionPoint, normal, contactTime) && contactTime > 0.0f && contactTime < 1.0f) { + // utils::SetColor(Colors::GREEN); + // utils::FillEllipse(intersectionPoint, 5, 5); + // utils::DrawLine(intersectionPoint, Point2f{intersectionPoint.x + normal.x * 50, intersectionPoint.y + normal.y * 50}); + // } + // // utils::SetColor(Colors::YELLOW); // utils::FillEllipse(m_mousePos,2,2); @@ -137,6 +169,24 @@ void WorldLevel::Draw() const { m_worldTiles[x][y]->Draw(); } } + + //loop over worldtiles + for (int x { 0 }; x < WORLD_WIDTH; ++x) { + for (int y { 0 }; y < WORLD_HEIGHT; ++y) { + if(m_worldTiles[x][y]->GetTileType() == GroundTileTypes::Dirt) { + Collision::CollisionRect rect = m_worldTiles[x][y]->GetCollisionRect(); + utils::SetColor(Colors::GREEN); + utils::DrawRect(rect.pos, rect.size.x, rect.size.y); + } + } + } + + for (size_t i { 0 }; i < 4; ++i) { + if(m_Rects[0].contact[i] != nullptr) { + utils::SetColor(Colors::RED); + utils::FillRect(m_Rects[0].contact[i]->pos, m_Rects[0].contact[i]->size.x, m_Rects[0].contact[i]->size.y); + } + } // utils::SetColor(Colors::WHITE); // for (int x { -100 }; x < 100; ++x) { diff --git a/Game/WorldLevel.h b/Game/WorldLevel.h index 2f378e6..ab59e90 100644 --- a/Game/WorldLevel.h +++ b/Game/WorldLevel.h @@ -5,6 +5,7 @@ #include "WorldTile.h" #include +#include "Collision.h" #include "Player.h" #include "utils.h" @@ -30,7 +31,7 @@ public: std::array, WORLD_HEIGHT> GetAllTiles() const; - std::vector m_Rects; + std::vector m_Rects; diff --git a/Game/WorldTile.h b/Game/WorldTile.h index f72c21f..9426499 100644 --- a/Game/WorldTile.h +++ b/Game/WorldTile.h @@ -1,4 +1,5 @@ #pragma once +#include "Collision.h" #include "Texture.h" enum class GroundTileTypes @@ -21,7 +22,9 @@ public: Point2f GetSize() const { return Point2f{ 50, 50 }; } GroundTileTypes GetTileType() const { return m_GroundTileType; } - + void SetTileType(GroundTileTypes type) { m_GroundTileType = type; } + + Collision::TileCollisionRect GetCollisionRect() const { return Collision::TileCollisionRect{ m_Position, GetSize(), const_cast(this)}; } private: @@ -30,6 +33,8 @@ private: Texture* m_pTexture; + Collision::CollisionRect m_CollisionRect; + };