EDIT 2: Made some more alterations, now the one area i'm still confused on is: how to work out the vector to project on the separation axes? My projectOnto(..) method has some huge gaps now and i know i need to use the dot product but i don't really understand how to. I left my old code in there commented out so you can see what i was trying to do following an article on SAT but i don't really understand how it works. Appreciate any help!
EDIT: Made several alterations thanks to suggestions below but the problem is still the very same.
The only collision experience i've had was with simple rectangles, i wanted to find something that would allow me to define polygonal areas for collision and have been trying to make sense of SAT using these two links
Though i'm a bit iffy with the math for the most part i feel like i understand the theory! Except my implementation somewhere down the line must be off as:
(excuse the hideous font)
As mentioned above i have defined a CollisionPolygon class where most of my theory is implemented and then have a helper class called Vect which was meant to be for Vectors but has also been used to contain a vertex given that both just have two float values.
I've tried stepping through the function and inspecting the values to solve things but given so many axes and vectors and new math to work out as i go i'm struggling to find the erroneous calculation(s) and would really appreciate any help. Apologies if this is not suitable as a question!
CollisionPolygon.java:
package biz.hireholly.gameplay;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import biz.hireholly.gameplay.Types.Vect;
public class CollisionPolygon {
Paint paint;
private Vect[] vertices;
private Vect[] separationAxes;
int x; //actually the positions of the object that owns this CollisionPolygon
int y;
CollisionPolygon(Vect[] vertices){
this.vertices = vertices;
//compute edges and separations axes
separationAxes = new Vect[vertices.length];
for (int i = 0; i < vertices.length; i++) {
// get the current vertex
Vect p1 = vertices[i];
// get the next vertex
Vect p2 = vertices[i + 1 == vertices.length ? 0 : i + 1];
// subtract the two to get the edge vector
Vect edge = p1.subtract(p2);
// get either perpendicular vector (my perp method returns (y, -x)
// then get a nomralized version
Vect normal = edge.perp().normalize();
separationAxes[i] = normal;
}
paint = new Paint();
paint.setColor(Color.RED);
}
public void draw(Canvas c){
if(x != 0 && y != 0){
for (int i = 0; i < vertices.length; i++) {
Vect v1 = vertices[i];
Vect v2 = vertices[i + 1 == vertices.length ? 0 : i + 1];
c.drawLine(
x + v1.x,
y + v1.y,
x + v2.x,
y + v2.y,
paint);
}
}
}
public void update(int xPos, int yPos){
x = xPos;
y = yPos;
}
/* consider changing to a static function */
public boolean intersects(CollisionPolygon p){
// loop over this polygons separation exes
for (Vect axis : separationAxes) {
// project both shapes onto the axis
Vect proj1 = this.projectOnto(axis);
Vect proj2 = p.projectOnto(axis);
// do the projections overlap?
if (!proj1.overlap(proj2)) {
// then we can guarantee that the shapes do not overlap
return false;
}
}
// loop over the other polygons separation axes
Vect[] sepAxesOther = p.getSeparationAxes();
for (Vect axis : sepAxesOther) {
// project both shapes onto the axis
Vect proj1 = this.projectOnto(axis);
Vect proj2 = p.projectOnto(axis);
// do the projections overlap?
if (!proj1.overlap(proj2)) {
// then we can guarantee that the shapes do not overlap
return false;
}
}
// if we get here then we know that every axis had overlap on it
// so we can guarantee an intersection
return true;
}
private Vect projectOnto(Vect axis) {
//When using the dot function we take into account the absolute position using the owning objects x & y
// Not entirely certain if neccessary? appears to make no difference for the moment at least..
//TODO: need some sort of loop to figure out a vector that represents the max breadth of the polygon onto the current separation axes
Vect breadth =...
//This is the simplified formula for projecting a vector onto a normalised vector (the axis)
return axis.multiplyByScalar(breadth.dot(axis));
/*
* OLD FUNCTIONLITY
float min = axis.dot(new Vect(vertices[0].x+x, vertices[0].y+y));
float max = min;
for (int i = 1; i < vertices.length; i++) {
float p = axis.dot(new Vect(vertices[i].x+x, vertices[i].y+y));
if (p < min) {
min = p;
}
else if (p > max) {
max = p;
}
}
Vect minMaxProj = new Vect(min, max);
return minMaxProj;*/
}
public Vect[] getSeparationAxes() {
return separationAxes;
}
public Vect[] getVertices() {
return vertices;
}
}
Vect.java:
package biz.hireholly.gameplay.Types;
/* NOTE: Can also be used to hold vertices! Projections, coordinates ect */
public class Vect{
public float x;
public float y;
public Vect(float x, float y){
this.x = x;
this.y = y;
}
public Vect perp() {
return new Vect(y, -x);
}
public Vect subtract(Vect other) {
return new Vect(x - other.x, y - other.y);
}
public boolean overlap(Vect other) {
if(y > other.x && other.y > x){
return true;
}
return false;
}
/* used specifically for my SAT implementation which i'm figuring out as i go,
* references for later..
* http://www.gamedev.net/page/resources/_/technical/game-programming/2d-rotated-rectangle-collision-r2604
* http://www.codezealot.org/archives/55
*/
/* doing away with..
public float scalarDotProjection(Vect other) {
//multiplier = dot product / length^2
float multiplier = dot(other) / (x*x + y*y);
//to get the x/y of the projection vector multiply by x/y of axis
float projX = multiplier * x;
float projY = multiplier * y;
//we want to return the dot product of the projection, it's meaningless but useful in our SAT case
return dot(new Vect(projX,projY));
}*/
public float dot(Vect other){
return (other.x*x + other.y*y);
}
public float length(){
return (float)Math.sqrt((x*x + y*y));
}
public Vect normalize(){
return new Vect( x / length(), y / length());
}
public Vect multiplyByScalar(float s){
return new Vect(x*s, y*s);
}
}
as3
but you can translate it easily – Sri Harsha Chilakapati Oct 26 '12 at 12:20