Обнаружение столкновений иногда не работает ⇐ C++
Обнаружение столкновений иногда не работает
I've attempted to make a 2D collision simulator with variable squares that should run into each other. My code is able to work in one dimension in both the x and y axis or with one square going in the x axis and one square going in the y axis. However, when I set randomly generate sizes and velocities for all the squares, they start to overlap and it looks like the collision wasn't detected. I'm not sure whether it's a problem with my loop or my collision boolean or whether it requires a swept AABB collision detection.
I've attempted to use the solution found in Sporadic Collision Detection , However when I implement it in "platform::checkCollision" it adds space for the collisions making it look like they dont touch. However, they also don't overlap. I implement this by setting
int leftObjX = x + (vX * (1 / 60.0)); In "platform::checkCollision" and likewise with leftOtherX, upObjX, and upOtherX.
platform.h
#include "SDL_image.h" #include class platform { public: float x, y, vX, vY; int r, g, b; int size; SDL_Renderer* renderer; std::string file; platform(SDL_Renderer* renderer, float x, float y, float vX, float vY, int r, int g, int b, int size); bool checkCollision(platform* square); void collisionManager(platform* other); void checkWall(); void render(); void anglelessCollision(platform* other); private: }; platform.cpp
#include "platform.h" #include #include #include #include "Collision.h" #include #include platform::platform(SDL_Renderer* renderer, float x, float y, float vX, float vY, int r, int g,int b, int size) { this->r = r; this->g = g; this->b = b; this->renderer = renderer; this->x = x; this->y = y; this->vX = vX; this->vY = vY; this->size = size; } void platform::collisionManager(platform* other) { int distance = sqrt(pow(other->x - this->x, 2) + pow(other->y - this->y, 2)); if (distance checkCollision(other)) { this->anglelessCollision(other); } } } bool platform::checkCollision(platform* square) { int leftObjX = x; //+(vX * (1 / 60.0)); int rightObjX = leftObjX + this->size; int leftOtherX = square->x; //+ (square->vX * (1 / 60.0)); int upOtherY = square->y; //+(square->vY * (1 / 60.0)); int rightOtherX = leftOtherX + this->size; int downOtherY = upOtherY + this->size; int upObjY = y; //+(vY * (1 / 60.0)); int downObjY = upObjY + this->size; if (vX > 0 && leftObjX = leftOtherX && upObjY = upOtherY) { return true; } else if (vX < 0 && leftObjX = rightOtherX && upObjY = upOtherY) { return true; } else if (vY > 0 && leftObjX = leftOtherX && upObjY = upOtherY ) { return true; } else if (vY < 0 && leftObjX = leftOtherX && upObjY = downOtherY ) { return true; } return false; } void platform::checkWall() { if (x = 800 - (1.5 * size) && vX > 0) vX *= -1; if (y = 600 - (size / 2.0) && vY > 0) { vY *= -1; } } void platform::render() { double timeDelta = 1.0f/60; x += vX * timeDelta; y += vY * timeDelta; SDL_Rect destR; destR.x = (int) x; destR.y = (int) y; destR.w = destR.h = this->size; SDL_SetRenderDrawColor(renderer, r, g, b, 255); SDL_RenderFillRect(renderer, &destR); SDL_RenderPresent(renderer); } void platform::anglelessCollision(platform* other) { float m1, m2; float center1X = this->x + (size / 2.0); float center1Y = this->y + (size / 2.0); float center2X = other->x + (size / 2.0); float center2Y = other->y + (size / 2.0); float gamma = atan2((center2Y - center1Y), (center2X - center1X)); if (this->size >= other->size) { m1 = 1; m2 = other->size / ((float)this->size); } else { m2 = 1; m1 = this->size / ((float)other->size); } const float initDot = (this->vX * other->vX) + (this->vY * other->vY); const float scalar1 = ((2 * m2) / (m1 + m2)) * (((this->vX - other->vX) * (center1X - center2X) + (this->vY - other->vY) * (center1Y - center2Y)) / (pow(center1X - center2X, 2) + pow(center1Y - center2Y, 2))); const float scalar2 = ((2 * m1) / (m1 + m2)) * (((other->vX - this->vX) * (center2X - center1X) + (other->vY - this->vY) * (center2Y - center1Y)) / (pow(center2X - center1X, 2) + pow(center2Y - center1Y, 2))); this->vX -= (scalar1 * (center1X - center2X)); this->vY -= (scalar1 * (center1Y - center2Y)); other->vX -= (scalar2 * (center2X - center1X)); other->vY -= (scalar2 * (center2Y - center1Y)); const float finalDot = (this->vX * other->vX) + (this->vY * other->vY); } Game.cpp
#include "Game.h" #include "Background.h"; #include "TextureManager.h" #include "platform.h" #include "Collision.h" #include #include "SquareStorage.h" Game::Game() {} Game::~Game() {} Background* background; SDL_Renderer* Game::renderer = nullptr; platform* red; platform* blue; platform* arr[100]; SquareStorage* storage; SDL_Surface* surf; Collision* collide; const int Game::width = 800; const int Game::height = 640; void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) { int flags = 0; if (fullscreen) { flags = SDL_WINDOW_FULLSCREEN; } if (SDL_Init(SDL_INIT_EVERYTHING) == 0) { std::cout
Источник: https://stackoverflow.com/questions/781 ... -sometimes
I've attempted to make a 2D collision simulator with variable squares that should run into each other. My code is able to work in one dimension in both the x and y axis or with one square going in the x axis and one square going in the y axis. However, when I set randomly generate sizes and velocities for all the squares, they start to overlap and it looks like the collision wasn't detected. I'm not sure whether it's a problem with my loop or my collision boolean or whether it requires a swept AABB collision detection.
I've attempted to use the solution found in Sporadic Collision Detection , However when I implement it in "platform::checkCollision" it adds space for the collisions making it look like they dont touch. However, they also don't overlap. I implement this by setting
int leftObjX = x + (vX * (1 / 60.0)); In "platform::checkCollision" and likewise with leftOtherX, upObjX, and upOtherX.
platform.h
#include "SDL_image.h" #include class platform { public: float x, y, vX, vY; int r, g, b; int size; SDL_Renderer* renderer; std::string file; platform(SDL_Renderer* renderer, float x, float y, float vX, float vY, int r, int g, int b, int size); bool checkCollision(platform* square); void collisionManager(platform* other); void checkWall(); void render(); void anglelessCollision(platform* other); private: }; platform.cpp
#include "platform.h" #include #include #include #include "Collision.h" #include #include platform::platform(SDL_Renderer* renderer, float x, float y, float vX, float vY, int r, int g,int b, int size) { this->r = r; this->g = g; this->b = b; this->renderer = renderer; this->x = x; this->y = y; this->vX = vX; this->vY = vY; this->size = size; } void platform::collisionManager(platform* other) { int distance = sqrt(pow(other->x - this->x, 2) + pow(other->y - this->y, 2)); if (distance checkCollision(other)) { this->anglelessCollision(other); } } } bool platform::checkCollision(platform* square) { int leftObjX = x; //+(vX * (1 / 60.0)); int rightObjX = leftObjX + this->size; int leftOtherX = square->x; //+ (square->vX * (1 / 60.0)); int upOtherY = square->y; //+(square->vY * (1 / 60.0)); int rightOtherX = leftOtherX + this->size; int downOtherY = upOtherY + this->size; int upObjY = y; //+(vY * (1 / 60.0)); int downObjY = upObjY + this->size; if (vX > 0 && leftObjX = leftOtherX && upObjY = upOtherY) { return true; } else if (vX < 0 && leftObjX = rightOtherX && upObjY = upOtherY) { return true; } else if (vY > 0 && leftObjX = leftOtherX && upObjY = upOtherY ) { return true; } else if (vY < 0 && leftObjX = leftOtherX && upObjY = downOtherY ) { return true; } return false; } void platform::checkWall() { if (x = 800 - (1.5 * size) && vX > 0) vX *= -1; if (y = 600 - (size / 2.0) && vY > 0) { vY *= -1; } } void platform::render() { double timeDelta = 1.0f/60; x += vX * timeDelta; y += vY * timeDelta; SDL_Rect destR; destR.x = (int) x; destR.y = (int) y; destR.w = destR.h = this->size; SDL_SetRenderDrawColor(renderer, r, g, b, 255); SDL_RenderFillRect(renderer, &destR); SDL_RenderPresent(renderer); } void platform::anglelessCollision(platform* other) { float m1, m2; float center1X = this->x + (size / 2.0); float center1Y = this->y + (size / 2.0); float center2X = other->x + (size / 2.0); float center2Y = other->y + (size / 2.0); float gamma = atan2((center2Y - center1Y), (center2X - center1X)); if (this->size >= other->size) { m1 = 1; m2 = other->size / ((float)this->size); } else { m2 = 1; m1 = this->size / ((float)other->size); } const float initDot = (this->vX * other->vX) + (this->vY * other->vY); const float scalar1 = ((2 * m2) / (m1 + m2)) * (((this->vX - other->vX) * (center1X - center2X) + (this->vY - other->vY) * (center1Y - center2Y)) / (pow(center1X - center2X, 2) + pow(center1Y - center2Y, 2))); const float scalar2 = ((2 * m1) / (m1 + m2)) * (((other->vX - this->vX) * (center2X - center1X) + (other->vY - this->vY) * (center2Y - center1Y)) / (pow(center2X - center1X, 2) + pow(center2Y - center1Y, 2))); this->vX -= (scalar1 * (center1X - center2X)); this->vY -= (scalar1 * (center1Y - center2Y)); other->vX -= (scalar2 * (center2X - center1X)); other->vY -= (scalar2 * (center2Y - center1Y)); const float finalDot = (this->vX * other->vX) + (this->vY * other->vY); } Game.cpp
#include "Game.h" #include "Background.h"; #include "TextureManager.h" #include "platform.h" #include "Collision.h" #include #include "SquareStorage.h" Game::Game() {} Game::~Game() {} Background* background; SDL_Renderer* Game::renderer = nullptr; platform* red; platform* blue; platform* arr[100]; SquareStorage* storage; SDL_Surface* surf; Collision* collide; const int Game::width = 800; const int Game::height = 640; void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) { int flags = 0; if (fullscreen) { flags = SDL_WINDOW_FULLSCREEN; } if (SDL_Init(SDL_INIT_EVERYTHING) == 0) { std::cout
Источник: https://stackoverflow.com/questions/781 ... -sometimes
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение