椭圆碰撞检测无法正常工作

所以我正在尝试实现椭圆可以与圆形连接的测试,但它不起作用。

edist = (float) Math.sqrt( Math.pow((px + ((pwidth/2) )) - (bx + (bsize/2)), 2 ) + Math.pow(-((py + ((pwidth/2)) ) - (bx + (bsize/2))), 2 ) ); 

这是完整的代码(需要Slick2D):

 import org.newdawn.slick.AppGameContainer; import org.newdawn.slick.BasicGame; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; public class ColTest extends BasicGame{ float px = 50; float py = 50; float pheight = 50; float pwidth = 50; float bx = 200; float by = 200; float bsize = 200; float edist; float pspeed = 3; Input input; public ColTest() { super("ColTest"); } @Override public void init(GameContainer gc) throws SlickException { } @Override public void update(GameContainer gc, int delta) throws SlickException { input = gc.getInput(); try{ if(input.isKeyDown(Input.KEY_UP)) py-=pspeed; if(input.isKeyDown(Input.KEY_DOWN)) py+=pspeed; if(input.isKeyDown(Input.KEY_LEFT)) px-=pspeed; if(input.isKeyDown(Input.KEY_RIGHT)) px+=pspeed; } catch(Exception e){} } public void render(GameContainer gc, Graphics g) throws SlickException { g.setColor(new Color(255,255,255)); g.drawString("col: " + col(), 10, 10); g.drawString("edist: " + edist + " dist: " + dist, 10, 100); g.fillRect(px, py, pwidth, pheight); g.setColor(new Color(255,0,255)); g.fillOval(px, py, pwidth, pheight); g.setColor(new Color(255,255,255)); g.fillOval(200, 200, 200, 200); } public boolean col(){ edist = (float) Math.sqrt(Math.pow((px + ((pwidth/2) )) - (bx + (bsize/2)), 2) + Math.pow(-((py + ((pwidth/2)) ) - (bx + (bsize/2))), 2)); if(edist <= (bsize/2) + (px + (pwidth/2))) return true; else return false; } public float rotate(float x, float y, float ox, float oy, float a, boolean b) { float dst = (float) Math.sqrt(Math.pow(x-ox,2.0)+ Math.pow(y-oy,2.0)); float oa = (float) Math.atan2(y-oy,x-ox); if(b) return (float) Math.cos(oa + Math.toRadians(a))*dst+ox; else return (float) Math.sin(oa + Math.toRadians(a))*dst+oy; } public static void main(String[] args) throws SlickException { AppGameContainer app = new AppGameContainer( new ColTest() ); app.setShowFPS(false); app.setAlwaysRender(true); app.setTargetFrameRate(60); app.setDisplayMode(800, 600, false); app.start(); } } 

使用椭圆是绝对的要求吗? 您可以通过用多个圆圈表示它们来近似发明者形状之间的碰撞。 这样,您可以在圆圈之间使用非常简单的碰撞检测,并且仍然可以为观看者提供高水平的准确性。

 collision(c1, c2) { dx = c1.x - c2.x; dy = c1.y - c2.y; dist = c1.radius + c2.radius; return (dx * dx + dy * dy <= dist * dist) } 

alt text http://sofzh.miximages.com/java/circle_collisions.png

找到交叉路口比你想象的要难。 你的col()方法有点偏,但这种方法最多能够告诉你单个点是否在圆圈内。 它无法真正检测到交叉点。

我用Google搜索了一些用于计算实际交叉点的代码。 我在JavaScript中找到了一个真正有趣且非常复杂的东西。 看看来源 。

如果你想要一些更简单(但不太准确)的东西,你可以检查椭圆周围的几个点,看看它们是否在圆圈内。

 private boolean isInCircle(float x, float y) { float r = bsize / 2; float center_x = bx + r; float center_y = by + r; float dist = (float) Math.sqrt(Math.pow(x - center_x, 2) + Math.pow(y - center_y, 2)); return dist < r; } public boolean col() { return isInCircle(px + pwidth / 2, py ) || // top isInCircle(px + pwidth , py + pheight / 2) || // right isInCircle(px + pwidth / 2, py + pheight ) || // bottom isInCircle(px , py + pheight / 2); // left } 

如果您计划实现更多形状和/或需要形状之间的最小距离,您可以开始使用GJK :您只需要为每个新形状实现支持function。 如果计算时间也很关键,那么GJK肯定是你应该看的东西,但它肯定需要你的一些更多的编程。

如果你能找到你的焦点,你可以检查与下面的伪代码冲突。 警告这仅适用于两个椭圆碰撞(椭圆和圆碰撞也可以)。

 r = length of semi major axis a_x = x coordinate of foci 1 of the first ellipse a_y = y coordinate of foci 1 of the first ellipse b_x = x coordinate of foci 2 of the first ellipse b_y = y coordinate of foci 2 of the first ellipse c_x = x coordinate of foci 1 of the second ellipse c_y = y coordinate of foci 1 of the second ellipse d_x = x coordinate of foci 2 of the second ellipse d_y = y coordinate of foci 2 of the second ellipse p_x = (a_x+b_x+c_x+d_x)/4 // ie the average of the foci x values p_y = (a_y+b_y+c_y+d_y)/4 // ie the average of the foci y values if r >= ( sqrt( (p_x + a_x)^2+(p_y + a_y)^2 ) + sqrt( (p_x + a_x)^2+(p_y + a_y)^2 ) ) then collision 

如果你真的想要推导我,请告诉我,我会提供。 但它使用的思想是椭圆的焦点和椭圆边缘上的任何点之间的距离之和是相隔的设定距离(半长轴)。 并且解决了两个椭圆体边缘上的点,如果存在,那么它们就是碰撞。