[SOLVED] How to make turrents shoot at a specific Spatial or direction

Hi there,
i have added a space turrent to shoot my ship whenever i get closer to it , so the problem is i cannot direct the gun relative to my space ship(character control) location

images:

code :

 if(spaceTurrentControls1.getPhysicsLocation().distance(player.getPhysicsLocation()) <= 140){
                   
                            Load_LaserGun(new Sphere(3, 3, 0.60f),"man_smoke_1.png",
              rootNode.getChild("Space Turrent 1").getLocalTranslation().add(new Vector3f(-10f,5f,0f)),new Vector3f(-player.getPhysicsLocation().getX(),player.getPhysicsLocation().getY()-12,player.getPhysicsLocation().getZ())
                                    ,0.03f,0.01f,new Vector3f(-player.getPhysicsLocation().getX(),player.getPhysicsLocation().getY()-66,player.getPhysicsLocation().getZ()));
            }

in simpleUpdate(float tpf);

&

public void Load_LaserGun(Mesh mesh,String Tex,Vector3f startingPosition,Vector3f gravity,float startSizeOfEffect,float endSizeOfEffect,
        Vector3f directionOfShooting ) {
       
            /** Create a Laser Gun geometry and attach to scene graph. new Box(0.01f, 0.03f, 0.01f)*/
            Geometry laser_geo = new Geometry("Laser Gun",mesh);
            Material lasermat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            Texture monkeyTex = assetManager.loadTexture("Textures/"+Tex);
            lasermat.setTexture("ColorMap", monkeyTex);
            laser_geo.setMaterial(lasermat);
            Node LaserGunNode=new Node("Laser Gun");
            LaserGunNode.attachChild(laser_geo);
            LaserGunNode.attachChild(effect(startSizeOfEffect,endSizeOfEffect));
            /** Position Laser gun above the camera location by 1f &  to the right by 0.008f & forward +0.2f */
            //   player.getPhysicsLocation().add(new Vector3f(1f,1f,0f))
            LaserGunNode.setLocalTranslation(startingPosition);
            /** Make the laser gun particles physical with a mass > 0.0f */
            RigidBodyControl ball_phy = new RigidBodyControl(CollisionShapeFactory.createDynamicMeshShape(laser_geo),0.1f);
            /** Add physical ball to physics space. */
            LaserGunNode.addControl(ball_phy);
            //add rock decay conrtol
            LaserGunNode.addControl(new LaserGunDecayControl(GameApplication.player,physics));
            bulletAppState.getPhysicsSpace().add(ball_phy);
            /** setting the gravity of the shoots to zero in all directions x,y,z */
            ball_phy.setGravity(gravity);
            /** Accelerate the physcial ball to shoot it in the direction of camera "see Vector3f multiplications" */
            ball_phy.setLinearVelocity(directionOfShooting);
            /**attach the laser shoots to our node */
            rootNode.attachChild(LaserGunNode);

           
}

Start with the location of the ship and your target, and then subtract and normalize to get the directional vector for your turret to shoot.

Vector3f targetToHitLocation;
Vector3f turretBarrelLocation


Vector3f directionToFire = targetToHitLocation.subtract(turretBarrelLocation);
directionToFire.normalizeLoca(); //now you have a normalized unit-vector. it can can also be multiplied by a speed value as well as TPF's value in the update loop for steady movement across varying framerates)

You may already be doing this (or somethig similar) but it looks like your code gets a bit messy doing all of of your math within the parameters of your call to Load_LaserGun(), so it may help to define and calculate the vectors/floats as independent variables prior to passing them into that method so you can ensure the math is doing what you want it to.

1 Like

I did a trial of something like that but it didnot work, I will try again in case I miss something
Thanks :blush:

1 Like

If the gun is a Spatial, then in order to orient it properly you’ll need more than just a direction vector. The next step might be to convert the direction vector to a 3-D rotation using Quaternion.lookAt(direction, up).

2 Likes

A video where the creator learns at the same time as the viewer. Hard to watch this kinda video but he gets to the meat of it at the end.

Edit:

1 Like

Okay, i have tried as far as i can but nothing works (i donot know positioning direction to the setLinearVelocity(-directionOfSpaceShipControls) directly not working properly, its not accurate),so i have made a mental algorithm to have a range in which these gun particles are directed whether by setLinearVelocity() or by gravity vector , so now the near galactic guns have around 80% chance of hitting the spaceShip

images:

Tips:look at the Health Points

Code:


package mygame;

import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
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.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.shape.Sphere;
import com.jme3.texture.Texture;

/**
 *
 * @author twisted AKA Pavly
 */
public class SpaceTurrentAutoShoot extends AbstractControl {
    
    private CharacterControl player;
    private RigidBodyControl spaceTurrent;
    private Node rootNode;
    private AssetManager assetManager;
    private BulletAppState physics;
    
    float timeStack=0.0f;
    private int num=0;
    private Spatial turrentNode;
    private Camera cam;
    private Vector3f startPosition;
    private Vector3f directionVector;
    private Vector3f gravityVector;
    private float xDir;

    public SpaceTurrentAutoShoot(Camera cam,Node rootNode,AssetManager assetManager,BulletAppState physics,CharacterControl player, RigidBodyControl spaceTurrent,Spatial turrentNode) {
        this.rootNode=rootNode;
        this.assetManager=assetManager;
        this.physics=physics;
        this.player=player;
        this.spaceTurrent=spaceTurrent;
        this.turrentNode=turrentNode;
        this.cam=cam;
    }

    @Override
    protected void controlUpdate(float tpf) {        
            
                if(spaceTurrent.getPhysicsLocation().distance(player.getPhysicsLocation()) <= 100){
                        //setting the warning for your spaceShip
                    GameApplication.dangertext.setText("Danger");
                    GameApplication.xpText.setText("Approaching Galactic Turrent : "+turrentNode.getName());
                    //rotate the galactic Gun to face the ship
                    Quaternion rotate=new Quaternion();
                    rotate=cam.getRotation();
                    rotate.negate();
                    spaceTurrent.setPhysicsRotation(rotate.inverse());
        
                               //check if the player is in front of machine gun or behind it 
                        if(player.getPhysicsLocation().getX()-spaceTurrent.getPhysicsLocation().getX() >= 0){
                            xDir=cam.getLocation().getX();
                        }else{
                            xDir=-cam.getLocation().getX();
                        }
                        
                   
                    //START position vector x=in front of turrent by 5f ,y,z=at the same level of the spaceShip 
                   startPosition=new Vector3f(spaceTurrent.getPhysicsLocation().getX()-5f,player.getPhysicsLocation().getY(),player.getPhysicsLocation().getZ());

                    //direction vector x=opposing the direction of camera to hit the ship ,y,z=at the same level of the spaceShip with a range upto 199 & 19 respectively 
                   directionVector=new Vector3f(xDir,(cam.getLocation().getY())
                    -(++num % 80),cam.getLocation().getZ()-(num % 20) );
                   //gravity vector x=opposing the spaceship motion ,y,z=same direction of camera of spaceship
                   gravityVector=new Vector3f(xDir,(cam.getLocation().getY()),cam.getLocation().getZ());
                    //load galactic turrent laser gun with startVector directionVector & gravity vector
                  Load_LaserGun(new Sphere(3, 3, 1.5f),"man_smoke_1.png",startPosition,gravityVector,0.4f,0.2f,directionVector);
                        timeStack=0.0f;

                 }else{
                    
                 }
        
    }
    
    
     public void Load_LaserGun(Mesh mesh,String Tex,Vector3f startingPosition,Vector3f gravity,float startSizeOfEffect,float endSizeOfEffect,
            Vector3f directionOfShooting ) {
           
                /** Create a Laser Gun geometry and attach to scene graph. new Box(0.01f, 0.03f, 0.01f)*/
                Geometry laser_geo = new Geometry("Space Turrent Laser",mesh);
                Material lasermat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                Texture monkeyTex = assetManager.loadTexture("Textures/"+Tex);
                lasermat.setTexture("ColorMap", monkeyTex);
                laser_geo.setMaterial(lasermat);
                Node LaserGunNode=new Node("Space Turrent Laser");
                LaserGunNode.attachChild(laser_geo);
                LaserGunNode.attachChild(new Effect(assetManager, "turrentGunEffect", "", 300).
                        emitter(new ColorRGBA(3f, 0.4f, 0f, 0.5f), new ColorRGBA(4f, 0.3f, 0.3f, 1f)
                                , startSizeOfEffect, endSizeOfEffect, 0.5f, 1f, Vector3f.ZERO));
                /** Position Laser gun above the camera location by 1f &  to the right by 0.008f & forward +0.2f */
                //   player.getPhysicsLocation().add(new Vector3f(1f,1f,0f))
                LaserGunNode.setLocalTranslation(startingPosition);
                /** Make the laser gun particles physical with a mass > 0.0f */
                RigidBodyControl ball_phy = new RigidBodyControl(CollisionShapeFactory.createDynamicMeshShape(laser_geo),0.1f);
                /** Add physical ball to physics space. */
                LaserGunNode.addControl(ball_phy);
                //add rock decay conrtol
                LaserGunNode.addControl(new LaserGunDecayControl(GameApplication.player,physics));
                physics.getPhysicsSpace().add(ball_phy);
                /** setting the gravity of the shoots to zero in all directions x,y,z */
                ball_phy.setGravity(gravity);
                /** Accelerate the physcial ball to shoot it in the direction of camera "see Vector3f multiplications" */
                ball_phy.setLinearVelocity(directionOfShooting);
                /**attach the laser shoots to our node */
                rootNode.attachChild(LaserGunNode);

               
    }

    
    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {

    }
    
}

