Here's the full program again, the problem is that the moving object isn't being pushed back out, rather the moving object seems to disappear off screen. If anybody could take a look at this and offer suggestions that would be much appreciated. Collision detection has made my head almost explode at this point.
The errors were due to a couple of transposed entries. I've updated the code to the working program in case anybody else reading this wants to see the SAT in action. The response is a little buggy, but as long as you don't try to break this demonstration, it should teach something.
// SFML Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "SFML\Graphics.hpp"
#include <memory>
#include <iostream>
int loops = 0;
sf::Vector2f Normalize(sf::Vector2f& input){
if(sqrt(input.x * input.x + input.y * input.y) == 0){
input.x = 1;
return input;
}
float length = sqrt(input.x * input.x + input.y * input.y);
input.x /= length;
input.y /= length;
return input;
}
sf::Vector2f GetNormalAxis(sf::VertexArray &shape, int index){
sf::Vector2f vectorOne = shape[index].position;
sf::Vector2f vectorTwo;
if(index >= shape.getVertexCount() - 1)
vectorTwo = shape[0].position;
else
vectorTwo = shape[index+1].position;
sf::Vector2f normalAxis(-(vectorTwo.y - vectorOne.y), vectorTwo.x - vectorOne.x);
normalAxis = Normalize(normalAxis);
return normalAxis;
}
float DotProduct(sf::Vector2f &vectorOne, sf::Vector2f &vectorTwo){
return vectorOne.x * vectorTwo.x + vectorOne.y * vectorTwo.y;
}
class WorldObject{
public:
WorldObject(){}
~WorldObject(){}
sf::VertexArray &GetOutline(){ return outline; }
private:
sf::VertexArray outline;
};
class Projection{
public:
Projection(sf::Vector2f &axis, sf::VertexArray &vertices){
min = DotProduct(axis, vertices[0].position);
max = min;
for(int i = 1; i < vertices.getVertexCount(); i++){
float proj = DotProduct(axis, vertices[i].position);
if(proj < min){
min = proj;
}
else if(proj > max){
max = proj;
}
}
}
~Projection(){}
float GetMin(){ return min; }
float GetMax(){ return max; }
float GetOverlap(Projection &projection){
if(projection.GetMin() <= max && max <= projection.GetMax()){
return max - projection.GetMin();
}
else if(min <= projection.GetMax() && projection.GetMax() <= max){
return projection.GetMax() - min;
}
else{
return 0;
}
}
private:
float min, max;
};
int _tmain(int argc, _TCHAR* argv[]){
sf::RenderWindow window(sf::VideoMode(500, 500, 32), "Test");
WorldObject object;
WorldObject objectTwo;
object.GetOutline().setPrimitiveType(sf::PrimitiveType::Quads);
object.GetOutline().append(sf::Vertex(sf::Vector2f(200, 180)));
object.GetOutline().append(sf::Vertex(sf::Vector2f(180, 180)));
object.GetOutline().append(sf::Vertex(sf::Vector2f(180, 200)));
object.GetOutline().append(sf::Vertex(sf::Vector2f(200, 200)));
objectTwo.GetOutline().setPrimitiveType(sf::PrimitiveType::Quads);
objectTwo.GetOutline().append(sf::Vertex(sf::Vector2f(20 + 80, 0)));
objectTwo.GetOutline().append(sf::Vertex(sf::Vector2f(0 + 80, 0)));
objectTwo.GetOutline().append(sf::Vertex(sf::Vector2f(0 + 80, 20)));
objectTwo.GetOutline().append(sf::Vertex(sf::Vector2f(20 + 80, 20)));
while(window.isOpen()){
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)){
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
for(int i = 0; i < objectTwo.GetOutline().getVertexCount(); i++){
objectTwo.GetOutline()[i].position.x += .05;
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
for(int i = 0; i < objectTwo.GetOutline().getVertexCount(); i++){
objectTwo.GetOutline()[i].position.x -= .05;
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
for(int i = 0; i < objectTwo.GetOutline().getVertexCount(); i++){
objectTwo.GetOutline()[i].position.y += .05;
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
for(int i = 0; i < objectTwo.GetOutline().getVertexCount(); i++){
objectTwo.GetOutline()[i].position.y -= .05;
}
}
//if(sf::FloatRect(object.GetOutline().getBounds()).intersects(sf::FloatRect(objectTwo.GetOutline().getBounds()))){
std::vector<sf::Vector2f> axesOne;
std::vector<sf::Vector2f> axesTwo;
//for both shapes, get their axes
for(int i = 0; i < object.GetOutline().getVertexCount(); i++){
axesOne.push_back(GetNormalAxis(object.GetOutline(), i));
}
for(int i = 0; i < objectTwo.GetOutline().getVertexCount(); i++){
//would call collision.getnormalaxis or whatevs
axesTwo.push_back(GetNormalAxis(objectTwo.GetOutline(), i));
}
//for both sets of axes
//project
float overlap = 50000000000;
sf::Vector2f smallestAxis;
for(int i = 0; i < axesOne.size(); i++){
Projection projectionOne(axesOne[i], object.GetOutline());
Projection projectionTwo(axesOne[i], objectTwo.GetOutline());
float o = projectionOne.GetOverlap(projectionTwo);
if(o == 0.f){
//no overlap
}
if(o < overlap){
overlap = o;
smallestAxis = axesOne[i];
}
}
for(int i = 0; i < axesTwo.size(); i++){
Projection projectionOne(axesTwo[i], object.GetOutline());
Projection projectionTwo(axesTwo[i], objectTwo.GetOutline());
float o = projectionOne.GetOverlap(projectionTwo);
if(o == 0.f){
//no overlap
}
if(o < overlap){
overlap = o;
smallestAxis = axesTwo[i];
}
}
for(int i = 0; i < objectTwo.GetOutline().getVertexCount(); i++){
//if it's moving in a negative dir, do this
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
objectTwo.GetOutline()[i].position -= (smallestAxis * overlap);
//otherwise do ditto += ditto
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
objectTwo.GetOutline()[i].position += (smallestAxis * overlap);
}
//}
window.clear();
window.draw(objectTwo.GetOutline());
window.draw(object.GetOutline());
window.display();
loops++;
}
return 0;
}