package org.anddev.andengine.collision;
import org.anddev.andengine.util.constants.Constants;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 11:50:19 - 11.03.2010
*/
public class ShapeCollisionChecker extends BaseCollisionChecker {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public static boolean checkCollision(final int pVerticesALength, final float[] pVerticesA, final int pVerticesBLength, final float[] pVerticesB) {
/* Check all the lines of A ... */
for(int a = pVerticesALength - 4; a >= 0; a -= 2) {
/* ... against all lines in B. */
if(ShapeCollisionChecker.checkCollisionSub(a, a + 2, pVerticesA, pVerticesB, pVerticesBLength)){
return true;
}
}
/* Also check the 'around the corner of the array' line of A against all lines in B. */
if(ShapeCollisionChecker.checkCollisionSub(pVerticesALength - 2, 0, pVerticesA, pVerticesB, pVerticesBLength)){
return true;
} else {
/* At last check if one polygon 'contains' the other one by checking
* if one vertex of the one vertices is contained by all of the other vertices. */
if(ShapeCollisionChecker.checkContains(pVerticesA, pVerticesALength, pVerticesB[Constants.VERTEX_INDEX_X], pVerticesB[Constants.VERTEX_INDEX_Y])) {
return true;
} else if(ShapeCollisionChecker.checkContains(pVerticesB, pVerticesBLength, pVerticesA[Constants.VERTEX_INDEX_X], pVerticesA[Constants.VERTEX_INDEX_Y])) {
return true;
} else {
return false;
}
}
}
/**
* Checks line specified by pVerticesA[pVertexIndexA1] and pVerticesA[pVertexIndexA2] against all lines in pVerticesB.
*/
private static boolean checkCollisionSub(final int pVertexIndexA1, final int pVertexIndexA2, final float[] pVerticesA, final float[] pVerticesB, final int pVerticesBLength) {
/* Check against all the lines of B. */
final float vertexA1X = pVerticesA[pVertexIndexA1 + Constants.VERTEX_INDEX_X];
final float vertexA1Y = pVerticesA[pVertexIndexA1 + Constants.VERTEX_INDEX_Y];
final float vertexA2X = pVerticesA[pVertexIndexA2 + Constants.VERTEX_INDEX_X];
final float vertexA2Y = pVerticesA[pVertexIndexA2 + Constants.VERTEX_INDEX_Y];
for(int b = pVerticesBLength - 4; b >= 0; b -= 2) {
if(LineCollisionChecker.checkLineCollision(vertexA1X, vertexA1Y, vertexA2X, vertexA2Y, pVerticesB[b + Constants.VERTEX_INDEX_X], pVerticesB[b + Constants.VERTEX_INDEX_Y], pVerticesB[b + 2 + Constants.VERTEX_INDEX_X], pVerticesB[b + 2 + Constants.VERTEX_INDEX_Y])){
return true;
}
}
/* Also check the 'around the corner of the array' line of B. */
if(LineCollisionChecker.checkLineCollision(vertexA1X, vertexA1Y, vertexA2X, vertexA2Y, pVerticesB[pVerticesBLength - 2], pVerticesB[pVerticesBLength - 1], pVerticesB[Constants.VERTEX_INDEX_X], pVerticesB[Constants.VERTEX_INDEX_Y])){
return true;
}
return false;
}
public static boolean checkContains(final float[] pVertices, final int pVerticesLength, final float pX, final float pY) {
int edgeResultSum = 0;
for(int i = pVerticesLength - 4; i >= 0; i -= 2) {
final int edgeResult = BaseCollisionChecker.relativeCCW(pVertices[i], pVertices[i + 1], pVertices[i + 2], pVertices[i + 3], pX, pY);
if(edgeResult == 0) {
return true;
} else {
edgeResultSum += edgeResult;
}
}
/* Also check the 'around the corner of the array' line. */
final int edgeResult = BaseCollisionChecker.relativeCCW(pVertices[pVerticesLength - 2], pVertices[pVerticesLength - 1], pVertices[Constants.VERTEX_INDEX_X], pVertices[Constants.VERTEX_INDEX_Y], pX, pY);
if(edgeResult == 0){
return true;
} else {
edgeResultSum += edgeResult;
}
final int vertexCount = pVerticesLength / 2;
/* Point is not on the edge, so check if the edge is on the same side(left or right) of all edges. */
return edgeResultSum == vertexCount || edgeResultSum == -vertexCount ;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}