/** * Create a shallow clone for the JME cloner. * * @return a new control (not null) */ @Override public Object jmeClone() { BetterCharacterControl control = new BetterCharacterControl(radius, height, mass); control.setJumpForce(jumpForce); control.spatial = this.spatial; return control; }
/** * Update this control. Invoked once per frame during the logical-state * update, provided the control is added to a scene graph. Do not invoke * directly from user code. * * @param tpf the time interval between frames (in seconds, ≥0) */ @Override public void update(float tpf) { super.update(tpf); rigidBody.getPhysicsLocation(location); //rotation has been set through viewDirection applyPhysicsTransform(location, rotation); }
/** * Updates the local coordinate system from the localForward and localUp * vectors, adapts localForward, sets localForwardRotation quaternion to * local Z-forward rotation. */ protected void updateLocalCoordinateSystem() { //gravity vector has possibly changed, calculate new world forward (UNIT_Z) calculateNewForward(localForwardRotation, localForward, localUp); localLeft.set(localUp).crossLocal(localForward); rigidBody.setPhysicsRotation(localForwardRotation); updateLocalViewDirection(); }
/** * Toggle character ducking. When ducked the characters capsule collision * shape height will be multiplied by duckedFactor to make the capsule * smaller. When unducking, the character will check with a ray test if it * can in fact unduck and only do so when its possible. You can test the * state using isDucked(). * * @param enabled true→duck, false→unduck */ public void setDucked(boolean enabled) { if (enabled) { setHeightPercent(duckedFactor); ducked = true; wantToUnDuck = false; } else { if (checkCanUnDuck()) { setHeightPercent(1); ducked = false; } else { wantToUnDuck = true; } } }
/** * Create a collision shape based on the scale parameter. The new shape is a * compound shape containing an offset capsule. * * @return a new compound shape (not null) */ protected CollisionShape getShape() { //TODO: cleanup size mess.. CapsuleCollisionShape capsuleCollisionShape = new CapsuleCollisionShape(getFinalRadius(), (getFinalHeight() - (2 * getFinalRadius()))); CompoundCollisionShape compoundCollisionShape = new CompoundCollisionShape(); Vector3f addLocation = new Vector3f(0, (getFinalHeight() / 2.0f), 0); compoundCollisionShape.addChildShape(capsuleCollisionShape, addLocation); return compoundCollisionShape; }
checkOnGround(); if (wantToUnDuck && checkCanUnDuck()) { setHeightPercent(1); wantToUnDuck = false; ducked = false;
/** * Alter the height of collision shape. * * @param percent the desired height, as a percentage of the full height */ protected void setHeightPercent(float percent) { scale.setY(percent); rigidBody.setCollisionShape(getShape()); }
@Override public void simpleInitApp() { flyCam.setEnabled(false); BulletAppState bulletAppState = new BulletAppState(); bulletAppState.setDebugEnabled(true); bulletAppState.setSpeed(0f); stateManager.attach(bulletAppState); PhysicsSpace space = bulletAppState.getPhysicsSpace(); float radius = 1f; CollisionShape sphere = new SphereCollisionShape(radius); CollisionShape box = new BoxCollisionShape(Vector3f.UNIT_XYZ); RigidBodyControl rbc = new RigidBodyControl(box); rbc.setEnabled(false); rbc.setPhysicsSpace(space); rootNode.addControl(rbc); BetterCharacterControl bcc = new BetterCharacterControl(radius, 4f, 1f); bcc.setEnabled(false); bcc.setPhysicsSpace(space); rootNode.addControl(bcc); GhostControl gc = new GhostControl(sphere); gc.setEnabled(false); gc.setPhysicsSpace(space); rootNode.addControl(gc); } }
/** * Updates the local X-Z view direction and the corresponding rotation * quaternion for the spatial. */ protected void updateLocalViewDirection() { //update local rotation quaternion to use for view rotation localForwardRotation.multLocal(rotatedViewDirection.set(viewDirection)); calculateNewForward(rotation, rotatedViewDirection, localUp); }
/** * Test whether the character is on the ground, by means of a ray test. */ protected void checkOnGround() { TempVars vars = TempVars.get(); Vector3f location = vars.vect1; Vector3f rayVector = vars.vect2; float height = getFinalHeight(); location.set(localUp).multLocal(height).addLocal(this.location); rayVector.set(localUp).multLocal(-height - 0.1f).addLocal(location); List<PhysicsRayTestResult> results = space.rayTest(location, rayVector); vars.release(); for (PhysicsRayTestResult physicsRayTestResult : results) { if (!physicsRayTestResult.getCollisionObject().equals(rigidBody)) { onGround = true; return; } } onGround = false; }
physicsCharacter = new BetterCharacterControl(0.3f, 2.5f, 8f); characterNode.addControl(physicsCharacter); getPhysicsSpace().add(physicsCharacter);
checkOnGround(); if (wantToUnDuck && checkCanUnDuck()) { setHeightPercent(1); wantToUnDuck = false; ducked = false;
/** * Create a collision shape based on the scale parameter. The new shape is a * compound shape containing an offset capsule. * * @return a new compound shape (not null) */ protected CollisionShape getShape() { //TODO: cleanup size mess.. CapsuleCollisionShape capsuleCollisionShape = new CapsuleCollisionShape(getFinalRadius(), (getFinalHeight() - (2 * getFinalRadius()))); CompoundCollisionShape compoundCollisionShape = new CompoundCollisionShape(); Vector3f addLocation = new Vector3f(0, (getFinalHeight() / 2.0f), 0); compoundCollisionShape.addChildShape(capsuleCollisionShape, addLocation); return compoundCollisionShape; }
/** * Toggle character ducking. When ducked the characters capsule collision * shape height will be multiplied by duckedFactor to make the capsule * smaller. When unducking, the character will check with a ray test if it * can in fact unduck and only do so when its possible. You can test the * state using isDucked(). * * @param enabled true→duck, false→unduck */ public void setDucked(boolean enabled) { if (enabled) { setHeightPercent(duckedFactor); ducked = true; wantToUnDuck = false; } else { if (checkCanUnDuck()) { setHeightPercent(1); ducked = false; } else { wantToUnDuck = true; } } }
/** * Alter the height of collision shape. * * @param percent the desired height, as a percentage of the full height */ protected void setHeightPercent(float percent) { scale.setY(percent); rigidBody.setCollisionShape(getShape()); }
/** * Updates the local X-Z view direction and the corresponding rotation * quaternion for the spatial. */ protected void updateLocalViewDirection() { //update local rotation quaternion to use for view rotation localForwardRotation.multLocal(rotatedViewDirection.set(viewDirection)); calculateNewForward(rotation, rotatedViewDirection, localUp); }
/** * Test whether the character is on the ground, by means of a ray test. */ protected void checkOnGround() { TempVars vars = TempVars.get(); Vector3f location = vars.vect1; Vector3f rayVector = vars.vect2; float height = getFinalHeight(); location.set(localUp).multLocal(height).addLocal(this.location); rayVector.set(localUp).multLocal(-height - 0.1f).addLocal(location); List<PhysicsRayTestResult> results = space.rayTest(location, rayVector); vars.release(); for (PhysicsRayTestResult physicsRayTestResult : results) { if (!physicsRayTestResult.getCollisionObject().equals(rigidBody)) { onGround = true; return; } } onGround = false; }
checkOnGround(); if (wantToUnDuck && checkCanUnDuck()) { setHeightPercent(1); wantToUnDuck = false; ducked = false;
/** * Create a shallow clone for the JME cloner. * * @return a new control (not null) */ @Override public Object jmeClone() { BetterCharacterControl control = new BetterCharacterControl(radius, height, mass); control.setJumpForce(jumpForce); control.spatial = this.spatial; return control; }
/** * Updates the local coordinate system from the localForward and localUp * vectors, adapts localForward, sets localForwardRotation quaternion to * local Z-forward rotation. */ protected void updateLocalCoordinateSystem() { //gravity vector has possibly changed, calculate new world forward (UNIT_Z) calculateNewForward(localForwardRotation, localForward, localUp); localLeft.set(localUp).crossLocal(localForward); rigidBody.setPhysicsRotation(localForwardRotation); updateLocalViewDirection(); }