Player/rigid body unable to jump when walking down a slope

Hey guys. I’m new to the JMonkey Engine, but pretty experienced with Java and game development. I installed JME3 beta along with the sdk and have read through and tested the ‘official’ tutorials. I like the engine a lot, but can’t seem to get properly working physics. What I am currently working on is a simple 3rd person platformer which uses the physics and scene from the HelloCollision example (the player is a capsuleShape character control which moves via the walkdirection vector but with an offset for free rotation). Everything appears to be working correctly, but if the player is moving downhill (eg. down the terrain or rooftops) the built-in onGround method returns false, and sure enough, attempting to jump does not work. Is there a way I can resolve this issue? I will gladly post more info or code if this is too vague.

Thanks in advance for any suggestions (I searched the forum and did not see any related problems, but if I missed an example or another thread which explains how to resolve this feel free to just post a link and I will play around with it some more).

I suppose you are using the character? Note that it doesn’t have “normal physics” but its own simple physics simulation. So you can’t really avoid this as the character is actually off the ground and falling. You could do a physicsSpace.rayTest() yourself, using a ray that goes a bit further down to only trigger when the character is really more “off the ground”.

Thanks for the fast reply! I thought that might be the case, so I attempted to write my own basic physics, but couldn’t seem to get proper collision detection. I tried two methods, neither of which worked correctly:

  1. I attempted to use the spatial.collideWith(object, resultslist) function so that I could get collisions between the player and the ground. However, this function appears to only get collisions with the bounding box of the sceneModel; If I try to pass in a CollisionShape created via creatMeshShape() it is not accepted as a valid argument (I believe the function requires a collidable, and I did not find any way of converting the collisionshape to a collidable or vice versa).
  2. I also tried using a ghostControl object which followed the player and recorded collisions (using the same boundingshape as the player). This did not work at all, recording random numbers of collisions each frame (usually several hundred, sometimes even >1000), the number of whichwould change when I simply rotated the camera or moved the player forward.



    Would handling all of my collisions via raycasting really be a good idea?



    EDIT: If I did handle collisions myself, how would I change the player’s state to on the ground so that jumping would be accepted? From what I can tell onGround() seems to return a variable that is only able to be edited by the program itself.

The character is actually a ghostObject and a kinematic rigid body and does its own penetration checks. So doing this yourself should not be a big issue. Note that you mix two different collision systems when you use e.g. ray.collideWith(spatial), the geometry-based collision is less flexible and a bit slower than bullet collision which in turn requires a physics space and bullet collision shapes for your objects (e.g. RigidBodyControl, GhostControl etc).

I attempted to create a second ghostControl to follow the player and record collisions, but this doesn’t seem to be working quite right.

No matter where I moved the player, the ghostcontrol would read off 2 collisions; 1 with the character control, which makes sense, and 1 with the RigidBodyControl (which I believe is referring to the scene) which doesn’t make too much sense. the strange part is, it would print a collision with the RigidBodyControl even if the player was in-midair. however, it did not print a collision with the RigidBodyControl when the player jumped past the highest roof in the scene, or stepped off of the edge of the scene. Do GhostControl Objects only check for collisions with bounding boxes, because that certianly seems to be what is going on. here is the code I used:



in the simpleInitApp() method:

ghostFloorCollisions = new GhostControl(capsuleShape);

bulletAppState.getPhysicsSpace().add(ghostFloorCollisions);



in the simpleUpdate() method:

ghostFloorCollisions.setPhysicsLocation(player.getPhysicsLocation().addLocal(new Vector3f(0,0,0)));

List objOverlappingObjects = ghostFloorCollisions.getOverlappingObjects();

int numOverlappingObjects = objOverlappingObjects.size();

if (numOverlappingObjects > 0) {

System.out.println("COLLISIONS: "+Integer.toString(numOverlappingObjects));

System.out.println(objOverlappingObjects);

}

