How do I add a Model to my Character Control or Capsule Collision shape?
Attach the control to a model.
thx, I will try it asap ^^
WhenI try to do this the game crashes with an null-pointer-exception
Then apparently you did it wrong.
Sorry for the bad answer xD I createt a Spatial model and added it to the root node. Then I added my already existing player (Which is the capsuleShape and the CharacterControl) as a Control to the model. Here is the full code:
package mygame;
/*
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.FogFilter;
import com.jme3.post.filters.LightScatteringFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.LightControl;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture;
import com.jme3.util.SkyFactory;
public class Main extends SimpleApplication
implements ActionListener{
private Spatial levelOne;
private BulletAppState bulletAppState;
private Spatial model;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
public static void main(String[] args) {
Main app = new Main();
//some presets
AppSettings settings = new AppSettings(true);
settings.setResolution(1280,720);
settings.setFrameRate(60);
//settings.setFullscreen(true);
app.setSettings(settings);
//app.setShowSettings(false);
app.setPauseOnLostFocus(true);
app.start();
}
public void simpleInitApp() {
//don't show stats
setDisplayFps(false);
setDisplayStatView(false);
/** A white, directional light source */
DirectionalLight sun = new DirectionalLight();
sun.setDirection((new Vector3f(-10f, -10f, -10f)).normalizeLocal());
sun.setColor(ColorRGBA.White);
rootNode.addLight(sun);
/** Add fog to a scene */
/** Add fog to a scene */
FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
FogFilter fog=new FogFilter();
fog.setFogColor(new ColorRGBA(0.9f, 0.9f, 0.9f, 1.0f));
fog.setFogDistance(155);
fog.setFogDensity(3.0f);
fpp.addFilter(fog);
viewPort.addProcessor(fpp);
/* this shadow needs a directional light */
DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, 1024, 2);
dlsr.setLight(sun);
viewPort.addProcessor(dlsr);
/** Load a model. Uses model and texture from jme3-test-data library! */
Spatial model = assetManager.loadModel("Models/undead.obj");
Material defaultMat = new Material( assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
model.setMaterial(defaultMat);
/** Write text on the screen (HUD) */
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText helloText = new BitmapText(guiFont, false);
helloText.setSize(guiFont.getCharSet().getRenderedSize());
helloText.setText("DECISION PRE-ALPHA 0.1");
helloText.setLocalTranslation(0, helloText.getLineHeight(), 0);
guiNode.attachChild(helloText);
bulletAppState = new BulletAppState();
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);//for bullets
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);
// We re-use the flyby camera for rotation, while positioning is handled by physics
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
flyCam.setMoveSpeed((float) 0.0001);
setUpKeys();
setUpLight();
//Preload Levels
levelOne = assetManager.loadModel("Scenes/Scene1/scene1.j3o");
levelOne.setLocalScale(5f);
//Set up physics and add level/player to scenegraph
setLevel(levelOne);
}
private void setLevel(Spatial level) {
// We set up collision detection for the scene by creating a
// compound collision shape and a static RigidBodyControl with mass zero.
CollisionShape sceneShape =
CollisionShapeFactory.createMeshShape((Node) level);
landscape = new RigidBodyControl(sceneShape, 0);
level.addControl(landscape);
// We set up collision detection for the player by creating
// a capsule collision shape and a CharacterControl.
// The CharacterControl offers extra settings for
// size, stepheight, jumping, falling, and gravity.
// We also put the player in its starting position.
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(0, 14, 120));
model.addControl(player);
// We attach the scene and the player to the rootnode and the physics space,
// to make them appear in the game world.
PointLight myLight = new PointLight();
rootNode.addLight(myLight);
LightControl lightControl = new LightControl(myLight);
model.addControl(lightControl);
rootNode.attachChild(level);
rootNode.attachChild(model);
bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);
AudioNode horror = new AudioNode(assetManager, "Sounds/horror.wav");
horror.setLooping(true);
horror.setPositional(false);
horror.setDirectional(false);
horror.play();
horror.setVolume((float) 0.5);
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
private void setUpLight() {
}
/** We over-write some navigational key mappings here, so we can
* add physics-controlled walking and jumping: */
private void setUpKeys() {
inputManager.deleteMapping(INPUT_MAPPING_EXIT);
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("Quit", new KeyTrigger(KeyInput.KEY_ESCAPE));
inputManager.addListener(this, "Left");
inputManager.addListener(this, "Right");
inputManager.addListener(this, "Up");
inputManager.addListener(this, "Down");
inputManager.addListener(this, "Jump");
inputManager.addListener(this, "Quit"); // listen for ESC key to close game
}
/** These are our custom actions triggered by key presses.
* We do not walk yet, we just keep track of the direction the user pressed. */
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("Left")) {
if (value) { left = true; } else { left = false; }
} else if (binding.equals("Right")) {
if (value) { right = true; } else { right = false; }
} else if (binding.equals("Up")) {
if (value) { up = true; } else { up = false; }
} else if (binding.equals("Down")) {
if (value) { down = true; } else { down = false; }
} else if (binding.equals("Jump")) {
player.jump();
} else if (binding.equals("Quit")) {
stop(); // simple way to close game
}
}
/**
* This is the main event loop--walking happens here.
* We check in which direction the player is walking by interpreting
* the camera direction forward (camDir) and to the side (camLeft).
* The setWalkDirection() command is what lets a physics-controlled player walk.
* We also make sure here that the camera moves with player.
*/
@Override
public void simpleUpdate(float tpf) {
float movingspeed = 0.2f; // speed for the player
float strafingspeed = 0.1f; //speed for strafing (right/left)
Vector3f camDir = cam.getDirection().clone().multLocal(movingspeed);
Vector3f camLeft = cam.getLeft().clone().multLocal(strafingspeed);
Vector3f camUp = new Vector3f(0f,0f,0f);
camUp.set(cam.getUp()).multLocal(movingspeed*(1-(cam.getUp().getY())));
walkDirection.set(0, 0, 0);
if (left) { walkDirection.addLocal(camLeft.setY(0)); }
if (right) { walkDirection.addLocal(camLeft.negate().setY(0)); }
if (up) {
walkDirection.addLocal(camDir.setY(0));
if(cam.getDirection().getY() < 0)walkDirection.addLocal(camUp.setY(0));
else walkDirection.addLocal(camUp.setY(0).negate());
}
if (down) {
walkDirection.addLocal(camDir.negate().setY(0));
if(cam.getDirection().getY() < 0)walkDirection.addLocal(camUp.setY(0).negate());
else walkDirection.addLocal(camUp.setY(0));
}
if(cam.getUp().y < 0){
cam.lookAtDirection( new Vector3f(0,cam.getDirection().y,0),new Vector3f(cam.getUp().x,0, cam.getUp().z));
}
player.setWalkDirection(walkDirection);
cam.setLocation(player.getPhysicsLocation());
}
}
And the stack trace please.
Could be that I missunderstood, im not sure what the stack trace was, im guessing this:
Schwerwiegend: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at mygame.Main.setLevel(Main.java:174)
at mygame.Main.simpleInitApp(Main.java:152)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:226)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207)
at java.lang.Thread.run(Thread.java:744)
Java Result: 1
BUILD SUCCESSFUL (total time: 1 minute 59 seconds)
Yes. So which line is 174?
model.addControl(player);
But wasnt this what I was supposed to do?
That means model is null.
Its null because in the setLevel method “model” is the field in the class (the first “Spatial model;” in your code). But in the simpleInit you do “Spatial model = assetManager.loadModel”, which creates a local variable in the simpleInit method - leaving the field “model” unassigned (the SDK probably also warns you about that with a squiggly line). Just remove the “Spatial” in “Spatial model = assetManager.loadModel” and it will assign it to the field instead, making it available for the other method.
And now you learned how to use stack traces to debug your code
Oh man I love this community <3
Got another problem now. I assigned “model” and “player” to the bulletAppState for Physics, but im falling throught the ground I think you got the code ^^ No error in the stack trace
Aaaaaand the model is way to big and not really attatched to the player Control
When you do model.addControl(player) it sets the models location on the player control.
I think I won´t ever get it how to be able to see my feet in a game I dont have a good model neither, no idea from where to get it. Well, i´ll just capitulate here, sry for taking your time
Im still too bad to get this working, dont try to help me xD
If you have a way to explain it too me you could try it, but I think im to bad for it
Thats what happens in your code already, your setPhysicsLocation gets overridden by that, might be why your model falls through the floor.
Ah the thing falling throught the ground is fixed, I just spawned under the terrain, but I still dont understand how to use models, I dont have valid models I think