I am trying to write a litte bomberman clone. (See pic)
The player can move on the x and on the z axis.
And i only need the bounding boxes for "physics", so i wrote this controller.
Player is a simple subclass of Jme Node.
The velocity vector of the player is set at the input controller as (speed*time) in each direction pressed…
The player node has to have the ability to "slide" along the walls.
Saving the current position of the player to lastPos
Check, if the x part of the velocity is allowed and apply if so
Check, if the z part of the velocity is allowed and apply if so
Zeroing velocity of player for next update
The check is done in this way:
Multiply the velocity vector with a mask (eg velocity is (.5, 0,1) and we want the x-component multiply with (1,0,0))
Add it to localtranslation of playerNode
Test with collisiondetecting if player collides
If player collides, set back localTranslation
Now i have the following behavior:
If i press key up (to the north of the gameboard), the playerbox runs against the wall. It stops at the wall, shivering because of the setbacks of the localTranslation. After releasing the key, sometimes the box’ localTranslation is set into the wall, and the key input is the other way round (up is down, down is up) because the box is inside the wall and is always set back more than velocity…
If you stick into a wall, press two keys (eg down and right) and you will end up in the wall, with controlls reversed.
If you set “doSyslog” true, you’ll see this behaviour:
Moving Player - no collisons
player has collisions at current position (There is a check at the beginning, if there is a collison atthe current position without moving the player!)
I think this is a very common problem isnt it?
For example, in a “fast” shooter motion and its physics is done with boundingboxes - only for testing if a player hits with his bullet the triangle collision seems a useful approach, and normaly there will be also boundingboxes around the targets zones…
I tried your triangle collisions test from the other thread, and only changed the Sphere of the character to a Box -> not working anymore…
About bounding boxes, I'm not aware of a way to calculate any useful information, like normals, from bounding box collisions, other than that it happened.
The shivering (if its a problem) could be cured by not setting the player back farther than it was the previous location, you may have tried this. I beleive you should not need to update the collision tree after every movement.
For what it appears you are trying to do, bounding collisions should be sufficient if handled correctly. I think you took a good stab at it. Because the movement is really only along the x and z axis I think you could get away from needing to do extra math for sliding and such.
Is the problem here the fact that you sometimes end up inside the wall, and then it goes screwey?
It does act a little strange with a box. I havn't had a chance to look into why it wants to slide to the side, perhaps its due to inaccuracies from some math.
In my app I simulate gravity and ray cast downward to check if i'm "on the ground", my collision geom is actually hovering above ground a little, this allows me to go up steps and such but not walls. I assume my gravity/ray casting keeps my character (which is a box) from sliding in wierd directions, I just get side to side sliding. But I don't get penetration. I would like to spend more time on it, but can't for a few days.
This isn't a general collision type solution, because I don't know how to do one, but since you are doing bomberman, could you not just code a specific collision system for the game? This could work a lot better than using a general collision system (see last point below):
Store the player position in coordinates relative to grid, so 0,0 is where the player is centered in the corner square of the grid.
The player is considered to be "occupying" some squares - if their coordinate in both directions is an integer, then they are occupying one single square at that coordinate. If only one coordinate is an integer, then they are occupying two squares (e.g. at 0, 0.5, the player is occupying squares 0,0 and 0,1). If both coords are non-integers, then the player is occupying 4 squares.
Whenever the player moves in a direction (horizontally or vertically), you just check whether their new coordinates result in them "occupying" the same squares, if so, it is fine. If the set of occupied squares is different after the move, then the move is okay only if all the new squares are clear (not walls). (Side note here - if for some reason you want to have a movement by >= 1 square, then break it down into multiple movements, and run them separately. This should happen unless you have some really terrible frame rates, but it's easy to check for)
If the move is NOT okay, then you need to modify it. The simplest way is just to clip the movement so it stays in the old set of occupied squares. This will result in the player coming to a halt exactly lined up with the blocking wall(s). Clip the horizontal and vertical movements separately to allow for sliding along a wall when pressing diagonally)
To make the movement more responsive (and more like the original bomberman, IIRC) you can actually add a degree of "homing" ability to the movement. The aim here is that if the player is trying to move right into a clear square, with occupied squares above and below it, but they are not EXACTLY aligned with the clear square (vertically) then strictly you need to stop them moving right, and so they will just stick forever. However you CAN help them out without breaking collision, by moving them vertically (even if they are only pressing right on the joystick) so that they move towards lining up with the clear square, and hence they will not get completely stuck. I would do this by using the same concept of occupying squares as above - in this case you will be getting a different set of occupied squares after the movement to the right that the player requests, and you will reject the move because one of the squares (at least) will be blocked. But you notice that the player is moving right, and that only one of the new occupied squares is blocked - so in this case you add some vertical movement to line the player up with the clear square and away from the blocked square. When you do this, make sure you add code that checks for "overshoot" and clips it, so that if you would move the player past an integer coordinate while aligning them, you instead line them up exactly. This code is actually required to make it possible to move around the standard bomberman level design (otherwise it would be very very hard to walk along a corridor horizontally, and then switch to walking down a vertical corridor at a "T" or "+" junction, since you would be unlikely to exactly line yourself up horizontally to allow yourself to move down into a gap instead of slightly clipping the block on the left or right side).
I hope all that makes sense. I would write some pseudo-code but even as pseudo-code it would be quite complex I may have missed something, but the basic idea of working with the grid system instead of against it should help.