&&

                shapeNode.addControl(new SpaceTurrentAutoShoot(cam,rootNode,assetManager,physics,player,spaceTurrentControls1,shapeNode));

I know itsnot that perfect thing , but that’s the level that i have reached actually :grin: :smile:
thank you, if you come up with any info let me know !

Also increasing the particles size would increase the chances upto 95%

1 Like

This Formula is the key that solves this problem ,
Code:

                       /**
                        * Load Laser Guns starting from the NPC & pointing to the player with speed of 100f
                        */
                      Load_LaserGun(new Sphere(10, 10, 0.2f),"man_smoke_1.png",spaceTurrent.getPhysicsLocation()
                            ,Vector3f.ZERO,0.2f,0.15f,player.getPhysicsLocation().subtract(spaceTurrent.getPhysicsLocation()).normalize().mult(100f));

but this must be considered as well but in terms of physics Rotation in my case , not the Spatial Rotation
Code :

     /**
     * Turns the NPC physics viewDirection to face the player
     * @param NPClookPosition Look direction vector  
     * @param upVector the Y-axis prependicular line
     */
    private void rotateNPCTOFacePlayer(Vector3f NPClookPosition,Vector3f upVector) {
          turrentNode.lookAt(NPClookPosition, upVector);
          spaceTurrent.setPhysicsRotation(turrentNode.getLocalRotation());
    }

Anyway, the problem is solved & Thanks for all !

Code :


package main_WorldMap;

import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
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.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.shape.Sphere;
import com.jme3.texture.Texture;

/**
 *
 * @author twisted AKA Pavly
 */
public class SpaceTurrentAutoShoot extends AbstractControl {
    
    private final CharacterControl player;
    private final RigidBodyControl spaceTurrent;
    private final Node rootNode;
    private final AssetManager assetManager;
    private final BulletAppState physics;
    private final Spatial turrentNode;
    
    private float timeStack=0.0f;
    
  
    
    /**
     * An abstract Control that calls the auto-shooting (have a reassignable methods"controlUpdate(tpf)"
     * @param rootNode
     * @param assetManager
     * @param physics
     * @param player
     * @param spaceTurrent
     * @param turrentNode 
     */
    public SpaceTurrentAutoShoot(Node rootNode,AssetManager assetManager,BulletAppState physics,CharacterControl player, RigidBodyControl spaceTurrent,Spatial turrentNode) {
        this.rootNode=rootNode;
        this.assetManager=assetManager;
        this.physics=physics;
        this.player=player;
        this.spaceTurrent=spaceTurrent;
        this.turrentNode=turrentNode;
        
    }

