圆形与方形碰撞检测以及需要响应C++ |OpenGL。我的问题就是这个"I need to keep the circle outside the square"

Circle vs Square Collision Detection AND NEED TO RESPONSE in C++ | OpenGL. My problem just this "I need to keep the circle outside the square"

本文关键字:the to outside square circle keep 问题 need 我的 碰撞检测 方形      更新时间:2023-10-16

我正在研究二维圆形与方形碰撞检测。我做了圆形和正方形之间的碰撞检测测试,没关系,碰撞检测没有问题,只是当圆形接触正方形时,我需要将圆保持在正方形之外。我希望圆圈不要进入正方形,圆圈必须留在正方形之外!我该怎么做?如何在广场外保持圆圈?

图片01 我的问题只是这个"当它们相互接触时,我只需要将圆圈保持在正方形之外"我做了这个碰撞检测测试,看着这个站点 => http://jeffreythompson.org/collision-detection/circle-rect.php,但在本教程中没有碰撞反应

请向我解释写代码

法典:

#include "shader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<vector>
#include<cmath>
#include <math.h>
using namespace std;
GLfloat blueSquareWidth = 0.3f, blueSquareHeight = 0.2f;
std::vector<glm::vec3>      vertices;
float x, y, z, r = 0.1f;
int num_segments = 48;
void DrawCircle()
{
for (int i = 0; i < num_segments; i++)
{
float theta = 2.0f * 3.1415926f * float(i) / float(num_segments);
//get the current angle
x = r * cosf(theta);
y = r * sinf(theta);
z = 0.0f;
vertices.push_back(glm::vec3(x, y, z));
} 
}
GLfloat blueSquareVertices[] =
{
0.0f, blueSquareHeight, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
blueSquareWidth, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
blueSquareWidth, blueSquareHeight, 0.0f,
0.0f, 0.0f, 1.0f
};
GLuint blueSqaureIndices[] =
{
0, 1, 2,
0, 2, 3
};
GLfloat rotationTime = 0.0f;
GLuint vbo[2], vao[2], ibo[2];
glm::vec3 blueSquarePosition(0.3f, 0.0f, 0.0f);
glm::vec3 spherePosition(0.660001f, 0.28f, 0.0f);
void inputKeys(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_TRUE)
{
glfwSetWindowShouldClose(window, true);
}
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_TRUE)
{
blueSquarePosition.y += 0.001f;
}
else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_TRUE)
{
blueSquarePosition.y -= 0.001f;
}
else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_TRUE)
{
blueSquarePosition.x -= 0.001f;
}
else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_TRUE)
{
blueSquarePosition.x += 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_TRUE)
{
spherePosition.y += 0.001f;
}
else if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_TRUE)
{
spherePosition.y -= 0.001f;
}
else if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_TRUE)
{
spherePosition.x -= 0.001f;
}
else if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_TRUE)
{
spherePosition.x += 0.001f;
}
}
bool circleRect(GLFWwindow* window) 
{
// temporary variables to set edges for testing
float testX = spherePosition.x;
float testY = spherePosition.y;
// which edge is closest?
if (spherePosition.x < blueSquarePosition.x)         
{
testX = blueSquarePosition.x;      // test left edge
}
else if (spherePosition.x > blueSquarePosition.x + blueSquareWidth) 
{
testX = blueSquarePosition.x + blueSquareWidth;   // right edge
}
if (spherePosition.y < blueSquarePosition.y)         
{
testY = blueSquarePosition.y;      // top edge
}
else if (spherePosition.y > blueSquarePosition.y + blueSquareHeight) 
{
testY = blueSquarePosition.y + blueSquareHeight;   // bottom edge
}
// get distance from closest edges
float distX = spherePosition.x - testX;
float distY = spherePosition.y - testY;
float distance = sqrt((distX * distX) + (distY * distY));
// if the distance is less than the radius, collision!
if (distance<= r) 
{
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
{
// WHAT I NEED TO DO HERE
}
if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
{
// WHAT I NEED TO DO HERE
}
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
{
// WHAT I NEED TO DO HERE
}
if (glfwGetKey(window, GLFW_KEY_BOTTOM) == GLFW_PRESS)
{
// WHAT I NEED TO DO HERE
}
return 1;
}
return 0;
}

int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 800, "Game Engine", NULL, 
NULL);
if (!window)
{
cout << "Failed to create a window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout << "Failed to initialize GLAD" << endl;
return -1;
}
DrawCircle();
glGenBuffers(1, &vbo[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(blueSquareVertices), blueSquareVertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao[0]);
glBindVertexArray(vao[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
glGenBuffers(1, &ibo[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(blueSqaureIndices), blueSqaureIndices, GL_STATIC_DRAW);
glGenBuffers(1, &vbo[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &vao[1]);
glBindVertexArray(vao[1]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
Shader shader("vs2.glsl", "fs2.glsl");
shader.useShader();
while (!glfwWindowShouldClose(window))
{
inputKeys(window);
circleRect(window);
glClearColor(0.6f, 0.8f, 0.8f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glm::mat4 blueSquareTransform(1.0f);
blueSquareTransform = glm::translate(blueSquareTransform, 
glm::vec3(blueSquarePosition));
GLuint blueSquareTransformUniform = 
glGetUniformLocation(shader.shader, "transform");
glUniformMatrix4fv(blueSquareTransformUniform, 1, GL_FALSE, 
glm::value_ptr(blueSquareTransform));
glBindVertexArray(vao[0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glm::mat4 redSquareTransform(1.0f);
redSquareTransform = glm::translate(redSquareTransform, 
glm::vec3(spherePosition));

GLuint redSquareTransformUniform = glGetUniformLocation(shader.shader, 
"transform");
glUniformMatrix4fv(redSquareTransformUniform, 1, GL_FALSE, 
glm::value_ptr(redSquareTransform));
glBindVertexArray(vao[1]);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size());
glfwSwapBuffers(window);
glfwPollEvents();
}
}

为了执行碰撞检测并防止穿透,您需要

上一个职位

当前位置

第一个问题是,在"我需要在这里做什么"行,你似乎已经错过了之前的位置。一旦你同时拥有了两者,你需要做:

如果当前位置发生冲突,则沿从当前位置到发生切换的上一个位置的线路进行二进制搜索。

您需要能够线性插值位置,其中 0 是前一个,1 是当前。

然后,如果你想做得好,而不是只是OK,然后计算碰撞,更新方向并重复剩余的长度。

相关文章: