World boundary

Hello,



I’m thinking in some ways to implement world boundary, and I’ve come up with a solution that was to add an invisible Quad on the edges of the map. That was working pretty well, until I raised the movement speed of my units. Now they are moving at 20m/s and they are going through my boundaries. I’ve seen that BulletAppState has WorldMax and WorldMin, but setting them didn’t change much. After the end of the map, I’m not worried about what comes after, just like Age of Empires 1 (after the boundaries, there was literally nothing, just black).

black is a color, what does that have to do with physics? Just do something like if(objectLocation>worldSize){object.remove()};

Black was just to represent nothing.



I do not want to remove the object, I just want to limit how far can he go. Like an invisible wall.

Taken from the physics tutorial (https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:physics) :

setCcdMotionThreshold(0f) Sets the amount of motion that has to happen in one physics tick to trigger the continuous motion detection. This avoids the problem of fast objects moving through other objects. Set to zero to disable (default).

setCcdSweptSphereRadius(.5f) Bullet does not use the full collision shape for continuous collision detection, insteadit uses a "swept sphere" shape to approximate a motion. Only relevant for fast moving dynamic bodies. (?)


I think these functions should help you. Your moving so fast that between each tick you have already gone past the object and hence no collision is detected.

Are your objects quite small in comparison to the quad?
@shirkit said:
I do not want to remove the object, I just want to limit how far can he go. Like an invisible wall.

:roll: ..well then do if(objectLocation>worldSize){object.setLinearVeloicty(0)};
@wezrule said:
Taken from the physics tutorial (https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:physics) :


I think these functions should help you. Your moving so fast that between each tick you have already gone past the object and hence no collision is detected.

Are your objects quite small in comparison to the quad?


I'll take a look at those methods.

Yes, one is a character, a person about 2f radius and 4f high, moving at 10-20 m/s, and the quad is 513f lenght and 40f high.

@normen said:
:roll: ..well then do if(objectLocation>worldSize){object.setLinearVeloicty(0)};


Huuum @normen good idea, but can be also tricky. I could also check if the object is beyond the boundary and then move him back to the closest point inside the world.

How about the bullet plane shape for this?

In the past I have done world boundaries along the lines:



if (player.pos.x > worldBoundMin.x)

player.applyForce( new Vector3f((worldBoundMin.x-player.pos.x)*4,0,0) )



… which applies an ever strengthening push back into the world the further out the player gets, I set this worldBoundMin inside my real world boundary at around the distance of player’s maximum move speed (in this case, max move speed divided by 4 would probably be fine - 4 increases the effectiveness, making it a narrower area). In the Cove I used the above in a prePhysicsTick and rather than player.applyForce I influenced the player moveDirection - normally set via UI.

2 Likes
  • Setting BroadphaseType to Axis Sweep 3 (or 32) and setting WorldMin and WorldMax didn work. I'm pretty sure this doesn't work as I am imagining.

  • Setting Ccd's value (MotionThreshold and SweptSphereRadius) to random values between 0.00001 and 100000 didn't solved it either. My object is still going through the Quad.

  • I'm using CharacterControl for the object I want to keep on the boundary, therefore I cannot applyForces nor simply move the object back inside.


I followed @EmpirePhoenix 's idea, so this is what I did:

[java]int size = (int) (terrain.getTotalSize() * terrain.getLocalScale().x);

// 1
Quad quadMesh = new Quad(size, height);
Geometry boundry = new Geometry("Boundry1", quadMesh);

Material quadMat = ApplicationUtils.unshaded();
quadMat.setColor("Color", ColorRGBA.Green);

boundry.setMaterial(quadMat);
boundry.setLocalTranslation(new Vector3f(-size / 2, 0, -size / 2));

RigidBodyControl quadPhysics = new RigidBodyControl(new PlaneCollisionShape(new Plane(Vector3f.UNIT_Z, 0)), 0);
boundry.addControl(quadPhysics);

rootNode.attachChild(boundry);
getPhysicsSpace().add(quadPhysics);[/java]

The mesh being visible is only for debug prupouse, I'll hide it later.
This works perfect (for me), and there was no impact at my framerate.
I created 4 boundary, each for a side, and I rotate each boundary object for each side.

Thank you all for your experienced advices!

if you use a character then do the same to the walkdirection, add a vector back to the “playing field”.

@normen said:
if you use a character then do the same to the walkdirection, add a vector back to the "playing field".


I would then need to change also the View Direction, or could cause a really strange behaviour. But even changing that, changing View and Walk direction to another direction that wasn't request would seem really strange, that's why I said I prefer an invisible wall. Now I can just put a big object in the end of the map ^^
@shirkit said:
I would then need to change also the View Direction, or could cause a really strange behaviour. But even changing that, changing View and Walk direction to another direction that wasn't request would seem really strange, that's why I said I prefer an invisible wall. Now I can just put a big object in the end of the map ^^

Well it *is* an invisible wall if you just set the walkDirection.x to zero each frame if the player steps over the bottom line. Effectively the player will have normal controls but cannot walk past a certain line.
@normen said:
Well it *is* an invisible wall if you just set the walkDirection.x to zero each frame if the player steps over the bottom line. Effectively the player will have normal controls but cannot walk past a certain line.

The issue with that approach is that if there's a long frame, then the player may have significantly stepped over the line by the time you set walkDirection to zero.

And once I crossed that line, I could only allow the X value a different value from zero if the walk direction’s X is not towards the map boundary, only if it’s going for the inside map. That’s a good solution also, I’ll think if I’m going to change solutions!

The easiest way is just to make a wall, really. You create a CollisionShape but don’t create actual (renderable) geometry for it. Simple does it guys, no need to complicate things.

@Momoko_Fan said:
The issue with that approach is that if there's a long frame, then the player may have significantly stepped over the line by the time you set walkDirection to zero.

Thats why all games have a bit of "green" around the map. We are talking about world boundaries here so I suppose you need them in exceptions only (when the player decides to run over a mountain range thats the edge of the map or so).
@Momoko_Fan said:
The easiest way is just to make a wall, really. You create a CollisionShape but don't create actual (renderable) geometry for it. Simple does it guys, no need to complicate things.

If you make one big wall it ends up in every nearphase. At least use a plane shape then.

Yeah, exactly what I did. By constructing a plane, the behaviour is exactly as intended.