Stopping object when it hits

Im trying to make arrows which I fire to stop when they hit a target. I added rigid body control to arrow spatial. First I tried to set rigid body controls mass to zero when it hits a target, but all arrows that I fire in the future have a mass of zero. So I tried to create custom control for arrow spatial in which I did the same, again same result. Last thing I tried was to create a class that extends rigid body control, and there I added PhysicsCollisionListener so when it hits I can call setMass(0), but again it didnt work. Instead of
RigidBodyControl arrowNode=new RigidBodyControl(bulletCollisionShape, 1);
I did:
RigidBodyControl arrowNode=new RigidArrow(bulletCollisionShape, 1, bulletAppState);
I used bulletAppState to set PhysicsCollisionListener.
Maybe the way I’m doing it isnt the best way, so if someone knows what I’m doing wrong or has a better idea how to do this please write.
btw I tryied to create custom control and in there do this: spatial.removeControl(arrowNode), but when arrows hits first or second time it crashes.

First I tried to set rigid body controls mass to zero when it hits a target, but all arrows that I fire in the future have a mass of zero

uh, why do your future arrows have a mass of zero? They aren’t connected. That should work, otherwise you can set the rigid body to kinematic.

@koljo45 said: First I tried to set rigid body controls mass to zero when it hits a target, but all arrows that I fire in the future have a mass of zero.

If this is happening then you are sharing something that shouldn’t be shared or something else is very wrong. I suggest putting together a simple test case to post here so that we can show you what you are doing wrong.

When I press shoot(when I press lmb) this hapens:
[java]ball_geo = assetManager.loadModel(“Models/Arrow2/arrow.mesh.j3o”);
ball_geo.setLocalTranslation(cam.getLocation().add(cam.getDirection()));
ball_geo.setLocalRotation(cam.getRotation());
SphereCollisionShape bulletCollisionShape = new SphereCollisionShape(0.2f);

     bulletNode=new RigidArrow(bulletCollisionShape, 1, bulletAppState, cam.getLocation().add(cam.getDirection()));
    bulletNode.setLinearVelocity(cam.getDirection().mult(25));
    bulletNode.setFriction(1.0f);
    bulletNode.setKinematic(false);
    bulletNode.setCcdMotionThreshold(0.1f);
    bulletNode.setCcdSweptSphereRadius(0.5f);


    ball_geo.addControl(bulletNode);
    rootNode.attachChild(ball_geo);
    bulletAppState.getPhysicsSpace().add(bulletNode);[/java]

RigidArrow:
[java]import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;

/**
*

  • @author Racunalo
    */
    public class RigidArrow extends RigidBodyControl implements PhysicsCollisionListener {
    Vector3f bullet_latest_point,counter;

    public RigidArrow(CollisionShape shape, float mass, BulletAppState bull, Vector3f latest) {
    super(shape, mass);
    setBulletAppState(bull);
    setBullet_latest_point(latest);
    }

    @Override
    public void update(float tpf) {
    super.update(tpf);
    System.out.println(spatial.getLocalTranslation());
    System.out.println(counter);
    spatial.setLocalRotation(arrow_rot(spatial.getLocalTranslation(), bullet_latest_point));
    // spatial.setLocalRotation(arrow_rot(spatial.getLocalTranslation(), bullet_latest_point));
    if(!counter.equals(spatial.getLocalTranslation())){
    bullet_latest_point=counter;
    counter=spatial.getLocalTranslation();
    }
    }

    public Quaternion arrow_rot(Vector3f curr_poss, Vector3f nex_poss){
    Node r=new Node(“aa”);
    r.setLocalTranslation(curr_poss);
    r.lookAt(nex_poss, Vector3f.UNIT_Y);
    r.rotate(3.14f, 0, 0);
    return r.getLocalRotation();
    }

    public void setBullet_latest_point(Vector3f bullet_latest_point) {
    this.bullet_latest_point = bullet_latest_point;
    counter=bullet_latest_point;
    }

    public void setBulletAppState(BulletAppState bull){
    bull.getPhysicsSpace().addCollisionListener(this);
    }

    public void collision(PhysicsCollisionEvent event) {
    if(!“player”.equals(event.getNodeA().getName())&&!“player”.equals(event.getNodeB().getName())){
    setMass(0);
    }
    }

}[/java]
Sry if the code is messy.

I also had a problem that I forgot to mention. Its about Vector counter. I only set it once at the beginning as counter=spatial.getLocalTranslation(), but later it gets eqal with local translation without game setting it, that is every time I see output to the console its same as local translation.

@koljo45 said: I also had a problem that I forgot to mention. Its about Vector counter. I only set it once at the beginning as counter=spatial.getLocalTranslation(), but later it gets eqal with local translation without game setting it, that is every time I see output to the console its same as local translation.

Yes, because you grabbed the reference directly instead of cloning it.

Tnx, just fixt it. If you have any idea on the mass problem just post or if not give me a clue how to do it in a different way.

Its because you are implementing PhysicsCollisionListener on your RigidBodyControl sub-class. For every collision, all Collision() methods will be called, not just the RigidBodies involved in the collision. I would suggest to have a class which is instantiated only once implement PhysicsCollisionListener, and decide what to do based on the controls involved in the collision. Or do it like you are, but check [java]if (event.getObjectA() == this || event.getObjectB() == this)[/java]

1 Like

Thank you for the help you gave me. Just did it, and it works. I understand now.