    @Override
    protected void controlUpdate(float tpf) {        
         
            if(spaceTurrent.getPhysicsLocation().distance(player.getPhysicsLocation()) <= 100){
                    //setting the warning for your spaceShip
                GameApplication.dangertext.setText("Danger");
                GameApplication.xpText.setText("Approaching Galactic Turrent : "+turrentNode.getName());
                
                timeStack+=tpf;
                
                    if(timeStack >= 0.5f ){          
                       /**
                        * Load Laser Guns starting from the NPC & pointing to the player with speed of 100f
                        */
                      Load_LaserGun(new Sphere(10, 10, 0.2f),"man_smoke_1.png",spaceTurrent.getPhysicsLocation()
                            ,Vector3f.ZERO,0.2f,0.15f,player.getPhysicsLocation().subtract(spaceTurrent.getPhysicsLocation()).normalize().mult(100f));
                      /**
                       * Rotate the NPC to face the player
                       */
                      rotateNPCTOFacePlayer(player.getPhysicsLocation(),Vector3f.UNIT_Y);
                      /**
                       * create an auidoNode & attaches it to the rootNode
                       */
                      new SoundEffects(assetManager, rootNode,"galacticGunShoots.wav", false).play();
                            /**
                             * Reset the coolDown time
                             */
                            timeStack=0.0f;

                     }
           }else{
                    /**
                     * Reset the rotation of the NPC
                     */
                    rotateNPCTOFacePlayer(new Vector3f(0f,0f,0f),Vector3f.UNIT_Y);

                 }
    }
    
    
     public void Load_LaserGun(Mesh mesh,String Tex,Vector3f startingPosition,Vector3f gravity,float startSizeOfEffect,float endSizeOfEffect,
            Vector3f directionOfShooting ) {
           
                /** Create a Laser Gun geometry and attach to scene graph. new Box(0.01f, 0.03f, 0.01f)*/
                Geometry laser_geo = new Geometry("Space Turrent Laser",mesh);
                Material lasermat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                Texture monkeyTex = assetManager.loadTexture("Textures/"+Tex);
                lasermat.setTexture("ColorMap", monkeyTex);
                laser_geo.setMaterial(lasermat);
                Node LaserGunNode=new Node("Space Turrent Laser");
                LaserGunNode.attachChild(laser_geo);
                LaserGunNode.attachChild(effect(startSizeOfEffect, endSizeOfEffect, ColorRGBA.Red, ColorRGBA.Yellow));
                /** Position Laser gun above the camera location by 1f &  to the right by 0.008f & forward +0.2f */
                //   player.getPhysicsLocation().add(new Vector3f(1f,1f,0f))
                LaserGunNode.setLocalTranslation(startingPosition);
                /** Make the laser gun particles physical with a mass > 0.0f */
                RigidBodyControl ball_phy = new RigidBodyControl(CollisionShapeFactory.createDynamicMeshShape(laser_geo),0.1f);
                /** Add physical ball to physics space. */
                LaserGunNode.addControl(ball_phy);
                //add rock decay conrtol
                LaserGunNode.addControl(new LaserGunDecayControl(GameApplication.player,physics));
                physics.getPhysicsSpace().add(ball_phy);
                /** setting the gravity of the shoots to zero in all directions x,y,z */
                ball_phy.setGravity(gravity);
                /** Accelerate the physcial ball to shoot it in the direction of camera "see Vector3f multiplications" */
                ball_phy.setLinearVelocity(directionOfShooting);
                /**attach the laser shoots to our node */
                rootNode.attachChild(LaserGunNode);

               
    }

    /**
     * Create a Particle EMitter
     * @param startSize of emitter
     * @param Endsize of emitter
     * @param startColor of emitter
     * @param endcolor of emitter
     * @return ParticleEmitter
     */
     public ParticleEmitter effect(float startSize,float Endsize,ColorRGBA startColor,ColorRGBA endcolor){

         ParticleEmitter fireEffect = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 300);
           Material fireMat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
//           fireMat.setTexture("Texture", assetManager.loadTexture("Textures/Fire.png"));
           fireEffect.setMaterial(fireMat);
           fireEffect.setImagesX(1); 
           fireEffect.setImagesY(1); // 2x2 texture animation
           fireEffect.setEndColor(endcolor );   // red
           fireEffect.setStartColor( startColor ); // yellow
           fireEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 0, 0));
           fireEffect.setStartSize(startSize);
           fireEffect.setEndSize(Endsize);
           fireEffect.setLowLife(0.5f);
           fireEffect.setHighLife(1f);
           fireEffect.getParticleInfluencer().setVelocityVariation(3f);

        return fireEffect;
    }
    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {

    }

    /**
     * Turns the NPC physics viewDirection to face the player
     * @param NPClookPosition Look direction vector  
     * @param upVector the Y-axis prependicular line
     */
    private void rotateNPCTOFacePlayer(Vector3f NPClookPosition,Vector3f upVector) {
          turrentNode.lookAt(NPClookPosition, upVector);
          spaceTurrent.setPhysicsRotation(turrentNode.getLocalRotation());
    }
    
}

[EDIT] :

2 Likes