Controllable, rolling ball with JME Physics 2

Hi there!



I am using JME Physics 2 and am trying to use a sphere as the player. The sphere shall be controllable via wsad and should roll through the world. At the moment I am using the KeyNode<…>Actions to move it, but they do not make the ball really roll but just change its translation.



I experimented with new Actions I wrote which apply a force to the sphere which worked well for forward and backward movement. The tricky part seems to be the steering to the left and right. If I change the rotation with the appropriate existing KeyNodeActions, the ball rotates but doesn't chang its  course. If I accellerate it again afterwards, it also doesn't change its course.



What I want is a change of course on the flight: The ball rolls forward, I press d to steer right and now the ball drifts to the right.



Everything I tried out - from applying a new, updated force when striking the key up to update the force at every single call of the update-function of my gameloop - failed so far.



The last thing I tried was this (modified version of the KeyNodeLeftAction):




   public void performAction(InputActionEvent evt) {
        if (lockAxis == null) {
            node.getLocalRotation().getRotationColumn(1, tempVa);
            tempVa.normalizeLocal();
            incr.fromAngleNormalAxis(speed * evt.getTime(), tempVa);
        } else {
            incr.fromAngleNormalAxis(speed * evt.getTime(), lockAxis);
        }
        node.getLocalRotation().fromRotationMatrix(
                incr.mult(node.getLocalRotation().toRotationMatrix(tempMa),
                        tempMb));
        node.getLocalRotation().normalize();
           

        Vector3f force = new Vector3f();
        node.getForce(force);
        force = force.addLocal(node.getLocalRotation().getRotationColumn(1).multLocal(speed));   
       
    }



So, simply apply a rotation as already known and then udpate the force of the ball (node here) by adding the new direction (I guess). The thing is that I don't really understand how this whole force-thing works. I also tried to replace the force, but that brings up some other problems, too (keeping the strength of the existing force is one of them).

Has anyone experience with that and can help me?

There is a really really old thread in the user showcase of someone who made a little marble madness game.

Maybe you can get some ideas from the discussion.



http://www.jmonkeyengine.com/jmeforum/index.php?topic=1104.0



I would simply try to add force forward is you press w, s backward, a left, d right.



Or you could rotate the Ball (the physics node) and always apply force into the direction the ball is heading you get the direction with ball.getLocalRotation().getRotationColumn(2).



Use a FrictionCallback, to get rid of the 'old' forces over time.

The game I'm developing now does something very similar, so I may be able to help.  There are many ways to do this depending on the exact effect you are looking to achieve.  In my game the character is actually a person and so I tried to make the sphere behave as much like a person as possible.  (The sphere is invisible and person graphics are rendered inside.)



So here are a few general pointers:

  • Don't directly change the translation or rotation of the physics sphere.  In general this can cause problems with physics objects…  only use forces.
  • Don't worry about the rotation of the sphere, just apply forces in the direction you want to go.  (For my game I use a 3rd person camera and "turning" just moves the camera and rotates the graphics – not the physics sphere.)
  • Apply forces in the physics update loop, not the input update loop.  These are not synced so you can get multiple input loops for each physics loop.
  • Forces are cleared every physics loop so you'll need to reapply them each time though.



    To make the sphere move like a person:
  • Use a FrictionCallback as Core-Dump suggests to slow the sphere to a stop.  Only apply this when key is not being pressed.  In my game the character can jump so I also only apply the friction when he's in contact with the ground.
  • Reduce the magnitude of the controlling force vector based on the component of the sphere's velocity in the direction of that vector.  (This is a bit confusing – I'll try to get you some code.)  Basically you want to prevent the player from being able to accelerate to infinite speed.  This effectively caps the speed the player can achieve via the controls, but doesn't limit the speed as the result of external influences.
  • Don't be afraid to use a very strong force.  Humans generally accelerate to their top speed pretty quickly and the velocity based force cap should keep things under control.



    I hope this helps some.  I'll try to get you some code and video shortly.

Much thanks to both of you!



Quite a lot of information.  :smiley:



* Reduce the magnitude of the controlling force vector based on the component of the sphere's velocity in the direction of that vector.  (This is a bit confusing -- I'll try to get you some code.)  Basically you want to prevent the player from being able to accelerate to infinite speed.  This effectively caps the speed the player can achieve via the controls, but doesn't limit the speed as the result of external influences.


If you'll find some code, I would be very happy ;)

Though done in jME 1.0 and jME-Physics 1.0 Roll-A-Rama may be what you’re looking for:



http://forum.captiveimagination.com/index.php/topic,85.0.html



You can find the source code there.

Hey darkfrog,



thanks for the link, but I think your resources are down. I get a 404 on every link I click on including the attached .zip-file.

Thanks to both of you! My controllable ball works fine now!



Now another question (if allowed): My player shall switch his form from ball to human. So I decided to do what you suggested, SockFullOfPennies. I created an invisible Sphere for the physics and put a model (the ninja from pyro) into it for display. The human is able to jump, what the ball isn't and now I get a problem with the FrictionCallback:


* Use a FrictionCallback as Core-Dump suggests to slow the sphere to a stop.  Only apply this when key is not being pressed.  In my game the character can jump so I also only apply the friction when he's in contact with the ground.


My question: How to tell the FrictionCallback to stop kill the forces?? I see a before- and an afterStep-method, I'm sure I have to do it in there, but I don't find any method to temporarily disable it or to remove my player from the Callback.

Do you have any suggestions?

The actual friction code is fairly small so you could just use it instead of the callback:


public boolean call( float time ) {
            DynamicPhysicsNode dpn = node.get();
            if ( dpn == null ) {
                return false;
            }

            if ( forceFriction != 0.0f ) {
                dpn.getLinearVelocity( store );
                float change = forceFriction * time;
                applyFriction( store, change );
                dpn.setLinearVelocity( store );
            }
            if ( angularFriction != 0.0f ) {
                dpn.getAngularVelocity( store );
                float change = angularFriction * time;
                applyFriction( store, change );
                dpn.setAngularVelocity( store );
            }

            return true;
        }

        private void applyFriction( Vector3f velocity, float change ) {
            float newLength = velocity.length() - change;
            if ( newLength < 0 ) {
                velocity.set( 0, 0, 0 );
            } else {
                velocity.normalizeLocal().multLocal( newLength );
            }
        }

Thanks for the hint!



In the meantime I managed to turn off the frictionCallback simply by using the Float-Class to set the friction and set its values to 0f when my player doesn't touch the ground.



I also wrote my own frictionCallBack witch had an on/off-switch but that caused some trouble so I dropped that idea.



The other one works quite nice.





Okay, a little EDIT:

The Float-Class-Thing didn't work, I just thought it worked. I now modified the frictionCallback-Class so I can set the values of the forceFriction and the angularFriction in there.

I am also doing some ball rolling game for fun, so it would be really cool to see some source code from Roll-A-Rama project --> I am also getting 404 error with attachment on forum.captiveimagination.com.

I would be really grateful if someone could post the code here.

Thanks.