Reputation: 308
What's up everyone,
Thanks for your time.
I am making a Pong clone, and I want to restrict Box2D to two MouseJoints maximum; one MouseJoint maximum per paddle. The MouseJoints should be created only if one of the user's two touches lands within either of the two paddle's boundaries.
I am getting a weird result with my code. If my first touch lands within the left paddle and my second touch lands outside of either paddle, a second MouseJoint is created on the left paddle (see attached image).
Note: In addition to the two MouseJoints on the left paddle, there are two PrismaticJoints in the image; one attached to each paddle.
To no avail, I've tried all of the algorithms that I could think of or adapt from other people's code.
If a code solution example or link could be posted, I would be much obliged.
Here is my code:
public class MyScreen implements Screen, InputProcessor{
/*========some variables and methods omitted for clarity========*/
/*multiple mouse joint experiment*/
public MouseJoint mouseJoint[] = new MouseJoint[2];
Body hitBody[] = new Body[2];
Body tempBody;
public MyScreen(Pong game) {
this.game = game;
}
/*---------------------Screen interface methods--------------------------*/
//methods omitted for clarity
/*---------------------end Screen interface methods----------------------*/
/*---------------------InputProcessor interface methods------------------*/
@Override
public boolean keyDown(int keycode) {
return false;
}
@Override
public boolean keyUp(int keycode) {
return false;
}
@Override
public boolean keyTyped(char character) {
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
testPoint.set(screenX, screenY, 0);
camera.unproject(testPoint);
// ask the world which bodies are within the given
// bounding box around the mouse pointer
hitBody[pointer] = null;
world.QueryAABB(callback, testPoint.x - 1.0f, testPoint.y - 1.0f, testPoint.x + 1.0f, testPoint.y + 1.0f);
hitBody[pointer] = tempBody;
// if we hit something we create a new mouse joint
// and attach it to the hit body.
if (hitBody[pointer] != null) {
MouseJointDef def = new MouseJointDef();
def.bodyA = groundBody;
def.bodyB = hitBody[pointer];
def.collideConnected = true;
def.target.set(hitBody[pointer].getPosition().x, hitBody[pointer].getPosition().y);
def.maxForce = 3000.0f * hitBody[pointer].getMass();
mouseJoint[pointer] = (MouseJoint)world.createJoint(def);
hitBody[pointer].setAwake(true);
} else {
}
return false;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (mouseJoint[pointer] != null) {
world.destroyJoint(mouseJoint[pointer]);
mouseJoint[pointer] = null;
}
return false;
}
/**a temporary vector for delta target destination during touchDragged() method**/
Vector2 target = new Vector2();
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (mouseJoint[pointer] != null) {
camera.unproject(testPoint.set(screenX, screenY, 0));
mouseJoint[pointer].setTarget(target.set(testPoint.x, testPoint.y));
}
return false;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
@Override
public boolean scrolled(int amount) {
return false;
}
/*----------------end InputProcessor interface methods------------------*/
/*------------------------helper methods------------------------------------*/
/*android screen touch vector for a mouse joint*/
Vector3 testPoint = new Vector3(); //we instantiate this vector and the callback here so we don't irritate the GC
QueryCallback callback = new QueryCallback() {
@Override public boolean reportFixture (Fixture fixture) {
// if the hit fixture's body is the ground body
// we ignore it
if (fixture.getBody() == groundBody) return true;
if (fixture.testPoint(testPoint.x, testPoint.y)) {
tempBody = fixture.getBody();
return false;
} else
return true;
}
};
/*------------------------end helper methods-------------------------------*/
}
Upvotes: 0
Views: 2119
Reputation: 630
From what I can see the tempBody
is never reset to null. What that means is that the first time you touch the pad it sets the tempBody
to the touched paddle and then when you press outside the body the callback will not find a new body but not reset the testBody
to null, so when you assign testBody
to hitBody[pointer]
it is setting it to the first paddle.
The way your touch down function should look like is:
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
testPoint.set(screenX, screenY, 0);
camera.unproject(testPoint);
// ask the world which bodies are within the given
// bounding box around the mouse pointer
hitBody[pointer] = null;
world.QueryAABB(callback, testPoint.x - 1.0f, testPoint.y - 1.0f, testPoint.x + 1.0f, testPoint.y + 1.0f);
hitBody[pointer] = tempBody;
// if we hit something we create a new mouse joint
// and attach it to the hit body.
if (hitBody[pointer] != null) {
MouseJointDef def = new MouseJointDef();
def.bodyA = groundBody;
def.bodyB = hitBody[pointer];
def.collideConnected = true;
def.target.set(hitBody[pointer].getPosition().x, hitBody[pointer].getPosition().y);
def.maxForce = 3000.0f * hitBody[pointer].getMass();
mouseJoint[pointer] = (MouseJoint)world.createJoint(def);
hitBody[pointer].setAwake(true);
} else {
}
tempBody = null;
return false;
}
This way the tempBody is always reset to null after use.
Upvotes: 2