I was needing a hollow circle that acts as an arena, so that other shapes can be either in or out, but not across it, so I implemented it, it's just an extension to Circle that redefines touches
In case someone finds it useful:
Code:
package net.phys2d.raw.shapes;
/**
* A hollow circle, only collides with another circles on the border
*
* @author Tulsi
*/
public strictfp class HollowCircle extends Circle {
/**
* @param radius
*/
public HollowCircle(float radius) {
super(radius);
}
/**
* Check if this circle touches another
*
* @param x
* The x position of this circle
* @param y
* The y position of this circle
* @param other
* The other circle
* @param ox
* The other circle's x position
* @param oy
* The other circle's y position
* @return True if they touch
*/
public strictfp boolean touches(float x, float y, Circle other, float ox,
float oy) {
float totalRad2 = getRadius() + other.getRadius();
float dx = Math.abs(ox - x);
float dy = Math.abs(oy - y);
float radDiff = getRadius() - other.getRadius();
// outside
if (dx > totalRad2 || dy > totalRad2) {
return false;
}
// inside
if (radDiff * radDiff >= dx * dx + dy * dy) {
return false;
}
// in between
totalRad2 *= totalRad2;
return totalRad2 >= ((dx * dx) + (dy * dy));
}
}
The modified CircleCircleCollider:
Code:
package net.phys2d.raw.collide;
import net.phys2d.math.MathUtil;
import net.phys2d.math.Vector2f;
import net.phys2d.raw.Body;
import net.phys2d.raw.Contact;
import net.phys2d.raw.shapes.Circle;
import net.phys2d.raw.shapes.HollowCircle;
/**
* A collider for circle 2 circle collisions
*
* The create() method is used as a factory just in case this class becomes
* stateful eventually.
*
* @author Kevin Glass
*/
public strictfp class CircleCircleCollider implements Collider {
/**
* @see net.phys2d.raw.collide.Collider#collide(net.phys2d.raw.Contact[],
* net.phys2d.raw.Body, net.phys2d.raw.Body)
*/
public int collide(Contact[] contacts, Body bodyA, Body bodyB) {
float x1 = bodyA.getPosition().getX();
float y1 = bodyA.getPosition().getY();
float x2 = bodyB.getPosition().getX();
float y2 = bodyB.getPosition().getY();
boolean touches = bodyA.getShape().getBounds().touches(x1, y1,
bodyB.getShape().getBounds(), x2, y2);
if (!touches) {
return 0;
}
Circle circleA = (Circle) bodyA.getShape();
Circle circleB = (Circle) bodyB.getShape();
touches = circleA.touches(x1, y1, circleB, x2, y2);
if (!touches) {
return 0;
}
Vector2f normal = MathUtil
.sub(bodyB.getPosition(), bodyA.getPosition());
float sep = (circleA.getRadius() + circleB.getRadius())
- normal.length();
normal.normalise();
Vector2f pt = MathUtil.scale(normal, circleA.getRadius());
pt.add(bodyA.getPosition());
contacts[0].setPosition(pt);
if (sep < circleB.getRadius() || !(circleA instanceof HollowCircle)) {
contacts[0].setNormal(normal);
contacts[0].setSeparation(-sep);
} else {
// we're on the inside
contacts[0].setNormal(normal.negate());
contacts[0].setSeparation(-(circleB.getRadius() - sep));
}
FeaturePair fp = new FeaturePair();
contacts[0].setFeature(fp);
return 1;
}
}
And finally a HollowCircleDemo:
Code:
package net.phys2d.raw.test;
import net.phys2d.raw.Body;
import net.phys2d.raw.StaticBody;
import net.phys2d.raw.World;
import net.phys2d.raw.shapes.Circle;
import net.phys2d.raw.shapes.HollowCircle;
/**
* A simple demo with HollowCircle
*
* @author Tulsi
*/
public class HollowCircleDemo extends AbstractDemo {
/**
* Create the demo
*/
public HollowCircleDemo() {
super("Phys2D HollowCircle Demo");
}
/**
* @see net.phys2d.raw.test.AbstractDemo#init(net.phys2d.raw.World)
*/
protected void init(World world) {
Body body1 = new StaticBody("bounds", new HollowCircle(200));
body1.setPosition(250, 250);
body1.setRestitution(1);
world.add(body1);
Body body2 = new Body(new Circle(20), 10);
body2.setPosition(300, 200);
body2.setRestitution(1);
world.add(body2);
Body body3 = new Body(new Circle(5), 10);
body3.setPosition(200, 150);
body3.setRestitution(1);
world.add(body3);
Body body4 = new Body(new Circle(30), 10);
body4.setPosition(222, 111);
body4.setRestitution(1);
world.add(body4);
}
/**
* Entry point for tetsing
*
* @param argv
* The arguments to the test
*/
public static void main(String[] argv) {
HollowCircleDemo demo = new HollowCircleDemo();
demo.start();
}
}
kev, jon or anybody, if you want a diff patch, just let me know