First Person Shooting Aim

I just completed the jme 3 Tutorials and noticed that the tutorial “HelloCollision” says that it can be used as the base for first person shooting games. So i’ve used the “HelloPhysics” tutorial with the “HelloCollision” tutorial as a base and have gotten the player able to shoot cannonballs. The only problem is that cannonballs do not go in the direction of the players reticule. Also the player shifts in a random direction backward after shooting each shot. I figure that it has something to do with the camera and physics because when I take out:



[java]cam.setLocation(player.getPhysicsLocation());[/java]



out of:



[java]package hello;



import com.jme3.app.SimpleApplication;

import com.jme3.asset.TextureKey;

import com.jme3.asset.plugins.ZipLocator;

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.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.MouseInput;

import com.jme3.input.controls.ActionListener;

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.Vector2f;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;

import com.jme3.scene.shape.Sphere.TextureMode;

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 HelloCollision extends SimpleApplication

    implements ActionListener {



    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, shoot = false;

    private RigidBodyControl brick_phy;

    private static final Box box;

    private RigidBodyControl ball_phy;

    private static final Sphere sphere;

    private RigidBodyControl floor_phy;

    private static final Box floor;

    private static final float brickLength = 0.48f;

    private static final float brickWidth = 0.24f;

    private static final float brickHeight = 0.12f;

    Material wall_mat;

    Material stone_mat;

    Material floor_mat;

    Material sphere_mat;



    static {

    /
    * Initialize the cannon ball geometry /

    sphere = new Sphere(32, 32, 0.4f, true, false);

    sphere.setTextureMode(TextureMode.Projected);

    /
    * Initialize the brick geometry /

    box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);

    box.scaleTextureCoordinates(new Vector2f(1f, .5f));

    /
    * Initialize the floor geometry /

    floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);

    floor.scaleTextureCoordinates(new Vector2f(3, 6));

    }



    public static void main(String[] args) {

    HelloCollision app = new HelloCollision();

    app.start();

    }



    public void simpleInitApp() {

    /
    * Set up Physics /

    bulletAppState = new BulletAppState();

    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(100);

    setUpKeys();

    setUpLight();

    initCrossHairs();

    initMaterials();





    // We load the scene from the zip file and adjust its size.

    assetManager.registerLocator("E:\jme3 Assets\town.zip", ZipLocator.class.getName());

    sceneModel = assetManager.loadModel("main.scene");

    sceneModel.setLocalScale(2f);



    // 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) sceneModel);

    landscape = new RigidBodyControl(sceneShape, 0);

    sceneModel.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, 10, 0));



    Box box = new Box(Vector3f.ZERO, 2.5f,2.5f,1.0f);

    Spatial wall = new Geometry("Box", box );

    Material mat_brick = new Material(

    assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat_brick.setTexture("ColorMap",

    assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));

    //assetManager.loadTexture("blackhole.jpg"));

    wall.setMaterial(mat_brick);

    wall.setLocalTranslation(0f,0f,0.0f);

    rootNode.attachChild(wall);



    // We attach the scene and the player to the rootNode and the physics space,

    // to make them appear in the game world.

    rootNode.attachChild(sceneModel);

    bulletAppState.getPhysicsSpace().add(landscape);

    bulletAppState.getPhysicsSpace().add(player);

    }



    public void initMaterials() {

    wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");

    key.setGenerateMips(true);

    Texture tex = assetManager.loadTexture(key);

    wall_mat.setTexture("ColorMap", tex);



    stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");

    key2.setGenerateMips(true);

    Texture tex2 = assetManager.loadTexture(key2);

    stone_mat.setTexture("ColorMap", tex2);



    floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");

    key3.setGenerateMips(true);

    Texture tex3 = assetManager.loadTexture(key3);

    tex3.setWrap(WrapMode.Repeat);

    floor_mat.setTexture("ColorMap", tex3);



    }



    private ActionListener actionListener = new ActionListener() {

    public void onAction(String name, boolean keyPressed, float tpf) {

    if (name.equals("shoot") && !keyPressed) {

    makeCannonBall();

    }

    }

    };





    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("Up", new KeyTrigger(KeyInput.KEY_W));

    inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));

    inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addMapping("shoot",

    new MouseButtonTrigger(MouseInput.BUTTON_LEFT));

    inputManager.addListener(actionListener, "shoot");

    inputManager.addListener(this, "Left");

    inputManager.addListener(this, "Right");

    inputManager.addListener(this, "Up");

    inputManager.addListener(this, "Down");

    inputManager.addListener(this, "Jump");

    }



    protected void initCrossHairs() {

    guiNode.detachAllChildren();

    guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");

    BitmapText ch = new BitmapText(guiFont, false);

    ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);

    ch.setText("+"); // fake crosshairs :slight_smile:

    ch.setLocalTranslation( // center

    settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,

    settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);

    guiNode.attachChild(ch);

    }



    public void makeCannonBall() {

    /
    * Create a cannon ball geometry and attach to scene graph. /

    Geometry ball_geo = new Geometry("cannon ball", sphere);

    ball_geo.setMaterial(stone_mat);

    rootNode.attachChild(ball_geo);

    /
    * Position the cannon ball /

    ball_geo.setLocalTranslation(cam.getLocation());

    /
    * Make the ball physcial with a mass > 0.0f /

    ball_phy = new RigidBodyControl(1f);

    /
    * Add physical ball to physics space. /

    ball_geo.addControl(ball_phy);

    bulletAppState.getPhysicsSpace().add(ball_phy);

    /
    * Accelerate the physcial ball to shoot it. /

    //cam.setLocation(walkDirection);

    //ball_phy.setLinearVelocity(cam.getDirection().mult(25));

    ball_phy.setLinearVelocity(cam.getDirection());

    }

    /
    * 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("shoot")) {

    makeCannonBall();

    }

    }



    /**
  • 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) {

    Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);

    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);

    listener.setLocation(cam.getLocation());

    listener.setRotation(cam.getRotation());

    cam.setLocation(player.getPhysicsLocation());





    }



    }

    [/java]



    the player is able to shoot accurately without shifting, but the player is able to noclip through everything and physics does not have any effect on the player.



    How am I able to make the cannonball shoot accurately without making the player noclip through everything?



    Thank you for your time! :smiley:

I guess you shoot your own character because your bullet starts inside of it.