Help on creating simple game

Hello, first of all I’m not sure if I’m posting this in the right section, if it is in the wrong one, I’m sorry.



I’m new to Java and jME and I am trying to create a game where you fight another character in close combat.



I’ve completed and almost understood the beginner HelloWorld tutorial series. So far I’ve added the ninja character onto the HelloCollision part of the tutorial, now I want to know how to add a weapon to my invisible characters hand, and supposedly “fight” this ninja.



I know I’m not going to clap my hands and let this happen, I’m willing to learn how to do this.



Thank you and sorry for being a noob!

To have a sword that collides with other physics objects but is still controllable you can use a RigidBodyControl with a mass but set to kinematic mode. This way you can just move it like any other Spatial to perform swings etc. Just attach the sword Spatial with the Control to a bone and it will move along with it and collide with the environment.

Edit: some code

[java]

Spatial myModel = assetManager.loadModel("Models/Model.j3o");

Spatial sword = assetManager.loadModel("Models/Sword.j3o");

RigidBodyControl control = new RigidBodyControl(1); //collision shape will be an auto-generated hull shape for models with mass

control.setKinematic(true);

sword.addControl(control);

physicsSpace.add(control);

myModel.getControl(AnimControl.class).getSkeleton().getBone("hand_right").getAttachmentsNode().attachChild(sword);

[/java]

You can also use the KinematicRagDollControl but it might be a bit overkill. Since it can switch between animation and rag doll mode, it can be used to create a collision object out of kinematic rigidbodies that moves along with the model and even its animations. Check the jme3test.bullet.TestRagdollCharacter test in the JmeTest project, it shows how its basically used. You can use the CharacterControl and the rag doll Control at the same time on one model, you will have to fiddle with the collision groups of the rag doll and the character control though, because they will collide with each other by default.

If this is 1st person, then you really have nothing to attach the sword too … If you’re using CameraNode you can attach the sword to it and then translate it so it appears in front of the camera.

Do I make it into its on method or …?



I looked at me3test.bullet.TestRagdollCharacter and that is basically what I want but with a sword.



Thanks for your help, and I’m sorry if I’m being nooby. I’m not that good with Java



Here’s all the code I have, its a modifed HelloCollision:



[java]package jme3test.helloworld;



import com.jme3.app.SimpleApplication;

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.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.light.AmbientLight;

import com.jme3.light.DirectionalLight;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;



/**

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



    public static void main(String[] args) {

    HelloCollision app = new HelloCollision();

    app.start();

    }



    public void simpleInitApp() {

    initCrossHairs();

    /
    * 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();



    Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");

    ninja.scale(0.05f, 0.06f, 0.05f);

    ninja.rotate(0.0f, -3.0f, 0.0f);

    ninja.setLocalTranslation(5.0f, -5.0f, -2.0f);

    rootNode.attachChild(ninja);



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

    assetManager.registerLocator("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(15);

    player.setFallSpeed(20);

    player.setGravity(50);

    player.setPhysicsLocation(new Vector3f(0, 10, 0));



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

    }



    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.addListener(this, "Left");

    inputManager.addListener(this, "Right");

    inputManager.addListener(this, "Up");

    inputManager.addListener(this, "Down");

    inputManager.addListener(this, "Jump");

    }



    /
    * 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();

    }

    }



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

    cam.setLocation(player.getPhysicsLocation());

    }

    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("+"); // crosshairs

    ch.setLocalTranslation( // center

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

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

    guiNode.attachChild(ch);

    }

    }[/java]

To have a sword you can simply load the Ninja into the TestRagdollCharacter… It has a sword and animations that move it.

Yes it is 1st person

For some reason when I load Ninja into TestRagdollCharacter it crashes on load up.

-.- …probably with quite obvious errors, check the log. For example the animations of the ogre obviously don’t exist on the ninja.

EDIT: when I run this code, the ninja doesn’t appear?



[java]/*

  • Copyright © 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.

    */

    package jme3test.bullet;



    import com.jme3.animation.AnimChannel;

    import com.jme3.animation.AnimControl;

    import com.jme3.animation.AnimEventListener;

    import com.jme3.animation.LoopMode;

    import com.jme3.bullet.BulletAppState;

    import com.jme3.app.SimpleApplication;

    import com.jme3.asset.TextureKey;

    import com.jme3.bullet.PhysicsSpace;

    import com.jme3.bullet.control.KinematicRagdollControl;

    import com.jme3.bullet.control.RigidBodyControl;

    import com.jme3.input.KeyInput;

    import com.jme3.input.controls.ActionListener;

    import com.jme3.input.controls.KeyTrigger;

    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.renderer.queue.RenderQueue.ShadowMode;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Node;

    import com.jme3.scene.shape.Box;

    import com.jme3.texture.Texture;



    /**
  • @author normenhansen

    */

    public class TestRagdollCharacter extends SimpleApplication implements AnimEventListener, ActionListener {



    BulletAppState bulletAppState;

    Node model;

    KinematicRagdollControl ragdoll;

    boolean leftStrafe = false, rightStrafe = false, forward = false, backward = false,

    leftRotate = false, rightRotate = false;

    AnimControl animControl;

    AnimChannel animChannel;



    public static void main(String[] args) {

    TestRagdollCharacter app = new TestRagdollCharacter();

    app.start();

    }



    public void simpleInitApp() {

    setupKeys();



    bulletAppState = new BulletAppState();

    bulletAppState.setEnabled(true);

    stateManager.attach(bulletAppState);





    // bulletAppState.getPhysicsSpace().enableDebug(assetManager);

    PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());

    initWall(2,1,1);

    setupLight();



    cam.setLocation(new Vector3f(-8,0,-4));

    cam.lookAt(new Vector3f(4,0,-7), Vector3f.UNIT_Y);



    model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");

    model.lookAt(new Vector3f(0,0,-1), Vector3f.UNIT_Y);

    model.setLocalTranslation(4, 0, -7f);



    ragdoll = new KinematicRagdollControl(0.5f);

    model.addControl(ragdoll);



    getPhysicsSpace().add(ragdoll);

    speed = 1.3f;



    rootNode.attachChild(model);





    AnimControl control = model.getControl(AnimControl.class);

    animChannel = control.createChannel();

    animChannel.setAnim("Idle2");

    control.addListener(this);



    }



    private void setupLight() {

    DirectionalLight dl = new DirectionalLight();

    dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());

    dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));

    rootNode.addLight(dl);

    }



    private PhysicsSpace getPhysicsSpace() {

    return bulletAppState.getPhysicsSpace();

    }



    private void setupKeys() {

    inputManager.addMapping("Rotate Left",

    new KeyTrigger(KeyInput.KEY_H));

    inputManager.addMapping("Rotate Right",

    new KeyTrigger(KeyInput.KEY_K));

    inputManager.addMapping("Walk Forward",

    new KeyTrigger(KeyInput.KEY_U));

    inputManager.addMapping("Walk Backward",

    new KeyTrigger(KeyInput.KEY_J));

    inputManager.addMapping("Slice",

    new KeyTrigger(KeyInput.KEY_SPACE),

    new KeyTrigger(KeyInput.KEY_RETURN));

    inputManager.addListener(this, "Strafe Left", "Strafe Right");

    inputManager.addListener(this, "Rotate Left", "Rotate Right");

    inputManager.addListener(this, "Walk Forward", "Walk Backward");

    inputManager.addListener(this, "Slice");

    }



    public void initWall(float bLength, float bWidth, float bHeight) {

    Box brick = new Box(Vector3f.ZERO, bLength, bHeight, bWidth);

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

    Material mat2 = 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);

    mat2.setTexture("ColorMap", tex);



    float startpt = bLength / 4;

    float height = -5;

    for (int j = 0; j < 15; j++) {

    for (int i = 0; i < 4; i++) {

    Vector3f ori = new Vector3f(i * bLength * 2 + startpt, bHeight + height, -10);

    Geometry reBoxg = new Geometry("brick", brick);

    reBoxg.setMaterial(mat2);

    reBoxg.setLocalTranslation(ori);

    //for geometry with sphere mesh the physics system automatically uses a sphere collision shape

    reBoxg.addControl(new RigidBodyControl(1.5f));

    reBoxg.setShadowMode(ShadowMode.CastAndReceive);

    reBoxg.getControl(RigidBodyControl.class).setFriction(0.6f);

    this.rootNode.attachChild(reBoxg);

    this.getPhysicsSpace().add(reBoxg);

    }

    startpt = -startpt;

    height += 2 * bHeight;

    }

    }



    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {



    if (channel.getAnimationName().equals("SliceHorizontal")) {

    channel.setLoopMode(LoopMode.DontLoop);

    channel.setAnim("Attack1", 5);

    channel.setLoopMode(LoopMode.Loop);

    }



    }



    public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {

    }



    public void onAction(String binding, boolean value, float tpf) {

    if (binding.equals("Rotate Left")) {

    if (value) {

    leftRotate = true;

    } else {

    leftRotate = false;

    }

    } else if (binding.equals("Rotate Right")) {

    if (value) {

    rightRotate = true;

    } else {

    rightRotate = false;

    }

    } else if (binding.equals("Walk Forward")) {

    if (value) {

    forward = true;

    } else {

    forward = false;

    }

    } else if (binding.equals("Walk Backward")) {

    if (value) {

    backward = true;

    } else {

    backward = false;

    }

    } else if (binding.equals("Slice")) {

    if (value) {

    animChannel.setAnim("Attack3");

    animChannel.setSpeed(0.3f);

    }

    }

    }



    @Override

    public void simpleUpdate(float tpf) {

    if(forward){

    model.move(model.getLocalRotation().multLocal(new Vector3f(0,0,1)).multLocal(tpf));

    }else if(backward){

    model.move(model.getLocalRotation().multLocal(new Vector3f(0,0,1)).multLocal(-tpf));

    }else if(leftRotate){

    model.rotate(0, tpf, 0);

    }else if(rightRotate){

    model.rotate(0, -tpf, 0);

    }

    fpsText.setText(cam.getLocation() + "/" + cam.getRotation());

    }



    }

    [/java]

I’m quite sure it’s because the ninja model is so big to see and the camera is looking under his legs. Scale it down.

I scaled him down, still can’t see him :confused:

LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOL.

I ran your code and the ninja is too big and it is behind the camera -.- .

Behind the camera?

:brainsout:

1 Like