Tank collides with ghost wall?!

Hi guys :smiley:



I have a little problem again. I have loaded a map with a floor, walls and tanks. I set several CollisionGroups for the wall, the floor and the tanks.

Now everythings fine and the tank collides with the wall and not with the floor.

Since Tanks can shoot and these bullets can destroy walls I have to change the type of my wall to the type of the floor, attach this Geometry to the floor node and remove it from the wall node and set the correct texture.

All this also worked without problem.

Now here comes the problem:

The tank still collides with the wall,which was shot down to a floor object!

Here is what I have done and I attached 2 screenshots:



GameObject gO = getGameObjectByName(elem);
floor.attachChild(gO.getSpatial());
walls.detachChildNamed(gO.getElementName());
gO.changeToFloorObject();



The method changeToFloorObject does the following (where b is a wall object - a simple box):


b.setLocalScale(new Vector3f(1,0.01f,1));
URL res = null;
res = getClass().getClassLoader().getResource("resources/Sand0028_thumblarge.jpg");
final Texture t = TextureManager.loadTexture(res, Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
final TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
ts.setTexture(t);
ts.setEnabled(true);
b.setModelBound(null); //remove bounding model
b.updateModelBound();
b.setRenderState(ts);
b.updateRenderState();



In the first screenshot there are walls (signalized by the red arrow) which I shot down during gameplay. The other screen shows how the tank collided with a "ghost" wall....

Now, how do I signalize to my tank, that there WAS a wall and the way is now free to cross the new path?

Regards and I would be very happy if anyone could help me out...:/

Alessandro

Can you provide any information as to what you are using for your collision detection? Are you using jME physics or something else?

Yeah, I use JME Physics with collision groups…

The walls are in a static node called wallNode and the floor is attached analogously to a node called floorNode, if this can be of any help.

so when you change from a wall object to a floor object, are you also removing the wall from the physics space?

Sorry for the noobish question, but how do I do this?^^



a little code snippet would be very appreciated :smiley:

physicsSpace.removeNode(wall);



Can you explain/provide how you build your walls and add them to the physics space?

Also, it might help you out to render the physics geometry so you can see problems like this. To do that, add this line to the end of your render()


PhysicsDebugger.drawPhysics( getPhysicsSpace(), renderer );

Hello nymon,



Alessandro and I are working in a team on this project. Here is the method that builds our walls:



private void setupMap() {
      URL res = null;
      floor = getPhysicsSpace().createStaticNode();
      walls = getPhysicsSpace().createStaticNode();
      gameNode.attachChild(floor);
      wallNode.attachChild(walls);
      for(int i=0;i<gameObjects.length;i++)
      {   
         for ( int y=0 ; y < gameObjects.length ; y++){
            /***Set textures***/
            int texture = gameObjects[i][y].getTexture();
            if(texture == 0 || texture == 3)
               res = getClass().getClassLoader().getResource("resources/Sand0028_thumblarge.jpg");
            else if(texture == 1)
               res = getClass().getClassLoader().getResource("resources/rockwall_small.jpg");
            else if(texture == 2)
               res = getClass().getClassLoader().getResource("resources/cracked_wall_small.png");

            final Texture t = TextureManager.loadTexture(res, Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
            final TextureState ts = renderer.createTextureState();
            ts.setTexture(t);
            ts.setEnabled(true);
            
            if(texture == 3)
            {
               gameObjects[i][y].setSpawn(true);
            }
            /***End textures***/
            if(texture == 0 || texture == 3)
            {   
               floor.attachChild(gameObjects[i][y].getSpatial());
            }
            else//(texture == 1 || texture == 2)
            {
               walls.attachChild(gameObjects[i][y].getSpatial());
            }
            gameObjects[i][y].setRenderState(ts);
            gameObjects[i][y].updateRenderState();            
         }
      }            
      
       final Material customMaterial = new Material( "floor" );
           customMaterial.setDensity( 10.0f );
           MutableContactInfo contactDetails = new MutableContactInfo();
           contactDetails.setBounce( 0 );
           contactDetails.setMu( 0 );
           customMaterial.putContactHandlingDetails( customMaterial, contactDetails );

      floor.setMaterial(customMaterial);
      floor.generatePhysicsGeometry();
      walls.setMaterial(customMaterial);
      walls.generatePhysicsGeometry();
      cgFloor = getPhysicsSpace().createCollisionGroup("floor");
      cgWalls = getPhysicsSpace().createCollisionGroup("walls");
      floor.setCollisionGroup(cgFloor);
      walls.setCollisionGroup(cgWalls);
      cgFloor.collidesWith(cgWalls, false);
   }



gameObjects is an array that contains the information of the map element. (wall or floor and the texture)

P.s.:

physicsSpace.removeNode(wall);

does not exist

PhysicsSpace.removeNode() is protected and only used internally.



You can do a physicNode.setActive(false / true), which then removes/attaches the node from/to the physics space.

Core-Dump said:

PhysicsSpace.removeNode() is protected and only used internally.

You can do a physicNode.setActive(false / true), which then removes/attaches the node from/to the physics space.

good call.

Since it looks like your walls are all one object, you would need to remove all your walls (setActive(false)) and then regenerate the wall collision geometry and add it to the physics space. Have you thought of splitting it up into pieces? Then you only have to remove the part you want. So for each game object you would have a static physics node which contained the collision geometry for that piece of wall.

nymon said:

Since it looks like your walls are all one object, you would need to remove all your walls (setActive(false)) and then regenerate the wall collision geometry and add it to the physics space. Have you thought of splitting it up into pieces? Then you only have to remove the part you want. So for each game object you would have a static physics node which contained the collision geometry for that piece of wall.


Well, now I have one StaticPhysicsNode for each wall object and when its time I call setActive(false), remove the node from the walls, change the type and attach it to the floor. It is still the same result...:(

sorry to bother you all guys, but I don't have any idea what the problem could be...:(
Maybe its one function call I'm missing, who knows...Oo

try setting up a small test case where you create a wall, then remove it on a key stroke. Then if you don't get it figured out setting that up, you can post your test and we can help you better.

Ok nymon, I appreciate your willingness to help ^^



import java.net.URL;

import lts.core.objects.LTSGameObject;

import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.shape.Box;
import com.jmex.physics.CollisionGroup;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsCollisionGeometry;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.contact.MutableContactInfo;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;

public class SimpleGamePhysikTestAlex extends SimplePhysicsGame{
   
   //Static Physic nodes
   StaticPhysicsNode floor;
   
   //Dynamic Physic Nodes
   DynamicPhysicsNode tank;
   Box b;
   //PhysicsCollisionGeometry
   private PhysicsCollisionGeometry playerLeftPart;
   private PhysicsCollisionGeometry playerRightPart;
   StaticPhysicsNode boxNode;
   //CollisionGroups
   CollisionGroup cgFloor;
   CollisionGroup cgTank;
   
   //GameElements
   LTSGameObject[][] gameObjects;
   private int gameRows;
   
   //Others
   private Renderer renderer;
   
   
   private void initPlayer() {
      tank = getPhysicsSpace().createDynamicNode();
         rootNode.attachChild(tank);
      
      // Tank down part
      tank.attachChild( new Box( "player", new Vector3f(), 0.35f, 0.3f, 0.3f ) );
        playerLeftPart = tank.createBox( "left" );
        playerLeftPart.getLocalTranslation().set( 0, 0, 0.15f );
        playerLeftPart.getLocalScale().set( 0.7f, 0.6f, 0.3f );
        playerRightPart = tank.createBox( "right" );
        playerRightPart.getLocalTranslation().set( 0, 0, -0.15f );
        playerRightPart.getLocalScale().set( 0.7f, 0.6f, 0.3f );
        tank.getLocalTranslation().set( 6, 0.5f, 5 );
               
        // Rotator and aim
       
        // Collision Group
        cgTank = getPhysicsSpace().createCollisionGroup("tank");
        tank.setCollisionGroup(cgTank);
        cgTank.collidesWith(cgTank, false);
        cgFloor.collidesWith(cgTank, true);
      
      
      // MAss
      
      tank.setMass(25.5f);
      
      
      playerLeftPart.setMaterial( new Material( "player material left" ) );
        playerRightPart.setMaterial( new Material( "player material right" ) );
        MutableContactInfo info = new MutableContactInfo();
        {
            info.setMu( 1 );
            info.setBounce( 0.4f );
            info.setMinimumBounceVelocity( 1f );
            info.setMuOrthogonal( 0.01f );
        }
        playerLeftPart.getMaterial().putContactHandlingDetails( null, info );
        playerRightPart.getMaterial().putContactHandlingDetails( null, info );
      
   }
   
   public static void main(String[] args) {
      // TODO Auto-generated method stub
      SimpleGamePhysikTestAlex t = new SimpleGamePhysikTestAlex();
      t.start();
   }

   @Override
   protected void simpleInitGame() {
      renderer = display.getRenderer();
      //initmap("Map1x8.lts");
      createFloor();
      
      initPlayer();
//      LTSHandleConfig ltsHandleConfig = new LTSHandleConfig();
//      ltsHandleConfig.loadConfig();
      KeyBindingManager.getKeyBindingManager().set("pause", KeyInput.KEY_P);
      KeyBindingManager.getKeyBindingManager().set("exit", KeyInput.KEY_ESCAPE);
      KeyBindingManager.getKeyBindingManager().set("vor", KeyInput.KEY_1);      
      KeyBindingManager.getKeyBindingManager().set("back", KeyInput.KEY_2);      
      KeyBindingManager.getKeyBindingManager().set("left", KeyInput.KEY_3);      
      KeyBindingManager.getKeyBindingManager().set("right", KeyInput.KEY_4);
      KeyBindingManager.getKeyBindingManager().set("removeBox", KeyInput.KEY_5);
      
      showPhysics = true;
      //pause = true;
      
   }
   
      
   public void releaseTankSpeed()
   {
      Vector3f direction = new Vector3f( 0, 0, 0 );
      playerLeftPart.getMaterial().setSurfaceMotion( direction );
      playerRightPart.getMaterial().setSurfaceMotion( direction );
   }
   
   public void moveForward()
   {
      Vector3f direction;
      direction = new Vector3f( 1.5f, 0, 0 );
      playerLeftPart.getMaterial().setSurfaceMotion( direction );
      playerRightPart.getMaterial().setSurfaceMotion( direction );
   }

   public void moveBack()
   {
      Vector3f direction;
      direction = new Vector3f( -1.5f, 0, 0 );
      playerLeftPart.getMaterial().setSurfaceMotion( direction );
      playerRightPart.getMaterial().setSurfaceMotion( direction );
   }
   
   public void moveLeft()
   {
      Vector3f direction;
      direction = new Vector3f( -0.25f, 0, 0 );
      playerLeftPart.getMaterial().setSurfaceMotion( direction );
      direction = new Vector3f( 0.25f, 0, 0 );
      playerRightPart.getMaterial().setSurfaceMotion( direction );
   }
   
   public void moveRight()
   {
      Vector3f direction;   
      direction = new Vector3f( 0.25f, 0, 0 );
      playerLeftPart.getMaterial().setSurfaceMotion( direction );
      direction = new Vector3f( -0.25f, 0, 0 );
      playerRightPart.getMaterial().setSurfaceMotion( direction );
   }
   
   @Override protected void simpleUpdate()
   {
      boolean moved = false;
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("vor", true)) {
         moved = true;
         moveForward();
      }

      if (KeyBindingManager.getKeyBindingManager().isValidCommand("back", true)) {
         moved = true;
         moveBack();
      }

      if (KeyBindingManager.getKeyBindingManager().isValidCommand("right", true)) {
         moved = true;
         moveRight();
      }
      
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("left", true)) {
         moved = true;
         moveLeft();
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("removeBox", true)) {
         boxNode.detachChild(b);
         boxNode.setActive(false);
         floor.detachChild(boxNode);
         
      }
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit", false)) {
         this.finish();
         //StartGame.bgState.setActive(true);
         //StartGame.singlePlayerState.setActive(true);
      }
      if(!moved)
      {
         if(playerLeftPart != null)
         {
            releaseTankSpeed();
         }
      }
   }
   
   private void createFloor() {
      URL res = null;
      floor = getPhysicsSpace().createStaticNode();
      rootNode.attachChild(floor);
      
        final Box visualFloorBox = new Box( "floor", new Vector3f(), 10, 0.25f, 10 );
       
        floor.attachChild( visualFloorBox );
       
        b = new Box("toRemove", new Vector3f(), 1,1,1);
        boxNode = getPhysicsSpace().createStaticNode();
        boxNode.setName("BoxNode");
        boxNode.attachChild(b);
        floor.attachChild( boxNode );
        b.getLocalTranslation().set(4,0.5f,6);
        boxNode.generatePhysicsGeometry();
        floor.generatePhysicsGeometry();
      cgFloor = getPhysicsSpace().createCollisionGroup("floor");
      floor.setCollisionGroup(cgFloor);
      
   }

}



The removal of the box is done in the simple update method. What am I missing?

Some words, what's done in the "game":
There will be two boxes and a floor. One of the boxes is a DynamicPhysicsNode which can be moved by pressing Keys 1, 2, 3 and 4 (not the numpad keys, since I have a laptop^^). The other box is a static element and the dynamic box (our "tank") is able to collide with this one. By pressing now the 5 key, it will be called the setActive-method of the node, where the static box is attached to, then it will be removed from the floor-node. But the tank still collides with the "ghost" box...I have no clue about that...Oo

Regards

I won't be able to get into it until I get home this evening, but maybe someone else can chime in before then.

it seems the probem was, that you attached a PhyiscsNode to another physicsNode, i think that is not supported.

if you attach both, the floor and the box, to the root node, it work.



    private void createFloor() {
        floor = getPhysicsSpace().createStaticNode();
        rootNode.attachChild(floor);
       
        final Box visualFloorBox = new Box( "floor", new Vector3f(), 10, 0.25f, 10 );
        visualFloorBox.setModelBound(new BoundingBox());
        visualFloorBox.updateModelBound();
        floor.attachChild( visualFloorBox );
        floor.generatePhysicsGeometry();
       
        b = new Box("toRemove", new Vector3f(), 1,1,1);
        b.setModelBound(new BoundingBox());
        b.updateModelBound();
        boxNode = getPhysicsSpace().createStaticNode();
        boxNode.setName("BoxNode");
        boxNode.attachChild(b);
        b.getLocalTranslation().set(4,0.5f,6);
        boxNode.generatePhysicsGeometry();
        rootNode.attachChild( boxNode );
    }

Many thanks Core-Dump, that solved everything!!!

Despite the fact, that my AI does not work anymore…don't know why, but I can fix it…:smiley:



Thank you, too, nymon…:slight_smile: