mirror of
https://github.com/HowestDAE/dae16-VerhulstBram.git
synced 2025-12-16 03:41:48 +01:00
Collision reworked into a Collision Namespace
Added basic player (Needs work)
This commit is contained in:
120
Engine/Collision.cpp
Normal file
120
Engine/Collision.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
44
Engine/Collision.h
Normal file
44
Engine/Collision.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
|
||||
class WorldTile;
|
||||
|
||||
namespace Collision
|
||||
{
|
||||
|
||||
struct CollisionRect
|
||||
{
|
||||
|
||||
Point2f pos;
|
||||
Point2f size;
|
||||
Point2f vel;
|
||||
|
||||
std::array<Collision::CollisionRect*, 4> 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);
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BaseGame.cpp" />
|
||||
<ClCompile Include="Collision.cpp" />
|
||||
<ClCompile Include="Matrix2x3.cpp" />
|
||||
<ClCompile Include="SoundEffect.cpp" />
|
||||
<ClCompile Include="SoundStream.cpp" />
|
||||
@@ -31,6 +32,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BaseGame.h" />
|
||||
<ClInclude Include="Collision.h" />
|
||||
<ClInclude Include="colors.h" />
|
||||
<ClInclude Include="Matrix2x3.h" />
|
||||
<ClInclude Include="base.h" />
|
||||
|
||||
@@ -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
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "Vector2f.h"
|
||||
#include "structs.h"
|
||||
#include "SDL.h"
|
||||
|
||||
namespace utils
|
||||
{
|
||||
|
||||
@@ -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 )
|
||||
//{
|
||||
|
||||
@@ -38,6 +38,6 @@ private:
|
||||
|
||||
Point2f m_MousePos{};
|
||||
Point2f m_MouseOffset{};
|
||||
bool m_IsMouseDown{};
|
||||
bool m_IsRightMouseDown{};
|
||||
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
#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<std::pair<int, float>> 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<int, float>{i, t});
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(contactTimes.begin(), contactTimes.end(), [](const std::pair<int, float>& a, const std::pair<int, float>& b) {
|
||||
return a.second < b.second;
|
||||
});
|
||||
|
||||
for (std::pair<int, float> 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<int, float>{x + y * WORLD_WIDTH, t});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(contactTimes.begin(), contactTimes.end(), [](const std::pair<int, float>& a, const std::pair<int, float>& b) {
|
||||
return a.second < b.second;
|
||||
});
|
||||
|
||||
for (std::pair<int, float> 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<int, float> 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) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "WorldTile.h"
|
||||
#include <array>
|
||||
|
||||
#include "Collision.h"
|
||||
#include "Player.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -30,7 +31,7 @@ public:
|
||||
|
||||
std::array<std::array<WorldTile*, WORLD_WIDTH>, WORLD_HEIGHT> GetAllTiles() const;
|
||||
|
||||
std::vector<utils::MovingRectf> m_Rects;
|
||||
std::vector<Collision::CollisionRect> m_Rects;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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<WorldTile*>(this)}; }
|
||||
|
||||
|
||||
private:
|
||||
@@ -30,6 +33,8 @@ private:
|
||||
|
||||
Texture* m_pTexture;
|
||||
|
||||
Collision::CollisionRect m_CollisionRect;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user