Added modular physics control.

pull/1/head
Joshua Sigona 5 years ago
parent c3fb6fa740
commit 77049c5bed
  1. 1
      nbproject/private/private.xml
  2. 20
      src/mygame/appstate/RunLevel.java
  3. 145
      src/mygame/control/PhysicsControl.java
  4. 75
      src/mygame/control/PlayableCharacter.java

@ -5,6 +5,7 @@
<group> <group>
<file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/Main.java</file> <file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/Main.java</file>
<file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/appstate/RunLevel.java</file> <file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/appstate/RunLevel.java</file>
<file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/control/PhysicsControl.java</file>
<file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/control/PlayableCharacter.java</file> <file>file:/E:/GameProjects/Rabi-Bounce-Bounce-R/src/mygame/control/PlayableCharacter.java</file>
</group> </group>
</open-files> </open-files>

@ -18,11 +18,16 @@ import com.jme3.input.InputManager;
import com.jme3.input.KeyInput; import com.jme3.input.KeyInput;
import com.jme3.input.controls.KeyTrigger; import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight; import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor; import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import static com.jme3.shader.Shader.ShaderType.Geometry;
import static com.jme3.shader.VarType.Vector3; import static com.jme3.shader.VarType.Vector3;
import com.jme3.shadow.DirectionalLightShadowFilter; import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.DirectionalLightShadowRenderer; import com.jme3.shadow.DirectionalLightShadowRenderer;
@ -30,6 +35,7 @@ import com.jme3.util.SkyFactory;
import com.jme3.water.WaterFilter; import com.jme3.water.WaterFilter;
import mygame.Main; import mygame.Main;
import static mygame.Main.main; import static mygame.Main.main;
import mygame.control.PhysicsControl;
import mygame.control.PlayableCharacter; import mygame.control.PlayableCharacter;
import mygame.control.PlayablePhysicsCharacter; import mygame.control.PlayablePhysicsCharacter;
@ -76,7 +82,19 @@ public class RunLevel extends BaseAppState
playerNode.attachChild(player); playerNode.attachChild(player);
playerNode.addControl(new PlayableCharacter()); playerNode.addControl(new PlayableCharacter());
playerNode.setUserData("Level", world); playerNode.setUserData("Level", world);
playerNode.setUserData("Terrain", main.SearchForTerrain(world));
for (int i=0;i<500;i++) {
Node sphereNode = new Node();
Geometry sphere = new Geometry("PhysicsSphere",new Sphere((int)(Math.random()*10)+3,(int)(Math.random()*10)+3,3f));
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.randomColor());
sphere.setMaterial(mat);
sphere.setLocalTranslation(0.01f,1.5f,0.01f);
sphereNode.attachChild(sphere);
sphereNode.addControl(new PhysicsControl(world,0.0f,-0.2f,3f));
sphereNode.setLocalTranslation(0.01f+75f*(float)Math.random()-75f*(float)Math.random(),25f+300f*(float)Math.random(),0.01f+75f*(float)Math.random()-75f*(float)Math.random());
reflectedScene.attachChild(sphereNode);
}
ChaseCamera chaseCam = new ChaseCamera(this.app.getCamera(), player, inputManager); ChaseCamera chaseCam = new ChaseCamera(this.app.getCamera(), player, inputManager);

@ -0,0 +1,145 @@
package mygame.control;
import com.jme3.collision.CollisionResults;
import template.*;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.Savable;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import java.io.IOException;
public class PhysicsControl extends AbstractControl implements Savable, Cloneable {
float jumpSpd = 0.1f;
float vspd = 0.0f;
float gravity = -0.25f;
float modelHeight = 2.5f;
Node levelData;
float walkOffTime = 0.25f; //How long you can jump after becoming airborne.
float airTime = 0.0f; //Amount of time in air.
public PhysicsControl(Node levelData, float jumpSpd, float gravity, float modelHeight){
this.levelData=levelData;
this.jumpSpd=jumpSpd;
this.gravity=gravity;
this.modelHeight=modelHeight;
}
/** This method is called when the control is added to the spatial,
* and when the control is removed from the spatial (setting a null value).
* It can be used for both initialization and cleanup.
*/
@Override
public void setSpatial(Spatial spatial) {
super.setSpatial(spatial);
spatial.setUserData("Level", levelData);
}
/** Implement your spatial's behaviour here.
* From here you can modify the scene graph and the spatial
* (transform them, get and set userdata, etc).
* This loop controls the spatial while the Control is enabled.
*/
@Override
protected void controlUpdate(float tpf){
if (!isOnGround()) {
vspd+=gravity*tpf;
airTime+=tpf;
} else {
vspd=0;
airTime=0;
}
spatial.move(0,vspd,0);
}
@Override
public Control cloneForSpatial(Spatial spatial){
final PhysicsControl control = new PhysicsControl((Node)(levelData.clone()),jumpSpd,gravity,modelHeight);
/* Optional: use setters to copy userdata into the cloned control */
// control.setIndex(i); // example
control.setSpatial(spatial);
return control;
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp){
/* Optional: rendering manipulation (for advanced users) */
}
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
// im.getCapsule(this).read(...);
}
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
// ex.getCapsule(this).write(...);
}
private Node GetLevel() {
return (Node)(spatial.getUserData("Level"));
}
void jump() {
setVerticalSpeed(jumpSpd);
}
void setVerticalSpeed(float spd) {
vspd = spd;
}
void addVerticalSpeed(float spd) {
vspd += spd;
}
float getVerticalSpeed() {
return vspd;
}
boolean isOnGround() {
if (vspd>0) {
System.out.println(vspd);
return false;
}
CollisionResults results = new CollisionResults();
Ray r = new Ray(spatial.getLocalTranslation().add(0,(modelHeight/2)-vspd,0),Vector3f.UNIT_Y.negate());
GetLevel().updateGeometricState();
GetLevel().collideWith(r, results);
if (results.size()>0) {
//System.out.println(results.getCollision(0));
if (results.getClosestCollision().getContactPoint().x!=0 ||
results.getClosestCollision().getContactPoint().y!=0 ||
results.getClosestCollision().getContactPoint().z!=0) {
//System.out.println(results.getClosestCollision());
if (results.getClosestCollision().getDistance()<=(modelHeight/2)+0.1-vspd) {
spatial.setLocalTranslation(results.getClosestCollision().getContactPoint());
return true;
} else {
return false;
}
} else {
vspd=jumpSpd; //???Undefined behavior.
}
}
/*if (results.size()>0) {
System.out.println("Distance: "+results.getClosestCollision().getDistance());
//if (results.getClosestCollision().getDistance()<=5.0f) {
//}
}*/
return false;
}
}

@ -29,16 +29,9 @@ import static mygame.Main.main;
public class PlayableCharacter extends AbstractControl implements Savable, Cloneable, ActionListener, AnalogListener, AnimEventListener { public class PlayableCharacter extends AbstractControl implements Savable, Cloneable, ActionListener, AnalogListener, AnimEventListener {
float speed = 10.0f; float speed = 10.0f;
float jumpSpd = 0.1f;
float vspd = 0.0f;
float gravity = -0.25f;
float walkOffTime = 0.25f; //How long you can jump after becoming airborne.
float airTime = 0.0f; //Amount of time in air.
float rotation_time = 3f; float rotation_time = 3f;
float current_time = 0.0f; float current_time = 0.0f;
Spatial standingOn = null;
Quaternion prevRot; Quaternion prevRot;
@ -50,6 +43,8 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone
AnimChannel channel; AnimChannel channel;
//AnimChannel channel_lowerbody; //AnimChannel channel_lowerbody;
AnimControl control; AnimControl control;
PhysicsControl physics;
public PlayableCharacter() { public PlayableCharacter() {
} // empty serialization constructor } // empty serialization constructor
@ -64,6 +59,14 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone
//control = spatial.getControl(BetterCharacterControl.class); //control = spatial.getControl(BetterCharacterControl.class);
Node myNode = (Node)spatial; Node myNode = (Node)spatial;
physics = new PhysicsControl(
(Node)spatial.getUserData("Level"),
0.1f,
-0.25f,
5f
);
myNode.addControl(physics);
control = ((Node)spatial).getChild(0).getControl(AnimControl.class); control = ((Node)spatial).getChild(0).getControl(AnimControl.class);
control.addListener(this); control.addListener(this);
channel = control.createChannel(); channel = control.createChannel();
@ -131,18 +134,6 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone
} }
} }
//isOnGround(); //isOnGround();
if (!isOnGround()) {
vspd+=gravity*tpf;
airTime+=tpf;
} else {
vspd=0;
airTime=0;
}
spatial.move(0,vspd,0);
}
private Node GetLevel() {
return (Node)(spatial.getUserData("Level"));
} }
private void SmoothMoveWalk(Vector3f walkDirection, float tpf) { private void SmoothMoveWalk(Vector3f walkDirection, float tpf) {
@ -212,12 +203,16 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone
public void onAnalog(String name, float value, float tpf) { public void onAnalog(String name, float value, float tpf) {
switch (name) { switch (name) {
case "Jump":{ case "Jump":{
if (isOnGround() || airTime<=walkOffTime) { if (isOnGround() || physics.airTime<=physics.walkOffTime) {
vspd=jumpSpd; physics.jump();
} }
}break; }break;
} }
} }
public boolean isOnGround() {
return physics.isOnGround();
}
@Override @Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) { public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
@ -227,42 +222,4 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone
@Override @Override
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) { public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
} }
private boolean isOnGround() {
if (vspd>0) {
System.out.println(vspd);
return false;
}
CollisionResults results = new CollisionResults();
Ray r = new Ray(spatial.getLocalTranslation().add(0,2.5f-vspd,0),Vector3f.UNIT_Y.negate());
GetLevel().updateGeometricState();
GetLevel().collideWith(r, results);
System.out.println("Collisions("+results.size()+"):");
for (int i=0;i<results.size();i++) {
System.out.println("Collision with "+results.getCollision(i).getGeometry().getName());
}
if (results.size()>0) {
//System.out.println(results.getCollision(0));
if (results.getClosestCollision().getContactPoint().x!=0 ||
results.getClosestCollision().getContactPoint().y!=0 ||
results.getClosestCollision().getContactPoint().z!=0) {
System.out.println(results.getClosestCollision());
if (results.getClosestCollision().getDistance()<=2.6-vspd) {
spatial.setLocalTranslation(results.getClosestCollision().getContactPoint());
return true;
} else {
return false;
}
} else {
vspd=jumpSpd; //???Undefined behavior.
}
}
/*if (results.size()>0) {
System.out.println("Distance: "+results.getClosestCollision().getDistance());
//if (results.getClosestCollision().getDistance()<=5.0f) {
//}
}*/
return false;
}
} }
Loading…
Cancel
Save