Added physics simulation and some platforming tests.

pull/1/head
Joshua Sigona 5 years ago
parent 8d6e84845d
commit 0c53d2ff94
  1. 6
      assets/Models/Oto.j3m
  2. BIN
      assets/Models/Oto.jpg
  3. 15
      assets/Models/Oto.material
  4. BIN
      assets/Models/Oto.mesh.j3o
  5. 3
      assets/Models/Oto.mesh.j3odata
  6. 29285
      assets/Models/Oto.mesh.xml
  7. 8801
      assets/Models/Oto.skeleton.xml
  8. 41497
      assets/Models/test ava/test ava.gltf
  9. BIN
      assets/Models/test ava/test ava.j3o
  10. 3
      assets/Models/test ava/test ava.j3odata
  11. BIN
      assets/Scenes/TestLevel.j3o
  12. BIN
      build/classes/mygame/Main.class
  13. 2
      nbproject/private/private.xml
  14. 53
      src/mygame/Main.java
  15. 159
      src/mygame/appstate/RunLevel.java
  16. 235
      src/mygame/control/PlayableCharacter.java
  17. 67
      src/template/MyBaseAppState.java
  18. 78
      src/template/MyControl.java

@ -0,0 +1,6 @@
Material OTO Lit : phong_lighting.j3md {
MaterialParameters {
Shininess: 8.0
DiffuseMap: Models/Oto/Oto.jpg
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

@ -0,0 +1,15 @@
material Material.002/SOLID/TEX/bluewarrior1024.j/VertCol
{
technique
{
pass
{
diffuse vertexcolour
specular 0.000000 0.000000 0.000000 0.250000
texture_unit
{
texture Oto.jpg
}
}
}
}

Binary file not shown.

@ -0,0 +1,3 @@
#
#Fri Jun 19 20:56:22 KST 2020
ORIGINAL_PATH=Models/Oto.mesh.xml

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,3 @@
#
#Fri Jun 19 15:57:58 KST 2020
ORIGINAL_PATH=Models/test ava/test ava.gltf

Binary file not shown.

Binary file not shown.

@ -4,6 +4,8 @@
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<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/control/PlayableCharacter.java</file>
</group>
</open-files>
</project-private>

@ -1,6 +1,8 @@
package mygame;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.BaseAppState;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
@ -12,26 +14,35 @@ import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.util.SkyFactory;
import com.jme3.water.SimpleWaterProcessor;
import com.jme3.water.WaterFilter;
import mygame.appstate.RunLevel;
import mygame.control.PlayableCharacter;
/**
* This is the Main Class of your Game. You should only do initialization here.
* Move your Logic into AppStates or Controls
* @author normenhansen
*/
public class Main extends SimpleApplication {
public static Main main;
public static void main(String[] args) {
AppSettings settings = new AppSettings(true);
settings.setResolution(1600,900);
settings.setVSync(true);
settings.setFrameRate(120);
Main app = new Main();
app.setSettings(settings);
main = app;
app.start();
}
@Override
public void simpleInitApp() {
flyCam.setMoveSpeed(50);
CreateLevel();
flyCam.setEnabled(false);
//flyCam.setMoveSpeed(50);
BaseAppState level = new RunLevel();
stateManager.attach(level);
}
@Override
@ -43,32 +54,4 @@ public class Main extends SimpleApplication {
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
private void CreateLevel() {
Node reflectedScene = new Node("Reflected Scene");
rootNode.attachChild(reflectedScene);
Spatial TestLevel = assetManager.loadModel("Scenes/TestLevel.j3o");
Node world = (Node)TestLevel;
System.out.println(world.getChildren());
reflectedScene.attachChild(TestLevel);
reflectedScene.attachChild(SkyFactory.createSky(assetManager,"Textures/Sky/Bright/BrightSky.dds",false));
/*SimpleWaterProcessor waterProcessor = new SimpleWaterProcessor(assetManager);
waterProcessor.setReflectionScene(reflectedScene);
waterProcessor.setWaterColor(new ColorRGBA(0.0f,0.0f,0.0f,1.0f));
waterProcessor.setWaterDepth(2);
waterProcessor.setWaterTransparency(0.9f);
waterProcessor.setWaveSpeed(0.02f);
waterProcessor.setDistortionScale(0.3f);
waterProcessor.setDistortionMix(0.6f);
waterProcessor.
viewPort.addProcessor(waterProcessor);
world.getChild("WaterNode").setMaterial(waterProcessor.getMaterial());*/
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
viewPort.addProcessor(fpp);
Vector3f lightDir = new Vector3f(-2.9f,-1.2f,-5.8f);
WaterFilter water = new WaterFilter(reflectedScene, lightDir);
fpp.addFilter(water);
//world.getChild("WaterNode").setQueueBucket(Bucket.Transparent);
}
}

@ -0,0 +1,159 @@
package mygame.appstate;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import template.*;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AppStateManager;
import com.jme3.app.state.BaseAppState;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.ChaseCamera;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import static com.jme3.shader.VarType.Vector3;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import com.jme3.util.SkyFactory;
import com.jme3.water.WaterFilter;
import mygame.Main;
import mygame.control.PlayableCharacter;
public class RunLevel extends BaseAppState
implements AnimEventListener {
private SimpleApplication app;
private Node rootNode;
private AssetManager assetManager;
private AppStateManager stateManager;
private InputManager inputManager;
private ViewPort viewPort;
private BulletAppState physics;
@Override
protected void initialize(Application app) {
//It is technically safe to do all initialization and cleanup in the
//onEnable()/onDisable() methods. Choosing to use initialize() and
//cleanup() for this is a matter of performance specifics for the
//implementor.
//TODO: initialize your AppState, e.g. attach spatials to rootNode
//super.initialize(stateManager, app);
this.app = (SimpleApplication) app; // can cast Application to something more specific
this.rootNode = this.app.getRootNode();
this.assetManager = this.app.getAssetManager();
this.stateManager = this.app.getStateManager();
this.inputManager = this.app.getInputManager();
this.viewPort = this.app.getViewPort();
this.physics = this.stateManager.getState(BulletAppState.class);
BulletAppState bulletAppState = new BulletAppState();
this.stateManager.attach(bulletAppState);
Node reflectedScene = new Node("Reflected Scene");
rootNode.attachChild(reflectedScene);
Spatial TestLevel = assetManager.loadModel("Scenes/TestLevel.j3o");
Node world = (Node)TestLevel;
TestLevel.addControl(new RigidBodyControl(0));
bulletAppState.getPhysicsSpace().addAll(TestLevel);
//System.out.println(world.getLocalLightList().size());
DirectionalLight sceneLight = (DirectionalLight)world.getLocalLightList().get(0);
Node player = (Node)assetManager.loadModel("Models/Oto/Oto.mesh.xml");
Node playerNode = new Node();
playerNode.attachChild(player);
playerNode.addControl(new PlayableCharacter(4f));
ChaseCamera chaseCam = new ChaseCamera(this.app.getCamera(), player, inputManager);
//channel.setLoopMode(LoopMode.Cycle);
world.attachChild(playerNode);
player.move(0,2.5f,0);
player.setLocalScale(0.5f);
BetterCharacterControl playerControl = new BetterCharacterControl(1.5f,4f,10f);
playerNode.addControl(playerControl);
playerNode.addControl(chaseCam);
playerControl.setJumpForce(new Vector3f(0,200f,0));
bulletAppState.getPhysicsSpace().add(playerControl);
bulletAppState.getPhysicsSpace().addAll(playerNode);
playerControl.setGravity(new Vector3f(0,-40f,0));
playerControl.warp(new Vector3f(0,10,10));
//System.out.println(world.getChildren());
reflectedScene.attachChild(world);
reflectedScene.attachChild(TestLevel);
reflectedScene.attachChild(SkyFactory.createSky(assetManager,"Textures/Sky/Bright/BrightSky.dds",false));
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
//viewPort.addProcessor(fpp);
Vector3f lightDir = new Vector3f(-2.9f,-1.2f,-5.8f);
WaterFilter water = new WaterFilter(reflectedScene, lightDir);
water.setWaterHeight(-1.5f);
fpp.addFilter(water);
final int SHADOWMAP_SIZE=1024;
DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
dlsr.setLight(sceneLight);
viewPort.addProcessor(dlsr);
DirectionalLightShadowFilter dlsf = new DirectionalLightShadowFilter(assetManager, SHADOWMAP_SIZE, 3);
dlsf.setLight(sceneLight);
dlsf.setEnabled(true);
fpp.addFilter(dlsf);
viewPort.addProcessor(fpp);
}
@Override
protected void cleanup(Application app) {
//TODO: clean up what you initialized in the initialize method,
//e.g. remove all spatials from rootNode
}
//onEnable()/onDisable() can be used for managing things that should
//only exist while the state is enabled. Prime examples would be scene
//graph attachment or input listener attachment.
@Override
protected void onEnable() {
//Called when the state is fully enabled, ie: is attached and
//isEnabled() is true or when the setEnabled() status changes after the
//state is attached.
}
@Override
protected void onDisable() {
//Called when the state was previously enabled but is now disabled
//either because setEnabled(false) was called or the state is being
//cleaned up.
}
@Override
public void update(float tpf) {
}
@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
}
@Override
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
}

@ -0,0 +1,235 @@
package mygame.control;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.bullet.control.BetterCharacterControl;
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.input.ChaseCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
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;
import java.util.ArrayList;
import java.util.List;
import mygame.Main;
import static mygame.Main.main;
public class PlayableCharacter extends AbstractControl implements Savable, Cloneable, ActionListener, AnalogListener, AnimEventListener {
float speed = 1000.0f;
boolean walkingForward = false;
boolean walkingBackward = false;
boolean strafingLeft = false;
boolean strafingRight = false;
boolean moving = false;
int waitForGround=0;
long lastJump = System.currentTimeMillis();
float height;
AnimChannel channel;
//AnimChannel channel_lowerbody;
AnimControl control;
public PlayableCharacter(float height) {
this.height=height;
} // empty serialization constructor
/** 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);
//control = spatial.getControl(BetterCharacterControl.class);
control = ((Node)spatial).getChild(0).getControl(AnimControl.class);
control.addListener(this);
channel = control.createChannel();
channel.setAnim("stand");
/*channel_lowerbody = control.createChannel();
channel_lowerbody.addBone("hip.right");
channel_lowerbody.addBone("hip.left");*/ //There is no strafing animation
main.getInputManager().addMapping("WalkForward", new KeyTrigger(KeyInput.KEY_W));
main.getInputManager().addMapping("WalkBackward", new KeyTrigger(KeyInput.KEY_S));
main.getInputManager().addMapping("StrafeLeft", new KeyTrigger(KeyInput.KEY_A));
main.getInputManager().addMapping("StrafeRight", new KeyTrigger(KeyInput.KEY_D));
main.getInputManager().addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
main.getInputManager().addListener(this, "WalkForward");
main.getInputManager().addListener(this, "WalkBackward");
main.getInputManager().addListener(this, "StrafeRight");
main.getInputManager().addListener(this, "StrafeLeft");
main.getInputManager().addListener(this, "Jump");
}
/** 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 (waitForGround<4) {
if (moving) {
if (!channel.getAnimationName().equalsIgnoreCase("Walk")) {
channel.setAnim("Walk");
channel.setLoopMode(LoopMode.Loop);
}
Vector3f camDir = main.getCamera().getDirection(); camDir.y=0; camDir.normalizeLocal();
Vector3f camLeftDir = main.getCamera().getLeft(); camLeftDir.y=0; camLeftDir.normalizeLocal();
Vector3f walkDirection = new Vector3f(0,0,0);
//spatial.setLocalRotation(new Quaternion().fromAngleAxis(spatial.getControl(ChaseCamera.class).getHorizontalRotation(),Vector3f.UNIT_Y));
//System.out.println(camDir);
moving=false;
if (strafingLeft) {
walkDirection.addLocal(camLeftDir);
moving=true;
}
if (strafingRight) {
walkDirection.addLocal(camLeftDir.negate());
moving=true;
}
if (walkingForward) {
walkDirection.addLocal(camDir);
moving=true;
}
if (walkingBackward) {
walkDirection.addLocal(camDir.negate());
moving=true;
}
if (moving) {
walkDirection.multLocal(speed).multLocal(tpf);
spatial.getControl(BetterCharacterControl.class).setViewDirection(walkDirection);
spatial.getControl(BetterCharacterControl.class).setWalkDirection(walkDirection);
Vector3f vel = spatial.getControl(BetterCharacterControl.class).getVelocity();
if (Math.abs(vel.x)<0.1f && Math.abs(vel.y)<0.1f && Math.abs(vel.z)<0.1f) {
System.out.println("Not moving!!");
waitForGround++;
} else {
waitForGround=0;
}
} else {
channel.setAnim("stand");
channel.setLoopMode(LoopMode.DontLoop);
spatial.getControl(BetterCharacterControl.class).setWalkDirection(walkDirection);
}
}
} else {
if (spatial.getControl(BetterCharacterControl.class).isOnGround()) {
waitForGround=0;
} else {
spatial.getControl(BetterCharacterControl.class).setWalkDirection(Vector3f.ZERO);
}
}
}
@Override
public Control cloneForSpatial(Spatial spatial){
final PlayableCharacter control = new PlayableCharacter(height);
/* 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(...);
}
@Override
public void onAction(String name, boolean isPressed, float tpf) {
switch (name) {
case "StrafeLeft":{
strafingLeft = isPressed;
moving = true;
}break;
case "StrafeRight":{
strafingRight = isPressed;
moving = true;
}break;
case "WalkBackward":{
walkingBackward = isPressed;
moving = true;
}break;
case "WalkForward":{
walkingForward = isPressed;
moving = true;
}break;
}
}
@Override
public void onAnalog(String name, float value, float tpf) {
switch (name) {
case "Jump":{
if (System.currentTimeMillis()-lastJump>=1000 && spatial.getControl(BetterCharacterControl.class).isOnGround()) {
spatial.getControl(BetterCharacterControl.class).jump();
lastJump = System.currentTimeMillis();
}
}break;
}
}
@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
}
@Override
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
private boolean isCollision() {
CollisionResults results = new CollisionResults();
System.out.println(spatial.getControl(BetterCharacterControl.class).getVelocity());
Ray ray = new Ray(spatial.getLocalTranslation(), spatial.getControl(BetterCharacterControl.class).getVelocity());
main.getRootNode().collideWith(ray, results);
List<Geometry> collisions = new ArrayList<Geometry>();
for (int i=0;i<results.size();i++) {
if (results.getCollision(i).getGeometry().getName().contains("Oto")) {
collisions.add(results.getCollision(i).getGeometry());
//System.out.println(results.getCollision(i).getGeometry().getName()+": Collision");
//System.out.println("Collision detected!");
return true;
}
//System.out.println(results.getCollision(i).getGeometry().getName());
}
//System.out.println(collisions);
return false;
}
}

@ -0,0 +1,67 @@
package template;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AppStateManager;
import com.jme3.app.state.BaseAppState;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.input.InputManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
public class MyBaseAppState extends BaseAppState {
private SimpleApplication app;
private Node rootNode;
private AssetManager assetManager;
private AppStateManager stateManager;
private InputManager inputManager;
private ViewPort viewPort;
private BulletAppState physics;
@Override
protected void initialize(Application app) {
//It is technically safe to do all initialization and cleanup in the
//onEnable()/onDisable() methods. Choosing to use initialize() and
//cleanup() for this is a matter of performance specifics for the
//implementor.
//TODO: initialize your AppState, e.g. attach spatials to rootNode
super.initialize(stateManager, app);
this.app = (SimpleApplication) app; // can cast Application to something more specific
this.rootNode = this.app.getRootNode();
this.assetManager = this.app.getAssetManager();
this.stateManager = this.app.getStateManager();
this.inputManager = this.app.getInputManager();
this.viewPort = this.app.getViewPort();
this.physics = this.stateManager.getState(BulletAppState.class);
}
@Override
protected void cleanup(Application app) {
//TODO: clean up what you initialized in the initialize method,
//e.g. remove all spatials from rootNode
}
//onEnable()/onDisable() can be used for managing things that should
//only exist while the state is enabled. Prime examples would be scene
//graph attachment or input listener attachment.
@Override
protected void onEnable() {
//Called when the state is fully enabled, ie: is attached and
//isEnabled() is true or when the setEnabled() status changes after the
//state is attached.
}
@Override
protected void onDisable() {
//Called when the state was previously enabled but is now disabled
//either because setEnabled(false) was called or the state is being
//cleaned up.
}
@Override
public void update(float tpf) {
//TODO: implement behavior during runtime
}
}

@ -0,0 +1,78 @@
package template;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.Savable;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import java.io.IOException;
public class MyControl extends AbstractControl implements Savable, Cloneable {
private int index; // can have custom fields -- example
public MyControl(){} // empty serialization constructor
/** Optional custom constructor with arguments that can init custom fields.
* Note: you cannot modify the spatial here yet!
*/
public MyControl(int i){
// index=i; // example
}
/** 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);
/* Example:
if (spatial != null){
// initialize
}else{
// cleanup
}
*/
}
/** 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(spatial != null) {
// spatial.rotate(tpf,tpf,tpf); // example behaviour
}
}
@Override
public Control cloneForSpatial(Spatial spatial){
final MyControl control = new MyControl();
/* 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(...);
}
}
Loading…
Cancel
Save