Added modular physics control.
This commit is contained in:
parent
c3fb6fa740
commit
77049c5bed
@ -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);
|
||||||
|
|
||||||
|
145
src/mygame/control/PhysicsControl.java
Normal file
145
src/mygame/control/PhysicsControl.java
Normal file
@ -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;
|
||||||
|
|
||||||
@ -51,6 +44,8 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone
|
|||||||
//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,13 +203,17 @@ 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…
x
Reference in New Issue
Block a user