NPC's shooting. Where to start from?

Hi, I would like to ask about shooting of NPC. What should I use to get NPC’s shooting (ActionListener, Rays, Controls… Something else…)? I want to show flying bullets (like in old scroll-shooter projects), so bullets are flying Geometries.



This is a concept:

http://imageshack.us/photo/my-images/560/bulleto.jpg/







Uploaded with ImageShack.us





Also, I did a test project (only 2 classes) to have a try it.



ShootBullet.java

[java]

import com.jme3.asset.AssetManager;

import com.jme3.material.Material;

import com.jme3.math.*;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;



/**

*

  • @author mifth

    /

    public class ShootBullet {





    Node shotGroup = new Node("shotGroup");

    Box box_a = new Box(Vector3f.ZERO, 1, 1, 1);

    Spatial charShoot;

    Material mat_box;

    Geometry bullet;



    // ShootTest ast = new ShootTest();





    public void shootObj (AssetManager AssetManager) {



    // Create a box Geometry



    charShoot = new Geometry("Box", box_a);

    charShoot.scale(1,1,2);



    mat_box = new Material(AssetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat_box.setColor("Color", ColorRGBA.Blue);

    charShoot.setMaterial(mat_box);



    shotGroup.attachChild(charShoot);







    }

    void shootBullets (AssetManager AssetManager) {



    bullet = new Geometry ("Bullet", box_a);

    Material mat_bullet = new Material(AssetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat_bullet.setColor("m_Color", ColorRGBA.Red);

    bullet.setMaterial(mat_bullet);





    Transform bulletTrans = charShoot.getWorldTransform().setScale(0.5f,0.5f,0.5f);

    bullet.setLocalTransform(bulletTrans);

    bullet.move(0,0,5f);



    shotGroup.attachChild(bullet);



    }

    void moveBullet (float tpf){

    bullet.move(0,0,7f
    tpf);



    }



    void rotateObj (float tpf){

    charShoot.rotate(0,2ftpf,0);



    }



    }[/java]



    ShootBulletRun.java

    [java]

    import com.jme3.app.SimpleApplication;

    import com.jme3.font.BitmapText;

    import com.jme3.math.
    ;

    import com.jme3.system.AppSettings;





    public class ShootBulletRun extends SimpleApplication {







    public static void main(String[] args) {

    ShootBulletRun app = new ShootBulletRun();



    //set vSinc on to get stable 60 fps

    AppSettings aps = new AppSettings(true);

    aps.setVSync(true);

    app.setSettings(aps);

    app.start();

    }



    ShootBullet shb = new ShootBullet();





    @Override

    public void simpleInitApp() {





    shb.shootObj(assetManager);

    starting();



    shb.shootBullets(assetManager);

    rootNode.attachChild(shb.shotGroup);



    }





    @Override

    public void simpleUpdate(float tpf)

    {

    shb.moveBullet(tpf);

    shb.rotateObj(tpf);









    }



    public void starting () {

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

    BitmapText ch = new BitmapText(guiFont, false);

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

    ch.setText("Shooting Cube!"); // crosshairs

    ch.setColor(new ColorRGBA(1f,0.8f,0.1f,1f));

    ch.setLocalTranslation(settings.getWidth()*0.3f,settings.getHeight()*0.1f,0);

    guiNode.attachChild(ch);



    viewPort.setBackgroundColor(ColorRGBA.Gray);

    flyCam.setMoveSpeed(30);

    cam.setLocation(new Vector3f(0f,3f,30f));

    }





    }[/java]



    So, I will appreciate any help.

There’s a few ways i can think of, and it depends on what your trying to achieve, do you want the NPC’s shoot you when your in close proximity? or if they can “see you”? Close proximity you can use a ghostControl with a spherecollisionshape or something around them. If you want the NPC to shoot if it “sees you” that would be a ray and a control, if closestcollision = your character, shoot him. I assume you can also put depth as well, so if the ray hits them and they are X units away start firing. I’ve never actually used rays if im honest, but i get the idea what they’re used for, and this seems suitable.

Thanks for your answering. I will explain more clear:



1 At present, I want just to make shooting. The object shoots constantly.

2 Bullets are geometries which move with tpf.

3 Bullets should die in 30 units. (if a distance between the object and a bullet is > 30 units/meters)



I cant understand how should I realize bullets for NPC? How should I make it? With Custom Controls? But how?

I think create 2 custom Controls, 1 which create the bullets (NPCControl), and then attach another control (BulletControl) to that bullet, which will be responsible for moving it, removing it etc. It might be easier to not “die in 30 units” but relate that to a time interval, and say die in 2.8seconds.

actually if flyspeed is known: units = speed*time, so both is possible without any problems.

Guys!!! Thank you a lot! I will try to do as you described. The only thing is where should I apply Controls? Inside of simpleUpdate() or simpleInitApp()?



About units I think something like that:

[java]Vector3f vecNpc = npc.getWorldTranslation();

Vector3f vecBullet = bullet.getWorldTranslation();

float distance = vecNpc.distance(vecBullet);

if (distance > 3.0f) bullet.removeFromParent;

[/java]



The only thing I cant understand is how to get the bullet as there will be many clones of the bullet.

yeh that looks good, but don’t forget to remove the bullet from the physics space if it has a collisionshape. You apply the controls where-ever the object is created. The BulletControl has a reference (called “spatial”) to the Bullet to which it is attached to, if thats what you mean. So that will keep track of how far it is, etc, unless i’m not understanding correctly.

Thanks man!

If I use Physics, so I should use BulletControl.



But what if do not use physics?

BulletControl was just an example name of a custom control that you need to implement regardless of using physics or not.

Hi again! I did shooting in some way… But I have questions about objects removing and clear cache, as there are many objects will be created.



I have 3 classes:

ShootBullet.java - bullet object (mesh, material)

ShootBulletControl.java - bullet control (moving, attaching to a scene, detaching from the scene)

ShootBulletRun.java - main



I have a blue cube which shoots with small red cubes.



Questions:

1 - I can detach a bullet from a scene and remove a control from it, but the bullet object still exists in cache and code. How can I remove the object from the scene at all?

In the ShootBulletControl.java I use such operations, possibly I shoud add something to the update loop? :

[java]

this.geoo.removeControl(this);

shoBuRu.getRootNode().detachChild(this.geoo);

[/java]



----



2 - In the ShootBulletRun.java I create a control every time to create a bullet. Should I use cloneForSpatial control feature to get more productivity?



At present it looks like:

[java]Geometry gm = shb.bullet.clone(false);

gm.addControl(new ShootBulletControl(gm, charShoot, this));[/java]





Ok, and then here is my working code:

ShootBullet.java:

[java]import com.jme3.asset.AssetManager;

import com.jme3.material.Material;

import com.jme3.math.;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;



public class ShootBullet {



Node shotGroup = new Node("shotGroup");

Box box_bullet = new Box(Vector3f.ZERO, 1, 1, 1);

Material mat_box;

Geometry bullet;

ShootBulletRun sbrun;



ShootBullet (ShootBulletRun runn) {



sbrun = runn;

bullet = new Geometry ("Bullet", box_bullet);

Material mat_bullet = new Material(sbrun.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");

mat_bullet.setColor("m_Color", ColorRGBA.Red);

bullet.setMaterial(mat_bullet);

// sbrun.getRootNode().attachChild(bullet);

}





}

[/java]



ShootBulletControl.java:

[java]import com.jme3.export.Savable;

import com.jme3.math.Quaternion;

import com.jme3.math.Transform;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Geometry;

import com.jme3.scene.Spatial;

import com.jme3.scene.control.AbstractControl;

import com.jme3.scene.control.Control;

import java.util.HashMap;



public class ShootBulletControl extends AbstractControl implements Savable, Cloneable

{

Geometry geoo;

Spatial spaa;

Transform bulletTrans;

ShootBulletRun shoBuRu;

Quaternion quaObj;

Vector3f frontVec;

float timer2;



public ShootBulletControl(Geometry zgeoo, Spatial zspaa, ShootBulletRun zshb)

{

this.shoBuRu = zshb;

this.spaa = zspaa;

this.geoo = zgeoo;

bulletTrans = spaa.getWorldTransform().setScale(0.5f,0.5f,0.5f);

geoo.setLocalTransform(bulletTrans);

// geoo.move(0,0,5f);



quaObj = spaa.getWorldRotation();

frontVec = quaObj.mult(Vector3f.UNIT_Z).normalize();



shoBuRu.getRootNode().attachChild(geoo);





}



public Control cloneForSpatial(Spatial arg0)

{

return null;

}



protected void controlRender(RenderManager arg0, ViewPort arg1) {}





@Override

protected void controlUpdate(float arg0) {



timer2 += arg0
4f;

this.geoo.move(frontVec.mult(1.2f));



if (timer2 > 3f) {

this.geoo.removeControl(this);

shoBuRu.getRootNode().detachChild(this.geoo);



}

// this.geoo.move(0,0,7farg0);

// geoo.rotate(0, 7f
arg0, 0);



}





}[/java]





ShootBulletRun.java:

[java]



import com.jme3.app.SimpleApplication;

import com.jme3.font.BitmapText;

import com.jme3.material.Material;

import com.jme3.math.;

import com.jme3.scene.Geometry;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

import com.jme3.system.AppSettings;





public class ShootBulletRun extends SimpleApplication {







public static void main(String[] args) {

ShootBulletRun app = new ShootBulletRun();



//set vSinc on to get stable 60 fps

AppSettings aps = new AppSettings(true);

aps.setVSync(true);

app.setSettings(aps);

app.start();

}



ShootBullet shb;

//ShootBulletControl sbc;

Spatial charShoot;

Material mat_box;

Box box_char = new Box(Vector3f.ZERO, 1, 1, 1);

float timer;





public void shootObj() {



// Create a blue box Geometry



charShoot = new Geometry("Box", box_char);

charShoot.scale(1,1,2);



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

mat_box.setColor("Color", ColorRGBA.Blue);

charShoot.setMaterial(mat_box);



rootNode.attachChild(charShoot);



}



@Override

public void simpleInitApp() {



shootObj();

starting();

shb = new ShootBullet(this);











}





@Override

public void simpleUpdate(float tpf)

{



timer += tpf
4f;

if (timer>0.2f){

Geometry gm = shb.bullet.clone(false);

gm.addControl(new ShootBulletControl(gm, charShoot, this));

// gm.getControl(0).setEnabled(true);

timer = 0;

}



charShoot.rotate(0,2f*tpf,0);







System.out.println(timer);



}



public void starting () {

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

BitmapText ch = new BitmapText(guiFont, false);

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

ch.setText("Shooting Cube!"); // crosshairs

ch.setColor(new ColorRGBA(1f,0.8f,0.1f,1f));

ch.setLocalTranslation(settings.getWidth()*0.3f,settings.getHeight()*0.1f,0);

guiNode.attachChild(ch);



viewPort.setBackgroundColor(ColorRGBA.Gray);

flyCam.setMoveSpeed(30);

cam.setLocation(new Vector3f(0f,3f,30f));



}





}



[/java]

it seems there are problems with code pasting…

& q u o t ; ---- is added in my code… :frowning:



http://pastebin.com/gJ7a43EL - ShootBulletRun.java

http://pastebin.com/H29FtrS0 - - ShootBulletControl.java

http://pastebin.com/uPD1HUGc - - ShootBullet.java

java uses reference counting in garbage collection to remove objects from memory. There’s no guarantee when it will be called, but its guaranteed to be called, normally this is done by removing all references to an object by assigning them to null when your done with them.



[java]spatial = null;[/java]

Thanks man a lot!!! I will try it. But what about controls?

should I use cloneForSpatial or create new and then make null?

no idea, i just create a new one every time.