I am trying to add hitscan guns, to my first person shooter, and to do this, I borrowed code from the Hello Picking example on the wiki.
if (shoot){
// 1. Reset results list.
CollisionResults results = new CollisionResults();
// 2. Aim the ray from cam loc to cam direction.
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in results list.
rootNode.collideWith(ray, results);
// 5. Use the results (we mark the hit object)
if (results.size() > 0) {
// The closest collision point is what was truly hit:
CollisionResult closest = results.getClosestCollision();
// Let's interact - we mark the hit with a red dot.
mark.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(mark);
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(mark);
}
}
This code attaches a red marker to the root node, so that it is touching solid objects, and in the direction you are pointing.
However, a strange issue occurs, that when you face the same direction, and hold down the shoot button, the red dot is placed in the correct spot, but then starts to glide towards the camera.
“non-collidable” just means that you skip it in results… which means you can no longer always just get the closest one.
Alternately, you can use a more advanced picking system where you add listeners to the things you want to pick (or their root/parent). Lemur includes such a picking system and it can be used without the rest of Lemur.
First of all, you use the rootNode: rootNode.collideWith(ray, results);
In an ideal situation you’d split collidables and non-collidables in different Nodes.
Also, you use: results.getClosestCollision();
Which gets the closest result, always. To get the preferred result you can iterate through results and pick out what you need.
Ok, I did what @jayfella said, and I added 2 different nodes that are childs to the root node, one for interactable objects like models, and another for aesthetics like skybox and water. Light is attached to the root node, so it effects everything.
if (shoot){
// 1. Reset results list.
CollisionResults results = new CollisionResults();
// 2. Aim the ray from cam loc to cam direction.
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in results list.
World.collideWith(ray, results);
// 5. Use the results (we mark the hit object)
if (results.size() > 0) {
// The closest collision point is what was truly hit:
CollisionResult closest = results.getClosestCollision();
// Let's interact - we mark the hit with a red dot.
mark.setLocalTranslation(closest.getContactPoint());
NonWorld.attachChild(mark);
} else {
// No hits? Then remove the red mark.
NonWorld.detachChild(mark);
}