Collision Rework, started adding directions to the collision (WIP)

This commit is contained in:
Bram Verhulst
2024-03-17 15:53:48 +01:00
parent d6c5cfa47b
commit 05f46b7eba
5 changed files with 42 additions and 21 deletions

View File

@@ -4,6 +4,9 @@
namespace Collision
{
TileCollisionRect::TileCollisionRect(const Point2f& pos, const Point2f& size, WorldTile* tile): pos(pos), size(size), tile(tile)
{}
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 );
}
@@ -99,16 +102,16 @@ namespace Collision
float contact_time = 0.0f;
if (DynamicRectVsRect(dynamicRectangle, ElapsedTime, *staticRectangle, contactPoint, contactNormal, contact_time)) {
if (contactNormal.y > 0) {
dynamicRectangle.contact[0] = staticRectangle;
dynamicRectangle.ContactMap[CollisionDirection::Bottom] = staticRectangle;
}
if (contactNormal.x < 0) {
dynamicRectangle.contact[1] = staticRectangle;
dynamicRectangle.ContactMap[CollisionDirection::Left] = staticRectangle;
}
if (contactNormal.y < 0) {
dynamicRectangle.contact[2] = staticRectangle;
dynamicRectangle.ContactMap[CollisionDirection::Top] = staticRectangle;
}
if (contactNormal.x > 0) {
dynamicRectangle.contact[3] = staticRectangle;
dynamicRectangle.ContactMap[CollisionDirection::Right] = staticRectangle;
}
//dynamicRectangle.vel = dynamicRectangle.vel + contactNormal * Point2f(std::abs(dynamicRectangle.vel.x), std::abs(dynamicRectangle.vel.y)) * ( 1 - contact_time );

View File

@@ -1,6 +1,7 @@
#pragma once
#include <array>
#include <cmath>
#include <map>
#include "structs.h"
#include "utils.h"
@@ -10,6 +11,13 @@ class WorldTile;
namespace Collision
{
enum CollisionDirection {
Top,
Bottom,
Left,
Right
};
struct CollisionRect
{
@@ -17,19 +25,25 @@ namespace Collision
Point2f size;
Point2f vel;
std::array<Collision::CollisionRect*, 4> contact;
std::map<CollisionDirection, CollisionRect*> ContactMap;
};
struct TileCollisionRect : public CollisionRect
struct TileCollisionRect
{
TileCollisionRect(const Point2f& pos, const Point2f& size, WorldTile* tile)
: CollisionRect{ pos, size, Point2f{ 0, 0 }, { nullptr, nullptr, nullptr, nullptr } }
, tile{ tile }
{}
Point2f pos;
Point2f size;
Point2f vel;
TileCollisionRect(const Point2f& pos, const Point2f& size, WorldTile* tile);
WorldTile* tile;
std::map<CollisionDirection, TileCollisionRect*> ContactMap;
bool Contains(Point2f point2_f) {
return utils::IsPointInRect(point2_f, Rectf{ pos.x, pos.y, size.x, size.y });
}
Collision::CollisionRect getCollisionRect() {
return Collision::CollisionRect{ pos, size, vel };
}
};
bool PointVsRect(const Point2f p, const CollisionRect& r);

View File

@@ -76,12 +76,13 @@ void WorldLevel::Update(float elapsedSec) {
if(utils::isKeyDown(SDL_SCANCODE_D)) {
m_Rects[0].vel.x += 10;
}
if(utils::isKeyDown(SDL_SCANCODE_SPACE)) {
//check if the player is on the ground
m_Rects[0].ContactMap[Collision::CollisionDirection::Bottom]->pos.y += 100;
}
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;
m_Rects[0].ContactMap.clear();
float t = 0, min_t = INFINITY;
Point2f intersectionPoint, normal;
@@ -108,7 +109,7 @@ void WorldLevel::Update(float elapsedSec) {
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)) {
if(Collision::DynamicRectVsRect(m_Rects[0], elapsedSec, m_worldTiles[x][y]->GetCollisionRect().getCollisionRect(), intersectionPoint, normal, t)) {
contactTimes.push_back(std::pair<int, float>{x + y * WORLD_WIDTH, t});
}
}
@@ -121,14 +122,13 @@ void WorldLevel::Update(float elapsedSec) {
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::CollisionRect rect = tile->GetCollisionRect().getCollisionRect();
Collision::ResolveDynamicRectVsRect(m_Rects[0], elapsedSec, &rect);
//delete tile;
//WorldTile* tileRect = tile->GetCollisionRect().tile;
//tileRect->SetTileType(GroundTileTypes::Air);
}
m_Rects[0].pos = m_Rects[0].pos + m_Rects[0].vel * elapsedSec;
}
@@ -174,7 +174,7 @@ void WorldLevel::Draw() const {
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();
Collision::CollisionRect rect = m_worldTiles[x][y]->GetCollisionRect().getCollisionRect();
utils::SetColor(Colors::GREEN);
utils::DrawRect(rect.pos, rect.size.x, rect.size.y);
}
@@ -182,9 +182,10 @@ void WorldLevel::Draw() const {
}
for (size_t i { 0 }; i < 4; ++i) {
if(m_Rects[0].contact[i] != nullptr) {
if(m_Rects[0].ContactMap.find(static_cast<Collision::CollisionDirection>(i)) != m_Rects[0].ContactMap.end()) {
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);
Collision::CollisionRect* rect = m_Rects[0].ContactMap.at(static_cast<Collision::CollisionDirection>(i));
utils::FillRect(rect->pos, rect->size.x, rect->size.y);
}
}

View File

@@ -19,3 +19,6 @@ void WorldTile::Draw() const {
//utils::FillRect(m_Position.x, m_Position.y, 50, 50);
}
}
Collision::TileCollisionRect WorldTile::GetCollisionRect() {
return Collision::TileCollisionRect{ m_Position, GetSize(), (this)};
}

View File

@@ -24,7 +24,7 @@ public:
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)}; }
Collision::TileCollisionRect GetCollisionRect();
private: