1
General / Collisions and vertex arrays
« on: July 23, 2021, 10:19:21 pm »
Hi guys, I don't know if I've missed something, am tired, or am going crazy,
possibly all three.
I'm a beginner, been messing around with a little collision sandbox, which I kinda expanded from the particle system example in the tutorials.
I'm slowly getting things working though there are weird behaviours everywhere.
I have a bunch of balls (2d) bouncing around, and am able to draw a line and add points to it which the circles will bounce off of, so I thought I can use basically the same functions to make em bounce off a square, which is a quad.
After a load of stupid omissions I got the balls bouncing off 3 sides like they should, the fourth (vertex 3-0) was bouncing wrong though.
The line function has a quirk that if its not drawn left to right it doesnt work properly and it got transferred to the quad, I tried all sorts of different things to fix it (doingfunction(vertex 3,vertex0) instead of function(vertex0, vertex3) til finally I found a way which really puzzles me.
For that one side only, I have to create a new vertexarray with two vertices, copy the positions from the two vertices from the quad into them, and feed those vertices into the formula.
The formula just takes coordinates so why would it matter if I copy those coordinates into some new vertices?
Even so it only works partially though, if the bottom vertex(3rd) is on the left and top(1st) on the right
The code is ridiculously messy please be gentle I'm happy to read any suggestions as long as they're attached with an answer to my question,
thanks guys
possibly all three.
I'm a beginner, been messing around with a little collision sandbox, which I kinda expanded from the particle system example in the tutorials.
I'm slowly getting things working though there are weird behaviours everywhere.
I have a bunch of balls (2d) bouncing around, and am able to draw a line and add points to it which the circles will bounce off of, so I thought I can use basically the same functions to make em bounce off a square, which is a quad.
After a load of stupid omissions I got the balls bouncing off 3 sides like they should, the fourth (vertex 3-0) was bouncing wrong though.
The line function has a quirk that if its not drawn left to right it doesnt work properly and it got transferred to the quad, I tried all sorts of different things to fix it (doingfunction(vertex 3,vertex0) instead of function(vertex0, vertex3) til finally I found a way which really puzzles me.
For that one side only, I have to create a new vertexarray with two vertices, copy the positions from the two vertices from the quad into them, and feed those vertices into the formula.
The formula just takes coordinates so why would it matter if I copy those coordinates into some new vertices?
Even so it only works partially though, if the bottom vertex(3rd) is on the left and top(1st) on the right
The code is ridiculously messy please be gentle I'm happy to read any suggestions as long as they're attached with an answer to my question,
thanks guys
if (obstSpawned == true) {
if (drawing == false)
for (int j = 0; j < m_obstQ.size(); j++)
for (int k = 0; k < (m_obstQ[j].getVertexCount()); k++) {
sf::Vector2f o1;
sf::Vector2f o2;
//if going from last vertex to 0 do this weirdness with the new vertices
int id = k + 1;
if (id == m_obstQ[j].getVertexCount())
id = 0;
if (id == 0) {
sf::Vertex v0(m_obstQ[j][k].position);
sf::Vertex v1(m_obstQ[j][id].position);
sf::VertexArray va;
va.setPrimitiveType(sf::LineStrip);
va.append(v0);
va.append(v1);
o1 = (va[0].position);
o2 = (va[1].position);
}
//which vertex is on which side seems to matter too
else {
if (m_obstQ[j][k].position.x < m_obstQ[j][id].position.x)
{
o1 = (m_obstQ[j][k].position);
o2 = (m_obstQ[j][id].position);
}
else {
o1 = (m_obstQ[j][id].position);
o2 = (m_obstQ[j][k].position);
}
}
sf::Vector2f Cp = closestPoint(o1, o2, bPos);
float x = Cp.x - bPos.x;
float y = Cp.y - bPos.y;
float Dis = sqrt((x * x) + (y * y));
if (Dis <= r) p.gravity = false;
else
if(gravity == true) p.gravity = true;
//the collisionsO stuff is just cuz I run a clock when a collision happens so it don't do it again next frame
if (collisionsO[j * pCount + i] == false) {
//point a
sf::Vector2f A = checklinescollide(bPos, p.bVec, o1, o2);
//little helper to see where the collision point is
cC.setRadius(20);
cC.setOrigin(20, 20);
cC.setFillColor(sf::Color(0, 70, 120, 255));
cC.setPosition(A);
if(A != sf::Vector2f(0,0))
if (A.x > 0 || A.y > 0)
{
//closest point
sf::Vector2f cP = closestPoint(o1, o2, bPos);
//little helper to see closest point on line
/* cp[0].position = sf::Vector2f(cP);
cp[1].position = sf::Vector2f(cP.x + 5, cP.y);
cp[2].position = sf::Vector2f(cP.x + 5, cP.y + 5);
cp[3].position = sf::Vector2f(cP.x, cP.y + 5);*/
if (p.colliding == false) {
p.Circ = bPos;
//point 1
p.P1 = closestPoint(o1, o2, bPos);
p.colliding = true;
}
float x = cP.x - bPos.x;
float y = cP.y - bPos.y;
float dis = sqrt((x * x) + (y * y));
if (dis <= r) {
if (gravity || !gravity ) {
sf::Vector2f P3 = bPos + (p.P1 - cP);
sf::Vector2f vel = ((P3 - bPos) + (P3 - bPos)) + bPos;
p.velocity = normalize(p.Circ - vel) * p.speed;
collisionsO[j * pCount + i] = true;
p.colliding = false;
}
}
}
}
}
}
if (drawing == false)
for (int j = 0; j < m_obstQ.size(); j++)
for (int k = 0; k < (m_obstQ[j].getVertexCount()); k++) {
sf::Vector2f o1;
sf::Vector2f o2;
//if going from last vertex to 0 do this weirdness with the new vertices
int id = k + 1;
if (id == m_obstQ[j].getVertexCount())
id = 0;
if (id == 0) {
sf::Vertex v0(m_obstQ[j][k].position);
sf::Vertex v1(m_obstQ[j][id].position);
sf::VertexArray va;
va.setPrimitiveType(sf::LineStrip);
va.append(v0);
va.append(v1);
o1 = (va[0].position);
o2 = (va[1].position);
}
//which vertex is on which side seems to matter too
else {
if (m_obstQ[j][k].position.x < m_obstQ[j][id].position.x)
{
o1 = (m_obstQ[j][k].position);
o2 = (m_obstQ[j][id].position);
}
else {
o1 = (m_obstQ[j][id].position);
o2 = (m_obstQ[j][k].position);
}
}
sf::Vector2f Cp = closestPoint(o1, o2, bPos);
float x = Cp.x - bPos.x;
float y = Cp.y - bPos.y;
float Dis = sqrt((x * x) + (y * y));
if (Dis <= r) p.gravity = false;
else
if(gravity == true) p.gravity = true;
//the collisionsO stuff is just cuz I run a clock when a collision happens so it don't do it again next frame
if (collisionsO[j * pCount + i] == false) {
//point a
sf::Vector2f A = checklinescollide(bPos, p.bVec, o1, o2);
//little helper to see where the collision point is
cC.setRadius(20);
cC.setOrigin(20, 20);
cC.setFillColor(sf::Color(0, 70, 120, 255));
cC.setPosition(A);
if(A != sf::Vector2f(0,0))
if (A.x > 0 || A.y > 0)
{
//closest point
sf::Vector2f cP = closestPoint(o1, o2, bPos);
//little helper to see closest point on line
/* cp[0].position = sf::Vector2f(cP);
cp[1].position = sf::Vector2f(cP.x + 5, cP.y);
cp[2].position = sf::Vector2f(cP.x + 5, cP.y + 5);
cp[3].position = sf::Vector2f(cP.x, cP.y + 5);*/
if (p.colliding == false) {
p.Circ = bPos;
//point 1
p.P1 = closestPoint(o1, o2, bPos);
p.colliding = true;
}
float x = cP.x - bPos.x;
float y = cP.y - bPos.y;
float dis = sqrt((x * x) + (y * y));
if (dis <= r) {
if (gravity || !gravity ) {
sf::Vector2f P3 = bPos + (p.P1 - cP);
sf::Vector2f vel = ((P3 - bPos) + (P3 - bPos)) + bPos;
p.velocity = normalize(p.Circ - vel) * p.speed;
collisionsO[j * pCount + i] = true;
p.colliding = false;
}
}
}
}
}
}
sf::Vector2f checklinescollide(sf::Vector2f b, sf::Vector2f bV,
sf::Vector2f l1, sf::Vector2f l2) {
float A1 = bV.y - b.y;
float B1 = b.x - bV.x;
float C1 = A1 * b.x + B1 * b.y;
float A2 = l2.y - l1.y;
float B2 = l1.x - l2.x;
float C2 = A2 * l1.x + B2 * l1.y;
float det = A1 * B2 - A2 * B1;
if (det != 0) {
float x = (B2 * C1 - B1 * C2) / det;
float y = (A1 * C2 - A2 * C1) / det;
if (x >= fmin(b.x, bV.x) && x <= fmax(b.x, bV.x)
&& x >= fmin(l1.x, l2.x) && x <= fmax(l1.x, l2.x)
&& y >= fmin(b.y, bV.y) && y <= fmax(b.y, bV.y)
&& y >= fmin(l1.y, l2.y) && y <= fmax(l1.y, l2.y))
return sf::Vector2f(x, y);
}
else
return sf::Vector2f(0, 0);
}
sf::Vector2f l1, sf::Vector2f l2) {
float A1 = bV.y - b.y;
float B1 = b.x - bV.x;
float C1 = A1 * b.x + B1 * b.y;
float A2 = l2.y - l1.y;
float B2 = l1.x - l2.x;
float C2 = A2 * l1.x + B2 * l1.y;
float det = A1 * B2 - A2 * B1;
if (det != 0) {
float x = (B2 * C1 - B1 * C2) / det;
float y = (A1 * C2 - A2 * C1) / det;
if (x >= fmin(b.x, bV.x) && x <= fmax(b.x, bV.x)
&& x >= fmin(l1.x, l2.x) && x <= fmax(l1.x, l2.x)
&& y >= fmin(b.y, bV.y) && y <= fmax(b.y, bV.y)
&& y >= fmin(l1.y, l2.y) && y <= fmax(l1.y, l2.y))
return sf::Vector2f(x, y);
}
else
return sf::Vector2f(0, 0);
}
sf::Vector2f closestPoint(sf::Vector2f l1,
sf::Vector2f l2, sf::Vector2f c) {
float A1 = l2.y - l1.y;
float B1 = l1.x - l2.x;
double C1 = (l2.y - l1.y) * l1.x + (l1.x - l2.x) * l1.y;
double C2 = -B1 * c.x + A1 * c.y;
double det = A1 * A1 - -B1 * B1;
double cx = 0;
double cy = 0;
if (det != 0) {
cx = (float)((A1 * C1 - B1 * C2) / det);
cy = (float)((A1 * C2 - -B1 * C1) / det);
}
else {
cx = c.x;
cy = c.y;
}
sf::Vector2f cP(cx, cy);
if (cP.x < l1.x || cP.x > l2.x)
return sf::Vector2f(0, 0);
else
return cP;
}
sf::Vector2f l2, sf::Vector2f c) {
float A1 = l2.y - l1.y;
float B1 = l1.x - l2.x;
double C1 = (l2.y - l1.y) * l1.x + (l1.x - l2.x) * l1.y;
double C2 = -B1 * c.x + A1 * c.y;
double det = A1 * A1 - -B1 * B1;
double cx = 0;
double cy = 0;
if (det != 0) {
cx = (float)((A1 * C1 - B1 * C2) / det);
cy = (float)((A1 * C2 - -B1 * C1) / det);
}
else {
cx = c.x;
cy = c.y;
}
sf::Vector2f cP(cx, cy);
if (cP.x < l1.x || cP.x > l2.x)
return sf::Vector2f(0, 0);
else
return cP;
}