Note that there are some explanatory texts on larger screens.

plurals
  1. POBasic AABB collision using projection vector
    primarykey
    data
    text
    <p>I've been searching around for the past few days, and researching about Vectors, but still can't quite get my head around the math..</p> <p>I have two <a href="http://en.wikipedia.org/wiki/Bounding_volume" rel="nofollow">AABB's</a>. On collision I want my method to return a Vector that I can then add to the position Vector to bring my object back into bounds.</p> <p>Here's my current code:</p> <p>(The position Vector is the center of the AABB)</p> <pre><code>public Vector2f collide(Sprite other) { if(!collideBoolean(other)) return null; //no collision float xAxis = Math.abs(this.position.x - other.getX()); //distance between centers on x axis float yAxis = Math.abs(this.position.y - other.getY()); //distance between centers on y axis //these combined values show the minimum distance apart the objects need to be to not collide int cw = this.getHalfWidth() + other.getHalfWidth(); //combined width int ch = this.getHalfHeight() + other.getHalfHeight(); //combined height float ox = Math.abs(xAxis - cw); //overlap on x float oy = Math.abs(yAxis - ch); //overlap on y //direction Vector2f dir = new Vector2f(this.position); dir.sub(other.getPosition()); //subtract other.position from this.position dir.normalise(); return new Vector2f(dir.x * ox, dir.y * oy); } </code></pre> <p>(self explanatory but here is also the code for collideBoolean(Sprite other) )</p> <pre><code>public boolean collideBoolean(Sprite other) { //code using halfwidths and centers if(Math.abs(this.position.x - other.getX()) &gt; (this.getHalfWidth() + other.getHalfWidth())) return false; if(Math.abs(this.position.y - other.getY()) &gt; (this.getHalfHeight() + other.getHalfHeight())) return false; return true; } </code></pre> <p>My current code more or less works.. But the (this) object that is colliding against 'other' gets pushed out AND sides towards the closest corner of 'other'. </p> <p>I think I'm really close. Surely it'll be something blindingly obvious to a different set of eyes, but I can't quite work it out. Any help would be greatly appreciated!</p> <p>Thanks,</p> <p><strong>EDIT:</strong></p> <p>Adding this into the end of the collide(Sprite other) method works, except isn't as tidy as I'd like. Also when moving into the 'other' body along only one axis it works fine, but if you push into the body at an angle you get inside the shape and it throws you out randomly. </p> <p>This is probably just because I'm moving too many pixels per step, and I should sweep test my collisions though</p> <p>(this code looks at the projection vector to see which component is bigger, then 0's out the biggest component. This means that I'm only projecting out of the shape along the shortest path)</p> <pre><code> .... //direction .... Vector2f projection = new Vector2f(dir.x * (ox+1), dir.y * (oy+1)); if(Math.abs(projection.x) &gt; Math.abs(projection.y)) projection.x = 0; else if(Math.abs(projection.y) &gt; Math.abs(projection.x)) projection.y = 0; return projection; } </code></pre> <p><strong>EDIT TWO</strong></p> <p>With the implementation of Ishtar's answer things were looking good. But I've found if I'm colliding a small object with a wide object, it accurately fixes the collision near the centers, but as you get out near the corners you sink into the shape. </p> <p>Like this:</p> <pre><code> _ _______l_l_________ | | |______OK___________| _--________________ | -- | |_____SINKS IN______| </code></pre> <p><strong>EDIT THREE</strong></p> <p>Current collision code:</p> <pre><code>public class Collision { /** fix collision based on mass */ public static void collide(Sprite s1, Sprite s2) { float xAxis = Math.abs(s1.getX() - s2.getX()); //distance between centers float yAxis = Math.abs(s1.getY() - s2.getY()); //distance between centers int cw = s1.getHalfWidth() + s2.getHalfWidth(); //combined width int ch = s1.getHalfHeight() + s2.getHalfHeight(); //combined height //early exit if(xAxis &gt; cw) return; if(yAxis &gt; ch) return; float ox = Math.abs(xAxis - cw); //overlap on x float oy = Math.abs(yAxis - ch); //overlap on y if(s1.getMass() &lt;= s2.getMass()) fixCollision(s1, s2, ox+1, oy+1); //the +1's make you get out of the shape instead of else //if(s1.getMass() &gt; s2.getMass()) //correcting you onto the edge where you'll be in constant collision fixCollision(s2, s1, ox+1, oy+1); } /** * Fixes the collision * @param s1 : this gets pushed out (should be lower mass) * @param s2 : this stays where it is * @param ox : the overlap along the x axis * @param oy : the overlap along the y axis */ private static void fixCollision(Sprite s1, Sprite s2, float ox, float oy) { //direction Vector2f dir = new Vector2f(s1.getPosition()); dir.sub(s2.getPosition()); dir.normalise(); Vector2f projection = new Vector2f(dir.x * (ox), dir.y * (oy)); if(Math.abs(projection.x) &gt; Math.abs(projection.y)) projection.x = 0; else if(Math.abs(projection.y) &gt; Math.abs(projection.x)) projection.y = 0; if(ox &gt; oy) s1.getPosition().add( new Vector2f(0, dir.y * oy) ); //overlap is bigger on x so project on y else if(ox &lt; oy) s1.getPosition().add( new Vector2f(dir.x * ox, 0)); //overlap is bigger on x so project on x else s1.getPosition().add( new Vector2f(dir.x * ox, dir.y * oy)); //corner to corner } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload