Hello all,
Been playing around with jme physics by creating a little pinball table. But I've been seeing some issues I was hoping to get some recommendations on
from the experts here.
- When playing, if you let the ball slide to the end of the paddle, it doesn't launch off of it with much force. Like when you stop the ball by keeping the flipper up, then let it roll to the tip.
When hitting it mid flipper, it has good effect. I've tried different things like messing around with mass of the ball vs flippers, and changing addForce to addTorque, etc. But I can never seem
to get the desired results of close to a real table.
2. Sometime, it seems like the ball will overlap the flipper and the ball gets stuck in it for a second, then goes off with a force not normal. I am thinking it has to do with the flipper being
too fast for the ball, or too much time in between updates for how fast of force I am adding to the flipper.
3. I was putting this together on a laptop, pretty weak system. And when I run this same program on my home PC which is much more powerful, the results are a lot faster. I had thought
the physics would take into consideration FPS it it's calculation of gravity, etc, but it doesn't seem like it does. Maybe I could be wrong, and just don't have something set up right. But I am
not sure how to make things run the same on all computers. I'm getting around 170 FPS on my laptop, and much more on my home pc. When using physics, do I need to cap my FPS at a set
amount to get it to run the same on all PCs?
Thanks in advance for any suggestions. I will post the entire code below, in case it helps to run it to see what's going on. name of file is "brian5.java".
import com.jme.app.SimpleGame;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jmex.physics.DynamicPhysicsObject;
import com.jmex.physics.PhysicsObject;
import com.jmex.physics.PhysicsWorld;
import com.jmex.physics.StaticPhysicsObject;
import com.jmex.physics.joints.HingeJoint;
public class brian5 extends SimpleGame {
Vector3f axis = new Vector3f(1, 0, 0);
float angle = .3f;
Box boxFloor;
Sphere ball;
DynamicPhysicsObject ballPhysics;
Box anchorLeft;
DynamicPhysicsObject anchorLeftp;
Box padLeft;
DynamicPhysicsObject padLeftp;
Box anchorRight;
DynamicPhysicsObject anchorRightp;
Box padRight;
DynamicPhysicsObject padRightp;
protected void simpleInitGame() {
display.setTitle("Simple Test");
cam.getLocation().y = 10;
cam.update();
KeyBindingManager kb = KeyBindingManager.getKeyBindingManager();
kb.set("zforce", KeyInput.KEY_Z);
kb.set("xforce", KeyInput.KEY_X);
PhysicsWorld.create();
PhysicsWorld.getInstance().setUpdateRate(100);
PhysicsWorld.getInstance().setStepSize(2f / 100f);
// boxFloor
boxFloor = new Box("boxFloor", new Vector3f(0f, -0.5f, -20f), 10, 0.5f, 20);
boxFloor.getLocalRotation().fromAngleAxis(angle, axis);
rootNode.attachChild(boxFloor);
PhysicsObject boxFloorPhysics = new StaticPhysicsObject(boxFloor);
PhysicsWorld.getInstance().addObject(boxFloorPhysics);
// BoxTop
Box boxTop = new Box("boxTop", new Vector3f(0f, 2f, -41.f), 10, 2f, 1f);
boxTop.getLocalRotation().fromAngleAxis(angle, axis);
rootNode.attachChild(boxTop);
PhysicsObject boxTopPhysics = new StaticPhysicsObject(boxTop);
PhysicsWorld.getInstance().addObject(boxTopPhysics);
// BoxLeft
Box boxLeft = new Box("boxLeft", new Vector3f(-11f, 2f, -20f), 1, 2f, 20f);
boxLeft.getLocalRotation().fromAngleAxis(angle, axis);
rootNode.attachChild(boxLeft);
PhysicsObject boxLeftPhysics = new StaticPhysicsObject(boxLeft);
PhysicsWorld.getInstance().addObject(boxLeftPhysics);
// BoxRight
Box boxRight = new Box("boxRight", new Vector3f(11f, 2f, -20f), 1, 2f, 20f);
boxRight.getLocalRotation().fromAngleAxis(angle, axis);
rootNode.attachChild(boxRight);
PhysicsObject boxRightPhysics = new StaticPhysicsObject(boxRight);
PhysicsWorld.getInstance().addObject(boxRightPhysics);
//anchorLeft
anchorLeft = new Box("anchorLeft", new Vector3f(0f, 0f, 0f), 1f, 1.1f, 1f);
rootNode.attachChild(anchorLeft);
anchorLeftp = new DynamicPhysicsObject(anchorLeft, 10000f);
PhysicsWorld.getInstance().addObject(anchorLeftp);
//padLeft
padLeft = new Box("padLeft", new Vector3f(4f, 0f, 0f), 4f, 1f, .1f);
rootNode.attachChild(padLeft);
padLeftp = new DynamicPhysicsObject(padLeft, 20f);
PhysicsWorld.getInstance().addObject(padLeftp);
//hingeJointLeft
HingeJoint hingeJointLeft = new HingeJoint("hingeJointLeft", padLeftp, anchorLeftp);
hingeJointLeft.setMaxAngleStop(1f);
hingeJointLeft.setMinAngleStop(-.3f);
hingeJointLeft.attach();
hingeJointLeft.setAnchor(new Vector3f(1f, 1f, 0f));
hingeJointLeft.setAxis(new Vector3f(0, 1, 0));
//anchorRight
anchorRight = new Box("anchorRight", new Vector3f(0f, 0f, 0f), 1f, 1.1f, 1f);
rootNode.attachChild(anchorRight);
anchorRightp = new DynamicPhysicsObject(anchorRight, 10000f);
PhysicsWorld.getInstance().addObject(anchorRightp);
//anchorRightp.setEnabled(false);
//padRight
padRight = new Box("padRight", new Vector3f(-4f, 0f, 0f), 4f, 1f, .1f);
rootNode.attachChild(padRight);
padRightp = new DynamicPhysicsObject(padRight, 20f);
PhysicsWorld.getInstance().addObject(padRightp);
//hingeJointRight
HingeJoint hingeJointRight = new HingeJoint("hingeJointRight", padRightp, anchorRightp);
hingeJointRight.setMaxAngleStop(.3f);
hingeJointRight.setMinAngleStop(-1f);
hingeJointRight.attach();
hingeJointRight.setAnchor(new Vector3f(-1f, 1f, 0f));
hingeJointRight.setAxis(new Vector3f(0, 1, 0));
//move Left objects to left of table
anchorLeft.getLocalTranslation().x = -9f;
anchorLeft.getLocalTranslation().z = -1f;
anchorLeft.getLocalTranslation().y = 1f;
anchorLeft.getLocalRotation().fromAngleAxis(angle, axis);
padLeft.getLocalTranslation().x = -9f;
padLeft.getLocalTranslation().z = 1f;
padLeft.getLocalTranslation().y = 1f;
padLeft.getLocalRotation().fromAngleAxis(angle, axis);
anchorLeftp.syncWithGraphical();
padLeftp.syncWithGraphical();
//move Right objects to the right of table
anchorRight.getLocalTranslation().x = 9f;
anchorRight.getLocalTranslation().z = -1f;
anchorRight.getLocalTranslation().y = 1f;
anchorRight.getLocalRotation().fromAngleAxis(angle, axis);
padRight.getLocalTranslation().x = 9f;
padRight.getLocalTranslation().z = -1f;
padRight.getLocalTranslation().y = 1f;
padRight.getLocalRotation().fromAngleAxis(angle, axis);
anchorRightp.syncWithGraphical();
padRightp.syncWithGraphical();
// ball
ball = new Sphere("ball", 30, 30, 1);
ball.setRandomColors();
ball.setLocalTranslation(new Vector3f(3, 2, -5));
rootNode.attachChild(ball);
DynamicPhysicsObject ballPhysics = new DynamicPhysicsObject(ball, .05f);
PhysicsWorld.getInstance().addObject(ballPhysics);
createTableObjects();
//rootNode.setLightCombineMode(LightState.OFF);
}
private void createTableObjects() {
//Bumper Object 1 (bo1)
Box bo1 = new Box("bo1", new Vector3f(0f, 0f, 0f), .5f, 2f, 2f);
bo1.setLocalTranslation(new Vector3f(0f, 6f, -10f));
bo1.getLocalRotation().fromAngleAxis(angle, axis);
bo1.setSolidColor(ColorRGBA.blue);
rootNode.attachChild(bo1);
PhysicsObject bo1p = new StaticPhysicsObject(bo1);
PhysicsWorld.getInstance().addObject(bo1p);
}
protected void cleanup() {
super.cleanup();
// Before ending your application you should always clean up the PhysicsWorld.
PhysicsWorld.getInstance().cleanup();
}
protected void simpleUpdate() {
PhysicsWorld.getInstance().update(tpf);
KeyBindingManager kb = KeyBindingManager.getKeyBindingManager();
if (kb.isValidCommand("zforce", true)) {
padLeftp.addForce(new Vector3f(0, 0, 500));
} else {
padLeftp.addForce(new Vector3f(0, 0, -500));
}
if (kb.isValidCommand("xforce", true)) {
padRightp.addForce(new Vector3f(0, 0, 500));
} else {
padRightp.addForce(new Vector3f(0, 0, -500));
}
//Lock paddle to left
anchorLeft.getLocalTranslation().x = -9f;
anchorLeft.getLocalTranslation().z = -1f;
anchorLeftp.syncWithGraphical();
//Lock paddle to right
anchorRight.getLocalTranslation().x = 9f;
anchorRight.getLocalTranslation().z = -1f;
anchorRightp.syncWithGraphical();
}
public static void main(String[] args) {
brian5 app = new brian5();
app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, brian5.class
.getClassLoader()
.getResource("jmextest/data/images/jmephysics_logo.png"));
app.start();
}
}