mirror of
https://github.com/HowestDAE/dae16-VerhulstBram.git
synced 2026-02-04 08:09:19 +01:00
Added a (temp) collision solver for Axis-Aligned rectangles
This commit is contained in:
@@ -5,6 +5,8 @@ Camera::Camera() : m_Position { 0, 0 }, m_Scale { 1.0f } {
|
||||
}
|
||||
Camera::Camera(const Point2f& position, const float scale) : m_Position { position }, m_Scale { scale } {
|
||||
}
|
||||
Camera::~Camera() {
|
||||
}
|
||||
|
||||
void Camera::BeginRendering() const {
|
||||
glPushMatrix();
|
||||
@@ -16,6 +18,6 @@ void Camera::EndRendering() const {
|
||||
glPopMatrix();
|
||||
}
|
||||
Point2f Camera::TransformMouse(const Point2f& mousePos) const {
|
||||
const Point2f translatedPosition = mousePos + m_Position;
|
||||
const Point2f translatedPosition = Point2f{ mousePos.x - m_Position.x, Viewport.height - mousePos.y - m_Position.y};
|
||||
return translatedPosition;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ class Camera
|
||||
public:
|
||||
Camera( );
|
||||
Camera( const Point2f& position, float scale = 1);
|
||||
virtual ~Camera();
|
||||
|
||||
void SetPosition( const Point2f& position ) { m_Position = position; }
|
||||
void SetScale( const float scale ) { m_Scale = scale; }
|
||||
@@ -16,6 +17,8 @@ public:
|
||||
void EndRendering() const;
|
||||
|
||||
Point2f TransformMouse (const Point2f& mousePos) const;
|
||||
Rectf Viewport = Rectf{ 0, 0, 846.f, 500.f };
|
||||
//TODO: Remove this and make it some static
|
||||
|
||||
private:
|
||||
Point2f m_Position;
|
||||
|
||||
@@ -44,6 +44,8 @@ void Game::Update(float elapsedSec) {
|
||||
m_MouseOffset = m_Camera.GetPosition();
|
||||
}
|
||||
|
||||
m_WorldLevel.Update(elapsedSec);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,4 @@ Level::Level(Camera* camera) {
|
||||
m_pCamera = camera;
|
||||
}
|
||||
Level::~Level() {
|
||||
}
|
||||
void Level::Update(float elapsedSec) {
|
||||
}
|
||||
void Level::Draw() const {
|
||||
}
|
||||
void Level::MouseMove(const Point2f& mousePos) {
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ public:
|
||||
Level(Camera* camera);
|
||||
virtual ~Level();
|
||||
|
||||
virtual void Update(float elapsedSec);
|
||||
virtual void Draw() const;
|
||||
virtual void MouseMove(const Point2f& mousePos);
|
||||
virtual void Update(float elapsedSec) = 0;
|
||||
virtual void Draw() const = 0;
|
||||
virtual void MouseMove(const Point2f& mousePos) = 0;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -14,11 +14,30 @@ void Player::Draw() const {
|
||||
}
|
||||
|
||||
void Player::Update(float elapsedTime, const WorldLevel& level) {
|
||||
Point2f acc{0, 0};
|
||||
acc.y += m_Gravity.y;
|
||||
// m_Acc.y += m_Gravity.y;
|
||||
// m_Vel.y = std::min(m_Vel.y, m_MaxSpeed);
|
||||
//
|
||||
// Point2f nextPos = m_Position + m_Vel * elapsedTime;
|
||||
// //collision checking
|
||||
m_Vel = Point2f{0, -100};
|
||||
|
||||
Point2f nextPos = m_Position + m_Vel * elapsedTime * acc * elapsedTime * elapsedTime;
|
||||
//collision checking
|
||||
//check for keys
|
||||
if(utils::isKeyDown(SDL_SCANCODE_W)) {
|
||||
m_Vel.y = 100;
|
||||
}
|
||||
if(utils::isKeyDown(SDL_SCANCODE_S)) {
|
||||
m_Vel.y = -100;
|
||||
}
|
||||
if(utils::isKeyDown(SDL_SCANCODE_A)) {
|
||||
m_Vel.x = -100;
|
||||
}
|
||||
if(utils::isKeyDown(SDL_SCANCODE_D)) {
|
||||
m_Vel.x = 100;
|
||||
}
|
||||
|
||||
Point2f nextPos = m_Position + m_Vel * elapsedTime;
|
||||
bool isColliding = false;
|
||||
|
||||
auto tiles = level.GetAllTiles();
|
||||
for (int x{0}; x < WorldLevel::WORLD_WIDTH; ++x) {
|
||||
for (int y{0}; y < WorldLevel::WORLD_HEIGHT; ++y) {
|
||||
@@ -26,20 +45,13 @@ void Player::Update(float elapsedTime, const WorldLevel& level) {
|
||||
if (tile->GetTileType() == GroundTileTypes::Dirt) {
|
||||
Rectf tileRect = Rectf{tile->GetPosition().x, tile->GetPosition().y, WorldLevel::TILE_WIDTH, WorldLevel::TILE_HEIGHT};
|
||||
if (utils::IsOverlapping(nextPos, m_Size, tileRect)) {
|
||||
//collision
|
||||
if (m_Vel.y < 0) {
|
||||
//collision from above
|
||||
m_Position.y = tileRect.bottom;
|
||||
m_Vel.y = 0;
|
||||
} else {
|
||||
m_Position.y = tileRect.bottom + m_Size.y;
|
||||
m_Vel.y = 0;
|
||||
}
|
||||
isColliding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_Vel = Point2f{m_Vel.x + float(acc.x * elapsedTime), m_Vel.y + float(acc.y * elapsedTime)};
|
||||
// m_Position += m_Vel * elapsedTime;
|
||||
m_Position = Point2f{m_Position.x + m_Vel.x * elapsedTime, m_Position.y + m_Vel.y * elapsedTime};
|
||||
|
||||
if(!isColliding) {
|
||||
m_Position = nextPos;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "WorldLevel.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
@@ -16,6 +17,21 @@ 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}});
|
||||
|
||||
|
||||
|
||||
// std::string dirtPath = + "tiles/dirt/dirt" + std::to_string(utils::randRange(1, 5)) + ".png";
|
||||
// m_pTextTexture = new Texture(dirtPath);
|
||||
@@ -28,30 +44,111 @@ void WorldLevel::Update(float elapsedSec) {
|
||||
int mouseX, mouseY;
|
||||
SDL_GetMouseState(&mouseX, &mouseY);
|
||||
m_mousePos = Point2f{ float(mouseX), float(mouseY) };
|
||||
m_player.Update(elapsedSec, *this);
|
||||
m_mousePos = m_pCamera->TransformMouse(m_mousePos);
|
||||
//m_player.Update(elapsedSec, *this);
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
if(utils::isKeyDown(SDL_SCANCODE_S)) {
|
||||
m_Rects[0].velocity.y += -10;
|
||||
}
|
||||
if(utils::isKeyDown(SDL_SCANCODE_A)) {
|
||||
m_Rects[0].velocity.x += -10;
|
||||
}
|
||||
if(utils::isKeyDown(SDL_SCANCODE_D)) {
|
||||
m_Rects[0].velocity.x += 10;
|
||||
}
|
||||
|
||||
Point2f intersectionPoint, normal;
|
||||
float contactTime;
|
||||
|
||||
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};
|
||||
|
||||
contactTimes.push_back({i, contactTime});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
void WorldLevel::Draw() const {
|
||||
m_pCamera->BeginRendering();
|
||||
|
||||
for (utils::MovingRectf rect : m_Rects) {
|
||||
utils::DrawRect(rect.bottomLeft, rect.width, rect.height);
|
||||
}
|
||||
|
||||
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};
|
||||
Point2f RayDir = Point2f{m_mousePos.x - RayPoint.x, m_mousePos.y - RayPoint.y};
|
||||
|
||||
utils::SetColor(Colors::WHITE);
|
||||
utils::DrawLine(RayPoint, m_mousePos);
|
||||
|
||||
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});
|
||||
}
|
||||
|
||||
|
||||
// utils::SetColor(Colors::YELLOW);
|
||||
// utils::FillEllipse(m_mousePos,2,2);
|
||||
for (size_t x { 0 }; x < WORLD_WIDTH; ++x) {
|
||||
for (size_t y { 0 }; y < WORLD_HEIGHT; ++y) {
|
||||
m_worldTiles[x][y]->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
utils::SetColor(Colors::WHITE);
|
||||
for (int x { -100 }; x < 100; ++x) {
|
||||
for (int y { -100 }; y < 100; ++y) {
|
||||
utils::DrawLine(x * 50, -5000, x * 50, 50000);
|
||||
utils::DrawLine(-5000, y * 50, 50000, y * 50);
|
||||
}
|
||||
}
|
||||
|
||||
// utils::SetColor(Colors::WHITE);
|
||||
// for (int x { -100 }; x < 100; ++x) {
|
||||
// for (int y { -100 }; y < 100; ++y) {
|
||||
// utils::DrawLine(x * 50, -5000, x * 50, 50000);
|
||||
// utils::DrawLine(-5000, y * 50, 50000, y * 50);
|
||||
// }
|
||||
// }
|
||||
utils::SetColor(Colors::MAGENTA);
|
||||
utils::FillEllipse(0, 0, 10, 10);
|
||||
utils::FillEllipse(0, 0, 5, 5);
|
||||
|
||||
m_player.Draw();
|
||||
//m_player.Draw();
|
||||
m_pCamera->EndRendering();
|
||||
|
||||
//utils::SetColor(Colors::WHITE);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <array>
|
||||
|
||||
#include "Player.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
class WorldLevel : public Level {
|
||||
@@ -29,6 +30,8 @@ public:
|
||||
|
||||
std::array<std::array<WorldTile*, WORLD_WIDTH>, WORLD_HEIGHT> GetAllTiles() const;
|
||||
|
||||
std::vector<utils::MovingRectf> m_Rects;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user