Do you use native bullet? Its not working 100% yet. Also do you add the GhostControl to the player spatial?

Edit: I just see you don’t but move the spatial manually. Note that overlappingObjects is only populated when a physics tick has passed.

Edit2: Also, you do addLocal() on a location you get, you should never do that. Always use the setters to set new values. (It doesn’t do anything in this case as you add a zero-vector anyway…?)

my intention when adding that local vector was simply to test something out. thanks for the heads up though; I’ll remove it now since it no longer serves any purpose.

I also took your advice and set the ghostControl to the ‘mario’ spatial (the player is a charactercontrol which handles collisions, and the mario spatial translates to the player spatial at the end of each update) and removed the setPhysicsLocation() line. This unfortunately produces the same results as before.

I am still pretty stuck, so I think I will do a bit more searching and perhaps take another look at the collideWith() function.

This definitely works, I tried it to create a more flexible character control in a prototype.

if that’s the case there must be a problem with the boundaries of the scene with which the ghostcontrol is colliding. I’m almost positive the ghostcontrol is checking for a collision with the scene’s boundingbox rather than the scene itself. The collision that is printed is with a rigidbody, which is probably referring to the landscape initialized in this block of code:



assetManager.registerLocator(“town.zip”, ZipLocator.class.getName());

sceneModel = assetManager.loadModel(“main.scene”);

sceneModel.setLocalScale(2f);



sceneShape = CollisionShapeFactory.createMeshShape((Node) sceneModel);

landscape = new RigidBodyControl(sceneShape, 0);

sceneModel.addControl(landscape);



So does the landscape only hold the bounding box of the scene? Otherwise it seems like collisions with the landscape should work just fine.

There is no bounds, there is only collision shapes. Use physicsSpace.enableDebug(assetManager) to see them.

thanks for the tip. the debug shows that the scene mesh is normal, but the ghostControl still acts as though testing for collisions with a big box with length (length of the scenemodel) by width (width of the scenemodel) by height (height of the scenemodel from the lowest point in the terrain to the highest point on the tallest house). here are a few screenshots to further clarify (note the console output for each screenshot): http://s908.photobucket.com/albums/ac289/risingstar64/JME3%20GhostControl%20collision%20issue%201/

  1. 2 collisions when on ground (should be 2)

    http://i908.photobucket.com/albums/ac289/risingstar64/JME3%20GhostControl%20collision%20issue%201/onground2collisions.png
  2. 1 collision when out of scene (should be 1)

    http://i908.photobucket.com/albums/ac289/risingstar64/JME3%20GhostControl%20collision%20issue%201/offedgeofsceneonly1collision.png
  3. 2 collisions when jumping (should be 1)

    http://i908.photobucket.com/albums/ac289/risingstar64/JME3%20GhostControl%20collision%20issue%201/mid-airstill2collisions.png
  4. 1 collision when jumping higher than tallest roof (should be 1)

    http://i908.photobucket.com/albums/ac289/risingstar64/JME3%20GhostControl%20collision%20issue%201/abovehighestroofinsceneonly1collision.png



    So as you can hopefully tell by these screenshots the ghostControl will collide with the scenemodel if it is anywhere between the top of the tallest roof and the lowest part of the terrain, even though the debug shows that the edges are all in the right places (certainly not in a big box around the scenemodel).

If I may ask a slightly off-topic question, how can one compile the sample applications, such as the ones provided on the ‘advanced physics’ page?

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:physics

I was interested in the sample labeled ‘TestWalkingChar.java’

Google Code Archive - Long-term storage for Google Code Project Hosting.

However, when I attempt to compile the code, many lines throw errors. For example; “cannot find symbol. symbol: class BombControl.”

I’m guessing I need to specify an external package which contains custom classes used by this sample, but I can’t seem to find any information on it.

Just create a new JmeTests project.

Oh, thanks. I can’t believe I missed something so simple.