## Black hole using Dyn4j

Posts that don't fit into other categories.
assofohdz
Posts: 26
Joined: Mon Apr 17, 2017 10:46 am

### Black hole using Dyn4j

Hi

I'm looking for a way to implement a center of gravitation, like black holes (or just planets in general), to use in my space game. Gravity is zero in my space game. Any ideas on how to achieve a center of gravitation that is not universal and also pulls in to a specific point in space as opposed to a general direction of gravity?

Kind regards,
Asser

assofohdz
Posts: 26
Joined: Mon Apr 17, 2017 10:46 am

### Re: Black hole using Dyn4j

I got it working.

1. Added the black holes with infinite mass, so they couldn't move.
2. Added a circle on top, that defines the bounds of the gravity
3. Checked for object types in a collisionlistener and applied a gravity if objects fit

assofohdz
Posts: 26
Joined: Mon Apr 17, 2017 10:46 am

### Re: Black hole using Dyn4j

Here is the code (got it from the JME Vector Shooter tutorial on tuts+):

Code: Select all

private PhysicsForce getAppliedGravity(double tpf, Wormhole wormhole, Vec3d wormholeLocation, Vec3d bodyLocation) {
//TODO: Mass of body should be a factor?
Vec3d difference = wormholeLocation.subtract(bodyLocation);
Vec3d gravity = difference.normalize().multLocal(tpf);
double distance = difference.length();

double wormholeGravity = wormhole.getForce();
double gravityDistance = wormhole.getDistance();

gravity.multLocal(wormholeGravity);
gravity.multLocal(gravityDistance / distance);

Force force = new Force(gravity.x, gravity.y);

PhysicsForce pf = new PhysicsForce(force, new Torque(), new Vector2());

return pf;
}

And here is my CollisionListener (i do it in Broad phase for now)

Code: Select all

@Override
public boolean collision(org.dyn4j.dynamics.Body body1, BodyFixture fixture1, org.dyn4j.dynamics.Body body2, BodyFixture fixture2) {

Entity one = (Entity) body1.getUserData();
Entity two = (Entity) body2.getUserData();

ObjectType ot1 = one.get(ObjectType.class);
ObjectType ot2 = two.get(ObjectType.class);
//TODO Not working because of infinate mass .. once we get 'inside' infinite mass we cannot move
if (ot1.getTypeName(ed).equals(ObjectTypes.WORMHOLE) && !ot2.getTypeName(ed).equals(ObjectTypes.WORMHOLE)) {
EntityId wormholeId = one.getId();
EntityId eId2 = two.getId();

Wormhole warp = ed.getComponent(wormholeId, Wormhole.class);
Position wormholePos = ed.getComponent(wormholeId, Position.class);

Vector2 bodyTranslation = body2.getTransform().getTranslation();
Vec3d bodyEntityLocation = new Vec3d(bodyTranslation.x, bodyTranslation.y, 0); //TODO: Arena setting?
//start applying gravity to other entity

PhysicsForce pf = getAppliedGravity(time.getTpf(), warp, wormholePos.getLocation(), bodyEntityLocation);

ed.setComponent(eId2, pf);
} else {
//Beam me up Scotty!
//TODO: Place blink animation at old and new location
body2.getTransform().setTranslation(warp.getTargetLocation().x, warp.getTargetLocation().y);
}
return false;
}

if (ot2.getTypeName(ed).equals(ObjectTypes.WORMHOLE) && !ot1.getTypeName(ed).equals(ObjectTypes.WORMHOLE)) {
EntityId wormholeId = two.getId();
EntityId eId2 = one.getId();

Wormhole warp = ed.getComponent(wormholeId, Wormhole.class);
Position wormholePos = ed.getComponent(wormholeId, Position.class);

Vector2 bodyTranslation = body1.getTransform().getTranslation();
Vec3d bodyEntityLocation = new Vec3d(bodyTranslation.x, bodyTranslation.y, 0); //TODO: Arena setting?
PhysicsForce pf = getAppliedGravity(time.getTpf(), warp, wormholePos.getLocation(), bodyEntityLocation);

ed.setComponent(eId2, pf);
} else {
//Beam me out of here
body1.getTransform().setTranslation(warp.getTargetLocation().x, warp.getTargetLocation().y);
}
return false;
}

return true; //Default, keep processing this event
}

I attached both a physical Circle to my wormhole, and a gravity Circle (for detecting when to apply gravity and when to warp the entity that hits the center of the wormhole), and to know which one of the circles is getting a collision, I do a check on the radius of the circle. I know its a bit crude, I'm open for other options.

William
Posts: 378
Joined: Sat Feb 06, 2010 10:23 pm

### Re: Black hole using Dyn4j

What you did is fine. If you didn't want the gravity well detector shape to be included in the world you could use the World.detect method instead:

For example:
1. // define the gravity well's shape
2. Convex convex = Geometry.createCircle(1.0);
3. convex.translate(1, 0.5);
4.
5. // after the update to the world
6. world.update(...);
7.
8. // get all fixtures that collide with the (in this case) world space convex
9. List<DetectResult> results = world.detect(convex, Transform.IDENTITY, ...);
10.
11. // each result is a fixture that collided with the convex shape
12. for (DetectResult result : results) {
13.   // result.getBody()
14.   // result.getFixture()
15. }

William

deepinspace
Posts: 8
Joined: Thu Jun 01, 2017 12:35 pm

### Re: Black hole using Dyn4j

Thank you for sharing this code. I was literally just wondering how to do this as well.

assofohdz
Posts: 26
Joined: Mon Apr 17, 2017 10:46 am

### Re: Black hole using Dyn4j

I changed it a bit since first go. I added tpf to the method, to make the forces more fluid, and seperated the force creation into its own method.

Code: Select all

public void collide(org.dyn4j.dynamics.Body body1, BodyFixture fixture1, org.dyn4j.dynamics.Body body2, BodyFixture fixture2, Manifold manifold, double tpf) {
EntityId one = (EntityId) body1.getUserData();
EntityId two = (EntityId) body2.getUserData();

if (wells.getObject(one) == fixture1) {
createWormholeForce(one, two, body1, body2, manifold.getPoints().get(0), tpf);
}

if (wells.getObject(two) == fixture2) {
createWormholeForce(two, one, body2, body1, manifold.getPoints().get(0), tpf);
}
}

private void createWormholeForce(EntityId wormholeEntityId, EntityId bodyEntityId, Body wormholeBody, Body body, ManifoldPoint mp, double tpf) {
Vec3d wormholeLocation = new Vec3d(wormholeBody.getTransform().getTranslationX(), wormholeBody.getTransform().getTranslationY(), 0);
Vec3d bodyLocation = new Vec3d(body.getTransform().getTranslation().x, body.getTransform().getTranslation().y, 0);

GravityWell gravityWell = ed.getComponent(wormholeEntityId, GravityWell.class);
//start applying gravity to other entity
Force force = getWormholeGravityOnBody(tpf, gravityWell, wormholeLocation, bodyLocation);
GameEntities.createForce(bodyEntityId, force, mp.getPoint(), ed);
}

private Force getWormholeGravityOnBody(double tpf, GravityWell wormhole, Vec3d wormholeLocation, Vec3d bodyLocation) {
Vec3d difference = wormholeLocation.subtract(bodyLocation);
Vec3d gravity = difference.normalize().multLocal(tpf);
double distance = difference.length();

double wormholeGravity = wormhole.getForce();
double gravityDistance = wormhole.getDistance();

switch (wormhole.getGravityType()) {
case GravityWell.PULL:
gravity.multLocal(Math.abs(wormholeGravity));
break;
case GravityWell.PUSH:
gravity.multLocal(-1 * Math.abs(wormholeGravity));
break;
}

gravity.multLocal(gravityDistance / distance);

Force force = new Force(gravity.x, gravity.y);

return force;
}