/**
* Copyright 2008 - 2011
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.1
*/
package loon.action.collision;
import loon.LSystem;
import loon.core.geom.Line;
import loon.core.geom.Point;
import loon.core.geom.RectBox;
import loon.core.geom.Shape;
import loon.core.graphics.device.LColor;
import loon.core.graphics.device.LImage;
import loon.utils.MathUtils;
public final class CollisionHelper {
/**
* 检查两个坐标值是否在指定的碰撞半径内
*
* @param x1
* @param y1
* @param r1
* @param x2
* @param y2
* @param r2
* @return
*/
public static boolean isCollision(float x1, float y1, float r1, float x2,
float y2, float r2) {
float a = r1 + r2;
float dx = x1 - x2;
float dy = y1 - y2;
return a * a > dx * dx + dy * dy;
}
/**
* 获得两个矩形间距离
*
* @param box1
* @param box2
* @return
*/
public static float getDistance(final RectBox box1, final RectBox box2) {
final float xdiff = box1.x - box2.x;
final float ydiff = box1.y - box2.y;
return MathUtils.sqrt(xdiff * xdiff + ydiff * ydiff);
}
/**
* 检查两个矩形是否发生了碰撞
*
* @param rect1
* @param rect2
* @return
*/
public static boolean isRectToRect(RectBox rect1, RectBox rect2) {
return rect1.intersects(rect2);
}
/**
* 判断两个圆形是否发生了碰撞
*
* @param rect1
* @param rect2
* @return
*/
public static boolean isCircToCirc(RectBox rect1, RectBox rect2) {
Point middle1 = getMiddlePoint(rect1);
Point middle2 = getMiddlePoint(rect2);
float distance = middle1.distanceTo(middle2);
float radius1 = rect1.getWidth() / 2;
float radius2 = rect2.getWidth() / 2;
return (distance - radius2) < radius1;
}
/**
* 检查矩形与圆形是否发生了碰撞
*
* @param rect1
* @param rect2
* @return
*/
public static boolean isRectToCirc(RectBox rect1, RectBox rect2) {
float radius = rect2.getWidth() / 2;
Point middle = getMiddlePoint(rect2);
Point upperLeft = new Point(rect1.getMinX(), rect1.getMinY());
Point upperRight = new Point(rect1.getMaxX(), rect1.getMinY());
Point downLeft = new Point(rect1.getMinX(), rect1.getMaxY());
Point downRight = new Point(rect1.getMaxX(), rect1.getMaxY());
boolean collided = true;
if (!isPointToLine(upperLeft, upperRight, middle, radius)) {
if (!isPointToLine(upperRight, downRight, middle, radius)) {
if (!isPointToLine(upperLeft, downLeft, middle, radius)) {
if (!isPointToLine(downLeft, downRight, middle, radius)) {
collided = false;
}
}
}
}
return collided;
}
/**
* 换算点线距离
*
* @param point1
* @param point2
* @param middle
* @param radius
* @return
*/
private static boolean isPointToLine(Point point1, Point point2,
Point middle, float radius) {
Line line = new Line(point1, point2);
float distance = line.ptLineDist(middle);
return distance < radius;
}
/**
* 返回中间距离的Point2D形式
*
* @param rectangle
* @return
*/
private static Point getMiddlePoint(RectBox rectangle) {
return new Point(rectangle.getCenterX(), rectangle.getCenterY());
}
/**
* 判定指定的两张图片之间是否产生了碰撞
*
* @param src
* @param x1
* @param y1
* @param dest
* @param x2
* @param y2
* @return
*/
public boolean isPixelCollide(LImage src, float x1, float y1, LImage dest,
float x2, float y2) {
float width1 = x1 + src.getWidth() - 1, height1 = y1 + src.getHeight()
- 1, width2 = x2 + dest.getWidth() - 1, height2 = y2
+ dest.getHeight() - 1;
int xstart = (int) MathUtils.max(x1, x2), ystart = (int) MathUtils.max(
y1, y2), xend = (int) MathUtils.min(width1, width2), yend = (int) MathUtils
.min(height1, height2);
int toty = MathUtils.abs(yend - ystart);
int totx = MathUtils.abs(xend - xstart);
for (int y = 1; y < toty - 1; y++) {
int ny = MathUtils.abs(ystart - (int) y1) + y;
int ny1 = MathUtils.abs(ystart - (int) y2) + y;
for (int x = 1; x < totx - 1; x++) {
int nx = MathUtils.abs(xstart - (int) x1) + x;
int nx1 = MathUtils.abs(xstart - (int) x2) + x;
try {
if (((src.getPixel(nx, ny) & LSystem.TRANSPARENT) != 0x00)
&& ((dest.getPixel(nx1, ny1) & LSystem.TRANSPARENT) != 0x00)) {
return true;
} else if (getPixelData(src, nx, ny)[0] != 0
&& getPixelData(dest, nx1, ny1)[0] != 0) {
return true;
}
} catch (Exception e) {
}
}
}
return false;
}
private static int[] getPixelData(LImage image, int x, int y) {
return LColor.getRGBs(image.getPixel(x, y));
}
/**
* 判断指定大小的两组像素是否相交
*
* @param rectA
* @param dataA
* @param rectB
* @param dataB
* @return
*/
public static boolean intersect(RectBox rectA, int[] dataA, RectBox rectB,
int[] dataB) {
int top = (int) MathUtils.max(rectA.getY(), rectB.getY());
int bottom = (int) MathUtils.min(rectA.getBottom(), rectB.getBottom());
int left = (int) MathUtils.max(rectA.getX(), rectB.getX());
int right = (int) MathUtils.min(rectA.getRight(), rectB.getRight());
for (int y = top; y < bottom; y++) {
for (int x = left; x < right; x++) {
int colorA = dataA[(int) ((x - rectA.x) + (y - rectA.y)
* rectA.width)];
int colorB = dataB[(int) ((x - rectB.x) + (y - rectB.y)
* rectB.width)];
if (colorA >>> 24 != 0 && colorB >>> 24 != 0) {
return true;
}
}
}
return false;
}
/**
* 判断两个Shape是否相交
*
* @param s1
* @param s2
* @return
*/
public final static boolean intersects(Shape s1, Shape s2) {
if (s1 == null || s2 == null) {
return false;
}
return s1.intersects(s2);
}
/**
* 判断两个Shape是否存在包含关系
*
* @param s1
* @param s2
* @return
*/
public final static boolean contains(Shape s1, Shape s2) {
if (s1 == null || s2 == null) {
return false;
}
return s1.contains(s2);
}
public final static Line getLine(Shape shape, int s, int e) {
float[] start = shape.getPoint(s);
float[] end = shape.getPoint(e);
Line line = new Line(start[0], start[1], end[0], end[1]);
return line;
}
public final static Line getLine(Shape shape, float sx, float sy, int e) {
float[] end = shape.getPoint(e);
Line line = new Line(sx, sy, end[0], end[1]);
return line;
}
}