I am working on this piece of code where i want to make to make FPS like game And i want the gun to be always visible in front of me even when i rotate the camera !
I have a playerNode which is the player ! So i attached the gun to the PlayerNode ,
So that gun would move along with the playerNode !
But it’s not working (The gun is not moving with the playerNode and is not visible)
What am i doing wrong ?
(I just want the gun to be in front of the camera all the time like a FPS game even
when i rotate the flycam )
here’s my code …
Please check it and correct me where i am doing wrong !
[java]
package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode;
import com.jme3.bullet.BulletAppState;
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.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.FogFilter;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import com.jme3.terrain.geomipmap.TerrainLodControl;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
/**
-
Example 9 - How to make walls and floors solid.
-
This collision code uses Physics and a custom Action Listener.
-
@author normen, with edits by Zathras
*/
public class FirstPerson1 extends SimpleApplication
implements ActionListener {private BitmapText ch;
private TerrainQuad terrain;
Geometry mark;
Material mat_terrain;
private AudioNode audio_gun,audio_nature;
private Node playerNode;
private Spatial sceneModel;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
private boolean isTargeting=false;
Spatial gun;
public static void main(String[] args) {
FirstPerson1 app = new FirstPerson1();
app.start();
}
public void simpleInitApp() {
/** Set up Physics */
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
flyCam.setMoveSpeed(100f);
flyCam.setRotationSpeed(10f);
flyCam.setEnabled(true);
loadAudio();
initMark();
loadTerrain();
loadEffects();
setUpKeys();
setUpLight();
// 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((Spatial)terrain);
landscape = new RigidBodyControl(sceneShape, 0);
terrain.addControl(landscape);
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, 50, 0));
playerNode=new Node("Player Node");
playerNode.setLocalTranslation(player.getPhysicsLocation());
playerNode.addControl(player);
gun = assetManager.loadModel("Models/pistol.j3o");
gun.setName("gun");
gun.scale(0.5f);
gun.move(0, 0, -5); // move it to front to make it visible
playerNode.attachChild(gun);
rootNode.attachChild(terrain);
rootNode.attachChild(playerNode);
// rootNode.attachChild(gun);
bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);
}
private void loadAudio()
{
/* gun shot sound is to be triggered by a mouse click. */
audio_gun = new AudioNode(assetManager, “Sound/Effects/Gun.wav”, false);
audio_gun.setLooping(false);
audio_gun.setVolume(2);
rootNode.attachChild(audio_gun);
/* nature sound - keeps playing in a loop. */
audio_nature = new AudioNode(assetManager, "Sound/Environment/Nature.ogg", false);
audio_nature.setLooping(true); // activate continuous playing
audio_nature.setPositional(false);
audio_nature.setLocalTranslation(Vector3f.ZERO.clone());
audio_nature.setVolume(3);
rootNode.attachChild(audio_nature);
audio_nature.play(); // play continuously!
}
private void loadTerrain()
{
/** 1. Create terrain material and load four textures into it. */
mat_terrain = new Material(assetManager,
“Common/MatDefs/Terrain/Terrain.j3md”);
/** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
mat_terrain.setTexture("Alpha", assetManager.loadTexture(
"Textures/Terrain/splat/alphamap.png"));
/** 1.2) Add GRASS texture into the red layer (Tex1). */
Texture grass = assetManager.loadTexture(
"Textures/Terrain/splat/grass.jpg");
grass.setWrap(WrapMode.Repeat);
mat_terrain.setTexture("Tex1", grass);
mat_terrain.setFloat("Tex1Scale", 64f);
/** 1.3) Add DIRT texture into the green layer (Tex2) */
Texture dirt = assetManager.loadTexture(
"Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(WrapMode.Repeat);
mat_terrain.setTexture("Tex2", dirt);
mat_terrain.setFloat("Tex2Scale", 32f);
/** 1.4) Add ROAD texture into the blue layer (Tex3) */
Texture rock = assetManager.loadTexture(
"Textures/Terrain/splat/road.jpg");
rock.setWrap(WrapMode.Repeat);
mat_terrain.setTexture("Tex3", rock);
mat_terrain.setFloat("Tex3Scale", 128f);
/** 2. Create the height map */
AbstractHeightMap heightmap = null;
Texture heightMapImage = assetManager.loadTexture(
"Textures/Terrain/splat/mountains512.png");
heightmap = new ImageBasedHeightMap(heightMapImage.getImage());
heightmap.load();
/** 3. We have prepared material and heightmap.
* Now we create the actual terrain:
* 3.1) Create a TerrainQuad and name it "my terrain".
* 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
* 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
* 3.4) As LOD step scale we supply Vector3f(1,1,1).
* 3.5) We supply the prepared heightmap itself.
*/
int patchSize = 65;
terrain = new TerrainQuad("my terrain", patchSize, 513, heightmap.getHeightMap());
/** 4. We give the terrain its material, position & scale it, and attach it. */
terrain.setMaterial(mat_terrain);
terrain.setLocalTranslation(0, -100, 0);
terrain.setLocalScale(2f, 1f, 2f);
rootNode.attachChild(terrain);
/** 5. The LOD (level of detail) depends on were the camera is: */
TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
terrain.addControl(control);
}
private void setUpLight() {
// We add light so we see the scene
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
rootNode.addLight(dl);
}
/** We over-write some navigational key mappings here, so we can
- add physics-controlled walking and jumping: */
private void setUpKeys() {
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Backward", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("Target", new KeyTrigger(KeyInput.KEY_LCONTROL));
inputManager.addMapping("Shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(this, "Left");
inputManager.addListener(this, "Right");
inputManager.addListener(this, "Forward");
inputManager.addListener(this, "Backward");
inputManager.addListener(this, "Jump");
inputManager.addListener(this, "Target");
inputManager.addListener(this, "Shoot");
}
protected void initCrossHairs() {
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // fake crosshairs :)
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}
/** A red ball that marks the last spot that was “hit” by the “shot”. */
protected void initMark() {
Sphere sphere = new Sphere(30, 30, 0.2f);
mark = new Geometry("BOOM!", sphere);
Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mark_mat.setColor("Color", ColorRGBA.Red);
mark.setMaterial(mark_mat);
}
/** 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”)) {
left = value;
} else if (binding.equals(“Right”)) {
right = value;
} else if (binding.equals(“Forward”)) {
up = value;
} else if (binding.equals(“Backward”)) {
down = value;
} else if (binding.equals(“Jump”)) {
player.jump();
}else if (binding.equals(“Target”)) {
isTargeting=value;if(isTargeting)initCrossHairs();
else guiNode.detachAllChildren();
}
if(isTargeting && binding.equals("Shoot") && !value)
{
Shoot();
}
}
private void Shoot()
{
audio_gun.playInstance();
CollisionResults results = new CollisionResults();
// 2. Aim the ray from cam loc to cam direction.
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in results list.
terrain.collideWith(ray, results);
// 4. Print the results
System.out.println("----- Collisions? " + results.size() + "-----");
for (int i = 0; i < results.size(); i++) {
// For each hit, we know distance, impact point, name of geometry.
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String hit = results.getCollision(i).getGeometry().getName();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
}
// 5. Use the results (we mark the hit object)
if (results.size() > 0) {
// The closest collision point is what was truly hit:
CollisionResult closest = results.getClosestCollision();
// Let's interact - we mark the hit with a red dot.
mark.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(mark);
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(mark);
}
}
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.4f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
walkDirection.set(0, 0, 0);
if (left) { walkDirection.addLocal(camLeft); }
if (right) { walkDirection.addLocal(camLeft.negate()); }
if (up) { walkDirection.addLocal(camDir); }
if (down) { walkDirection.addLocal(camDir.negate()); }
player.setWalkDirection(walkDirection);
player.setViewDirection(cam.getDirection());
cam.setLocation(player.getPhysicsLocation());
listener.setLocation(cam.getLocation());
listener.setRotation(cam.getRotation());
Debug();
}
private void Debug()
{
System.out.println("Player Postion: "+playerNode.getLocalTranslation());
System.out.println("Player Rotation: "+playerNode.getLocalRotation());
System.out.println("Gun position: "+playerNode.getChild("gun").getLocalTranslation());
System.out.println("Gun rotation: "+playerNode.getChild("gun").getLocalRotation());
}
private void loadEffects() {
/** 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(1.2f);
fpp.addFilter(fog);
viewPort.addProcessor(fpp);
}
}
[/java]