Package metro.adam.tank

Source Code of metro.adam.tank.Tank

package metro.adam.tank;

import java.net.URL;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import java.util.logging.Level;

import javax.swing.ImageIcon;

import jmetest.TutorialGuide.HelloIntersection;
import jmetest.terrain.TestTerrain;
//import jmetest.TutorialGuide.HelloIntersection.BulletMover;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.DirectionalLight;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Controller;
import com.jme.scene.Line;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.Spatial;
import com.jme.scene.Text;
import com.jme.scene.TriMesh;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Cylinder;
import com.jme.scene.shape.Dome;
import com.jme.scene.shape.Sphere;
import com.jme.scene.shape.Pyramid;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.util.LoggingSystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.BufferUtils;
import com.jmex.sound.openAL.SoundSystem;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;


public class Tank extends SimpleGame{
    public static void main(String[] args) {
        Tank app=new Tank();    // Create Object
        app.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);
        // Turn the logger off so we can see the XML later on
        LoggingSystem.getLogger().setLevel(Level.OFF);
        // Signal to show properties dialog
        app.start();    // Start the program
    }
    private Node tankTurret;
    private float currentPitch = -30.0f;
    private float currentYaw = 30.0f;
    private Node missleTrajectory = new Node("missleTrajectory");
    private static final float BARREL_LENGTH = 1.8f;
    private static final float BARREL_ELEVATION = .3f;
    private Vector3f barrelPosition = new Vector3f(0.0f,BARREL_ELEVATION,1.1f);
    private Text gameStats = new Text("gameStats", "yaw: "+ currentYaw+ "\npitcdh: "+ currentPitch +"\n");
    private Cylinder tankTurretBarrel;
   
    //DDaniels added 05/20/2006
    private static final String HIT = "HIT!!";
    private static final String NO_HIT = "NO HIT";
    private Text tankHUD = new Text("tankHUD", "");
    private Text hitStatus = new Text("hitStatus", NO_HIT);
    private Line trajectoryLine;
    private Node trajectoryNode = new Node("trajectorynode");
    private Node tankNode;
    //The target getting hit
    private TriMesh target;
  /** Used to move target location on a hit */
  Random r = new Random();
    private TerrainBlock tb;
    private float agl = 0.0f;
    protected void simpleInitGame()
    {
     
        //Sphere dome = new Sphere("TankDome", new Vector3f(-1.0f,1.0f,0.5f),16,16,.5f);
      TriMesh dome = new Dome("TankDome", new Vector3f(0, 0, 0), 16, 16, .5f);
      dome.setLocalTranslation(new Vector3f(-1.0f,1.0f,0.5f));
        //Cylinder canon = new Cylinder("Canon", 16, 16, 0.25f, 3.0f,true);
      TriMesh mesh = new TriMesh("TankMesh");
     
      Vector3f[] vertexes = {
          new Vector3f(1.0f,.5f,0.0f),
          new Vector3f(0.0f,0.0f,0.0f),
          new Vector3f(0.0f,1.0f,0.0f),
          new Vector3f(-2.0f,0.0f,0.0f),
          new Vector3f(-2.0f,1.0f,0.0f),
         
          new Vector3f(-3.0f,0.5f,0.0f),
          new Vector3f(1.0f,.5f,1.0f),
          new Vector3f(0.0f,0.0f,1.0f),
          new Vector3f(0.0f,1.0f,1.0f),
          new Vector3f(-2.0f,0.0f,1.0f),
          new Vector3f(-2.0f,1.0f,1.0f),
          new Vector3f(-3.0f,0.5f,1.0f)};
     
     
      Vector3f[] normals={
                new Vector3f(0,0,-1),
                new Vector3f(0,0,-1),
                new Vector3f(0,0,-1),
                new Vector3f(0,0,-1),
                new Vector3f(0,0,-1),
                new Vector3f(0,0,-1),
                new Vector3f(0,0,1),
                new Vector3f(0,0,1),
                new Vector3f(0,0,1),
                new Vector3f(0,0,1),
                new Vector3f(0,0,1),
                new Vector3f(0,0,1)};
     
     
     
     
      int[] indexes = {0,1,2,2,3,1,2,4,3,4,5,3,6,7,8,8,9,7,
              8,10,9,10,11,9,1,7,9,1,3,9,9,3,11,3,11,5,
              6,0,8,8,2,0,8,10,2,10,4,2,4,11,5,10,4,11,1,7,6,0,6,1};
     
      mesh.reconstruct(BufferUtils.createFloatBuffer(vertexes),
              BufferUtils.createFloatBuffer(normals),
              null, null,BufferUtils.createIntBuffer(indexes));
     
     
     
      mesh.setModelBound(new BoundingBox());
      mesh.updateModelBound();
     
      tankNode = new Node("TankNode");
      tankTurret = new Node("tankTurret");
        tankTurretBarrel = new Cylinder("tankTurretBarrel", 16, 16, .1f, BARREL_LENGTH );
        tankTurretBarrel.setModelBound(new BoundingBox());
        tankTurretBarrel.updateModelBound();

        tankTurretBarrel.setLocalTranslation(barrelPosition);
        tankTurret.attachChild(tankTurretBarrel);
        //tankTurret.attachChild(dome);
        tankTurret.setLocalTranslation(new Vector3f(-1.0f,1.0f,0.5f));
       
        //Text code
        tankHUD.setLocalTranslation(new Vector3f(display.getWidth() / 2f - 8f,
            30, 0));
        tankHUD.print("yaw: "+ currentYaw+ "\npitch: "+ currentPitch +"\npower:"+Vm);
        hitStatus.setLocalTranslation(new Vector3f(display.getWidth() / 2f - 8f,
            60, 0));
    target = new Sphere("my sphere", 15, 15, 1);
    target.setModelBound(new BoundingSphere());
    target.updateModelBound();
        target.setLocalTranslation(new Vector3f(r.nextFloat() * 10, r
        .nextFloat() * 10, r.nextFloat() * 10));
       
       //ddaniels
        Vector3f lineV[] = {new Vector3f(0.0f, 0.0f, 0.0f)};
        trajectoryLine = new Line("Trajectory",lineV, null, null,null);
        trajectoryNode.attachChild(trajectoryLine);
       
      tankNode.attachChild(mesh);
      tankNode.attachChild(dome);
      tankNode.attachChild(tankTurret);
     
      tankNode.setLocalScale(2);
      tankNode.setLocalTranslation(new Vector3f(100,0, 100));
      tankNode.updateWorldBound();
        //we now store this initial value, because we are rotating the wheels the bounding box will
        //change each frame.
        agl = ((BoundingBox)tankNode.getWorldBound()).yExtent;
        System.out.println("agl="+agl);
        //Add terrain to the scene
        buildTerrain();

        //Add lighting
        buildLighting();
       
      rootNode.attachChild(tankNode);
      //rootNode.attachChild(missleTrajectory);
      rootNode.attachChild(target);
      rootNode.attachChild(trajectoryNode);
      rootNode.attachChild(posBox);
      fpsNode.attachChild(tankHUD);
      fpsNode.attachChild(hitStatus);
     
    /** Create a skybox to suround our world */
    Skybox sb = new Skybox("skybox", 500, 500, 500);
    URL monkeyLoc = HelloIntersection.class.getClassLoader().getResource(
        "data/texture/sky4stars-a_original.jpg");
    TextureState ts = display.getRenderer().createTextureState();
    ts.setTexture(TextureManager.loadTexture(monkeyLoc, Texture.MM_LINEAR,
        Texture.FM_LINEAR));
    sb.setRenderState(ts);

    // Attach the skybox to our root node, and force the rootnode to show
    // so that the skybox will always show
    rootNode.attachChild(sb);
    rootNode.setCullMode(Spatial.CULL_NEVER);
    rootNode.setLocalTranslation(new Vector3f(-20f, -60f, -20f));
        // Assign the "+" key on the keypad to the command "coordsUp"
        KeyBindingManager.getKeyBindingManager().set(
            "pitchDown",
            KeyInput.KEY_U);

        // Adds the "u" key to the command "coordsUp"
        KeyBindingManager.getKeyBindingManager().set(
            "yawRight",
            KeyInput.KEY_K);
       
        // Assign the "-" key on the keypad to the command "coordsDown"
        KeyBindingManager.getKeyBindingManager().set(
            "pitchUp",
            KeyInput.KEY_J);
   
        // Adds the "d" key to the command "coordsDown"
        KeyBindingManager.getKeyBindingManager().set(
            "yawLeft",
            KeyInput.KEY_H);
        KeyBindingManager.getKeyBindingManager().set(
                "fire",
                KeyInput.KEY_SPACE);
        KeyBindingManager.getKeyBindingManager().set(
                "powerUp",
                KeyInput.KEY_Z);
        KeyBindingManager.getKeyBindingManager().set(
                "powerDown",
                KeyInput.KEY_X);
       
        setTurretAngle();
       
       
    }

    /**
     * creates a light for the terrain.
     */
    private void buildLighting() {
        /** Set up a basic, default light. */
        DirectionalLight light = new DirectionalLight();
        light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
        light.setDirection(new Vector3f(1,-1,0));
        light.setShadowCaster(true);
        light.setEnabled(true);

          /** Attach the light to a lightState and the lightState to rootNode. */
        LightState lightState = display.getRenderer().createLightState();
        lightState.setEnabled(true);
        lightState.setGlobalAmbient(new ColorRGBA(.2f, .2f, .2f, 1f));
        lightState.attach(light);
        rootNode.setRenderState(lightState);
    }
    /**
     * build the height map and terrain block.
     */
    private void buildTerrain() {
       
       
        MidPointHeightMap heightMap = new MidPointHeightMap(64, 1f);
        // Scale the data
        Vector3f terrainScale = new Vector3f(4, 0.1575f, 4);
        // create a terraiwblock
         tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
                heightMap.getHeightMap(), new Vector3f(0, 0, 0), false);
        //tb.setLocalTranslation(new Vector3f(-20, -60, -20));
        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();

        // generate a terrain texture with 2 textures
        ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
                heightMap);
        pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
                .getResource("jmetest/data/texture/grassb.png")), -128, 0, 128);
        pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
                .getResource("jmetest/data/texture/dirt.jpg")), 0, 128, 255);
        pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
                .getResource("jmetest/data/texture/highest.jpg")), 128, 255,
                384);
        pt.createTexture(32);
       
        // assign the texture to the terrain
        TextureState ts = display.getRenderer().createTextureState();
        Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
                Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR, true);
        ts.setTexture(t1, 0);
       
        //load a detail texture and set the combine modes for the two terrain textures.
        Texture t2 = TextureManager.loadTexture(
                TestTerrain.class.getClassLoader().getResource(
                "jmetest/data/texture/Detail.jpg"),
                Texture.MM_LINEAR_LINEAR,
                Texture.FM_LINEAR);

        ts.setTexture(t2, 1);
        t2.setWrap(Texture.WM_WRAP_S_WRAP_T);

        t1.setApply(Texture.AM_COMBINE);
        t1.setCombineFuncRGB(Texture.ACF_MODULATE);
        t1.setCombineSrc0RGB(Texture.ACS_TEXTURE);
        t1.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
        t1.setCombineSrc1RGB(Texture.ACS_PRIMARY_COLOR);
        t1.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
        t1.setCombineScaleRGB(1.0f);

        t2.setApply(Texture.AM_COMBINE);
        t2.setCombineFuncRGB(Texture.ACF_ADD_SIGNED);
        t2.setCombineSrc0RGB(Texture.ACS_TEXTURE);
        t2.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
        t2.setCombineSrc1RGB(Texture.ACS_PREVIOUS);
        t2.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
        t2.setCombineScaleRGB(1.0f);

        tb.setRenderState(ts);
        //set the detail parameters.
        tb.setDetailTexture(1, 16);
        tb.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
        rootNode.attachChild(tb);
       
       
    }

    private static final float MIN_PITCH = -90;
    private static final float MAX_PITCH = 25;
    private boolean fired = false;
    private Vector3f normal = new Vector3f();
   
    private void updateTankHeight(){
        //make sure that if the player left the level we don't crash. When we add collisions,
        //the fence will do its job and keep the player inside.
      Vector3f tankPos = tankNode.getLocalTranslation();
     
      //tankPos.x -= 20;
      //tankPos.y -= 60;
      //tankPos.z -= 20;
     
        float characterMinHeight = tb.getHeight(tankPos)+agl;
        //System.out.println("MinHeight="+characterMinHeight);
        if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
            tankNode.setLocalTranslation(new Vector3f(tankPos.x,characterMinHeight, tankPos.z )) ;
        }
        //get the normal of the terrain at our current location. We then apply it to the up vector
        //of the player.
        tb.getSurfaceNormal(tankNode.getLocalTranslation(), normal);
        if(normal  != null) {
            tankNode.rotateUpTo(normal);
        }
        //rootNode.updateWorldTranslation();
        //Because we are changing the scene (moving the skybox and player) we need to update
        //the graph.
        //rootNode.updateGeometricState();
    }
    // Called every frame update
    protected void simpleUpdate(){

      //Remove any
      comittNodeRemoval();
        boolean updateTurret = false;
        //update Tank position
        updateTankHeight();
        // If the coordsDown command was activated
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("pitchDown",true)){
          currentPitch -= .5f;
          if(currentPitch<MIN_PITCH){
            currentPitch = MIN_PITCH;
          }
          updateTurret = true;
        }
        // if the coordsUp command was activated
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("pitchUp",true)){
          currentPitch += .5f;
          if(currentPitch>MAX_PITCH){
            currentPitch = MAX_PITCH;
          }
          updateTurret = true;
        }
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("yawRight",true)){
          currentYaw -= .5f;
          /*if(currentYaw<=0)
            currentYaw = 360;*/
          updateTurret = true;
        }
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("yawLeft",true)){
          currentYaw += .5f;
          /*if(currentYaw>=360)
            currentYaw=0;*/
          updateTurret = true;
        }
        // jhurst 05/20/06 changed from "true" to "false"
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("fire",false) && !fired){
          fire();
          fired = true;
        }
        if(KeyBindingManager.getKeyBindingManager().isValidCommand("powerUp",true)){
          Vm += 1.0f;
          updateTurret = true;
          if(Vm>50.0f){
            Vm = 50.0f;
          }
        }
        if(KeyBindingManager.getKeyBindingManager().isValidCommand("powerDown",true)){
          Vm -= 1.0f;
          updateTurret = true;
          if(Vm<10.0f){
            Vm = 10.0f;
          }
        }
        else{
          fired = false;
        }
       
       
        if (updateTurret) {
          setTurretAngle();
          tankHUD.print("yaw: "+ currentYaw+ "\npitch: "+ currentPitch +"\npower:"+Vm);
        }
      
    }
    private static final float METERS_TO_SIMULATION_UNITS = 0.5f;
    private static final float GRAVITY = -9.8f * METERS_TO_SIMULATION_UNITS;
    private static final float TIME_INCREMENT = 0.15f;
    private float Vm = 25.0f; //muzzle velcoity
    private Box posBox = new Box("posBox", new Vector3f(-.5f, -.5f, -.5f), new Vector3f(.5f, .5f, .5f));
    private void fire(){
      //System.out.println("Firing!!");
      System.out.println("Yaw="+currentYaw + "Pitch="+ currentPitch + " Vm="+Vm);
      posBox.setLocalTranslation(tankTurretBarrel.getWorldTranslation());
        //   jhurst 05/20/06  Commented out
      /* missleTrajectory.removeFromParent();
      missleTrajectory = new Node("missleTrajectory");
     
      //Initial positions - should use muzzle position but whatever
      float x0 = 0.0f;
      float y0 = 0.0f;
      float z0 = 0.0f;
     
      float velX = (float)(velocity*METERS_TO_SIMULATION_UNITS*Math.cos(FastMath.DEG_TO_RAD*currentPitch));
      float velY =(float)(velocity*METERS_TO_SIMULATION_UNITS*-Math.sin(FastMath.DEG_TO_RAD*currentPitch));
      float velZ = (float)(velocity*METERS_TO_SIMULATION_UNITS*Math.cos(FastMath.DEG_TO_RAD*currentYaw));
      System.out.println( "velX="+velX+" velY="+velY+" velZ="+velZ);
      */
     
      //time
      float t = 0.0f;
      float dx = 0.0f;
      float dy = BARREL_ELEVATION;
      float dz = 0.0f;

      float cosX;
      float cosY;
      float cosZ;
      float xe;
      float ze;
      float b, Lx, Ly, Lz, Yb;
      float L = 1.0f;
      Quaternion turretAngle = tankTurretBarrel.getWorldRotation();
      float angles[] = turretAngle.toAngles(null);
      System.out.println("angles[0]="+angles[0]*FastMath.RAD_TO_DEG);
      System.out.println("angles[1]="+angles[1]*FastMath.RAD_TO_DEG);
      System.out.println("angles[2]="+angles[2]*FastMath.RAD_TO_DEG);
      float Alpha = -(angles[0]*FastMath.RAD_TO_DEG) - 90;
      float Gamma = -(angles[1]*FastMath.RAD_TO_DEG) - 90;
      b = (float)(L * Math.cos((90-Alpha) * FastMath.DEG_TO_RAD)); //projection of barrel onto xz plane
      Lx = (float)(b * Math.cos(Gamma * FastMath.DEG_TO_RAD)); // x-component barrel of gun
      Ly = (float)(L * Math.cos(Alpha * FastMath.DEG_TO_RAD)); //y-component
      Lz = (float)(b * Math.sin(Gamma * FastMath.DEG_TO_RAD)); // x-component barrel of gun
     
      Yb  = BARREL_ELEVATION;
     
      cosX = Lx/L;
      cosY = Ly/L;
      cosZ = Lz/L;
     
      //x- and z- coordinates at end of barrel
      //dx = xe = (float)(L*Math.cos((90-Alpha)*FastMath.DEG_TO_RAD) * Math.cos(Gamma * FastMath.DEG_TO_RAD));
      //dz = ze = (float)(L*Math.cos((90-Alpha)*FastMath.DEG_TO_RAD) * Math.sin(Gamma * FastMath.DEG_TO_RAD));
      Vector3f position = tankTurretBarrel.getWorldTranslation();
      System.out.println("tankNode.getWorldTranslation="+tankNode.getWorldTranslation());
      System.out.println("tankTurretBarrel.getWorldTranslation="+this.tankTurretBarrel.getWorldTranslation());
      //DDANIELS HACK = translate to reverse terrain positioning translation, (-20, -60, -20)
     
      dx = xe = position.x + 20;
      dy = Yb = position.y + 60;
      dz = ze = position.z + 20;
     
     
      //  jhurst 05/20/06   Commented out
      //while(dy>=0){
      //  Box box = new Box("position"+t, new Vector3f(-.5f, -.5f, -.5f), new Vector3f(.5f, .5f, .5f));
      //  box.setLocalTranslation(new Vector3f(dx, dy, dz));
      //  box.setLocalScale(.15f);
      //  box.setDefaultColor(ColorRGBA.red);
      //  box.setModelBound(new BoundingBox());
      //  box.updateModelBound();
      //  missleTrajectory.attachChild(box);
      //  //update positionss
      //  t+=TIME_INCREMENT;
      //  dx = Vm * cosX * t + xe;
      //  dy = (float)((Yb + L * Math.cos(Alpha*FastMath.DEG_TO_RAD))+ (Vm * cosY * t)  + (0.5f * GRAVITY*t*t));
      //  dz = Vm * cosZ * t + ze;
        //System.out.println("t="+t+" dx="+dx+" dy="+dy+" dz="+dz);
      //}
     
     
      //   jhurst 05/20/06 I reorganized the code above to make the new
      //   firing method work.  Instead of dealing with creating a box along
      //   the trajectory, like doug implemented to start, I just take the
      //   vector representing the initial motion of the block and use that to
      //   create a box with a BulletMover controller that manages the movement
      //   for me. ROCK
     
      // Get the initial velocity components based on the muzzel velocity
      // Vm and the pitch/yaw of the barrel
      dx = Vm * cosX + xe;
      dy = (float)((Yb + L * Math.cos(Alpha*FastMath.DEG_TO_RAD))+ (Vm * cosY));
      dz = Vm * cosZ + ze;
       
      // Create the bullet and translate it to be in the center of the barrel.
      // This doesn't end up looking all that great at the moment, but its a
      // start.  Also, set the size, color and bounding box of the bullet.
      Box box = new Box("position"+t, new Vector3f(-.5f, -.5f, -.5f), new Vector3f(.5f, .5f, .5f));
      box.setLocalTranslation(new Vector3f(xe, Yb, ze));
      box.setLocalScale(3f);
    box.setDefaultColor(ColorRGBA.red);
    box.setModelBound(new BoundingBox());
    box.updateModelBound();
   
    // Create a node for the missle trajectory.  This makes it possible to apply
    // a light state to the bullets.  Now that I think of it, this could probably
    // be removed by applying the LightState to the rootNode... but I don't really
    // know... too tired to try.
    Node missleTrajectory2 = new Node("missleTrajectory");
      missleTrajectory2.attachChild(box);
     
      // Don't know what this is doing really.... see comments below
        LightState ls = display.getRenderer().createLightState();
        ls.setEnabled(false);
        missleTrajectory2.setRenderState(ls);
        missleTrajectory2.updateRenderState();
       
        //  Add the controller class to the box. Notice, I am passing the
        //  missleTrajectory2 node to the BulletMover class.  This is so the
        //  bullet can be removed from the rootNode when it times out.  If
        //  I could remove the missleTrajectory2 junk, I could make it a lot simpler.
        box.addController(new BulletMover(this, box, new Vector3f(dx,dy,dz),missleTrajectory2));
        rootNode.attachChild(missleTrajectory2);
    }
    private void setTurretAngle(){
        Quaternion turretAnglePitch = new Quaternion();
        Quaternion turretAngleYaw = new Quaternion();
        Quaternion turretAngle;

        turretAngleYaw.fromAngleAxis(FastMath.DEG_TO_RAD*currentYaw, new Vector3f(0, 1, 0));
        turretAnglePitch.fromAngleAxis(FastMath.DEG_TO_RAD*currentPitch, new Vector3f(1, 0, 0));
        turretAngle = turretAngleYaw.mult(turretAnglePitch);
       
        tankTurret.setLocalRotation(turretAngle)
       
       
        //ddaniels added 05/20/06
        //updateTrajectoryLine();
        // jhurst 05/20/06  commented out.
        // fire(); 
    }
   
    //List of items to remove
    ArrayList<Spatial> nodesToRemove = new ArrayList<Spatial>();
    public void removeNode(Spatial s)
    {
      if(!nodesToRemove.contains(s))
      {
        nodesToRemove.add(s);
      }
    }
   
    //Actually perform the removal
    private void comittNodeRemoval()
    {
      Iterator<Spatial> removeNodeIter = nodesToRemove.iterator();
      while(removeNodeIter.hasNext())
      {
        Spatial s = removeNodeIter.next();
        s.removeFromParent();
        //remove spatial from list now that it has been cleaned
        removeNodeIter.remove();
      }
    }
    private void updateTrajectoryLine(){
     
      //time
      float t = 0.0f;
      float dx = 0.0f;
      float dy = BARREL_ELEVATION;
      float dz = 0.0f;

      float cosX;
      float cosY;
      float cosZ;
      float xe;
      float ze;
      float bar, Lx, Ly, Lz, Yb;
      float L = 1.0f;
      float Alpha = -currentPitch - 90;
      float Gamma = -currentYaw - 90;
      bar = (float)(L * Math.cos((90-Alpha) * FastMath.DEG_TO_RAD)); //projection of barrel onto xz plane
      Lx = (float)(bar * Math.cos(Gamma * FastMath.DEG_TO_RAD)); // x-component barrel of gun
      Ly = (float)(L * Math.cos(Alpha * FastMath.DEG_TO_RAD)); //y-component
      Lz = (float)(bar * Math.sin(Gamma * FastMath.DEG_TO_RAD)); // x-component barrel of gun
     
      Yb  = BARREL_ELEVATION;
      ArrayList linePoints = new ArrayList();    
      cosX = Lx/L;
      cosY = Ly/L;
      cosZ = Lz/L;
     
      //x- and z- coordinates at end of barrel
      //dx = xe = (float)(L*Math.cos((90-Alpha)*FastMath.DEG_TO_RAD) * Math.cos(Gamma * FastMath.DEG_TO_RAD));
      //dz = ze = (float)(L*Math.cos((90-Alpha)*FastMath.DEG_TO_RAD) * Math.sin(Gamma * FastMath.DEG_TO_RAD));
     
      Vector3f position = tankTurretBarrel.getLocalTranslation();
      dx = xe = position.x;
      dy = Yb = position.y;
      dz = ze = position.z;
     
      //Solve for when dy == 0 to figure out how many time increments there are
      /*
      //dy == 0 when t = (-b +- sqrt(b^2-4ac)/(2a)
      float a = Vm * cosY;
      float b = -0.5f * GRAVITY;
      float c = (float) (Yb + L * Math.cos(Alpha*FastMath.DEG_TO_RAD) );
      //float c = .1f;
      float ty0 = (float) ((-b + Math.sqrt(b*b+4*a*c))/(2*a));
      System.out.println("a="+a + "\nb="+b+"\nc="+c+"\nty0="+ty0);
      //calculate the number of time increments
      //int numTimeIncrements = (int)Math.ceil(ty0/TIME_INCREMENT);
      int numTimeIncrements = 0;

      //count to find out how big to allocate
  */
      while(dy>=0){

        linePoints.add(new Vector3f(dx,dy,dz));
        //update positionss
        t+=TIME_INCREMENT;
        dx = Vm * cosX * t + xe;
        //System.out.println("Yb + L * Math.cos(Alpha*FastMath.DEG_TO_RAD))+ (Vm * cosY * t)  + (0.5f * GRAVITY*t*t)==\n"+
        //    Yb + " + " + L * Math.cos(Alpha*FastMath.DEG_TO_RAD)+ " + ("  + (Vm * cosY+"*"+t) + ")" + 0.5f * GRAVITY+"*"+t*t+"=\n"+
        //    (float)((Yb + L * Math.cos(Alpha*FastMath.DEG_TO_RAD))+ (Vm * cosY * t)  + (0.5f * GRAVITY*t*t)));
        dy = (float)((Yb + L * Math.cos(Alpha*FastMath.DEG_TO_RAD))+ (Vm * cosY * t+ (0.5f * GRAVITY*t*t));
        dz = Vm * cosZ * t + ze;
        System.out.println("t="+t+" dx="+dx+" dy="+dy+" dz="+dz);
      }

    Vector3f[] vertex = new Vector3f[linePoints.size()];
    ColorRGBA[] color = new ColorRGBA[linePoints.size()];
    for (int i = 0; i < linePoints.size(); i++) {
      vertex[i] = (Vector3f)linePoints.get(i);
      color[i] = ColorRGBA.red;
     
    }

    Line l = new Line("Line Group", vertex, null, color, null);
    l.setMode(Line.CONNECTED);
    l.setModelBound(new BoundingBox());
    l.updateModelBound();
    l.setLightCombineMode(LightState.OFF);
     
      trajectoryLine.removeFromParent();
      trajectoryLine = l;   
      this.trajectoryNode.attachChild(trajectoryLine);
    }
   

  class BulletMover extends Controller {
      private static final long serialVersionUID = 1L;

      // The bullet to be controlled
      // TODO make this more general.  Use a super class instead.
    TriMesh bullet;

    float lifeTime = 15; // sec

    // Velocity in each component so we can determine the
    // updated bullet location.  We hack in a constant gravity
    // in the y direction to accelerate the object back
    // towards the x-z plane.
    float velX = 0f// meters/sec
    float velY = 0f// meters/sec
    float velZ = 0f// meters/sec


    // Node for easy removal from the scene
    // TODO remove this Node passing non-sense
    Node traj;
    Tank tankGame;

    // basic constructor sets all our members
    BulletMover(Tank tGame, TriMesh bullet, Vector3f direction, Node traj) {
      //We need the tnak game so that we can safely remove objects
      tankGame = tGame;
      this.bullet = bullet;
      this.velX = direction.x;
      this.velY = direction.y;
      this.velZ = direction.z;
      this.traj = traj;
     
    }

    public void update(float time) {

      //  Check if our node has timed out, is so, remove it from
      //  the rootNode tree
      lifeTime -= time;
      if (lifeTime < 0) {
        traj.removeController(this);
        removeNode(traj);

        return;
      }

      Vector3f bulletPos = bullet.getLocalTranslation();

      /** Does the bullet intersect with target? */
      if (bullet.getWorldBound().intersects(target.getWorldBound())) {
            target.setLocalTranslation(new Vector3f(r.nextFloat() * 10+100, r
            .nextFloat() * 10+100, r.nextFloat() * 10+100));
            traj.removeController(this);
            removeNode(traj);
       
        hitStatus.print(HIT);
        return;
      }
      // Check if we have hit the ground, or we have hit
      // the enemy tank so we can remove the bullet and
      // possibly trigger an explosion.
      // TODO add collision detection or something.
      if(bulletPos.y < 0)
      {
        // These lines are commented out so the box will site on
        // the ground until it times out.
        //rootNode.detachChild(traj);
       
        traj.removeController(this);
        return;
      }

      // Move the bullet to the next location based on time.
      // TODO use the conversion from METERS to GRID SQUARES here....
      Vector3f dPos = new Vector3f( velX * time,      // X position
                    (float)(velY * time + .5f*(-9.8f)*time*time), // Y
                    velZ * time);    // Z position
      bulletPos.addLocal(dPos);
      bullet.setLocalTranslation(bulletPos);

      // update the Y velocity based on gravity.
      velY = velY + (-9.8f)*time;
    }
  }

}

 
TOP

Related Classes of metro.adam.tank.Tank

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.