Need Help With Applying Velocities to Character Control!

In my project, I’m trying to recreate the code that happens in the update loop from the following youtube video: https://youtu.be/7KiK0Aqtmzc?t=605

Specifically, I wanted to be able to set the velocity of my Character Control (called player1), so that it accelerates upwards breifly and then falls back down in a ‘jumping fashion’

CapsuleCollisionShape capsuleShape1 = new CapsuleCollisionShape(1.5f,6f,1f);
player1 = new CharacterControl(capsuleShape1, 1f);
player1.setGravity(new Vectorf3f( 0f,-9.81f,0f ));

bulletAppState.getPhysicsSpace().add(player1);

I tried to write the code so that it would apply this new jumping velocity to what ever the existing velocity was on the character control, so that you could walk and jump simultaneously.

So in my attempt to do this, in my ActionListener I have the following code:

if (name.equals("Space") && isPressed) {
    player1.setLinearVelocity( player1.getLinearVelocity(new Vector3f()).addLocal(new Vector3f(0f,5f,0f)) );
}

My issue is, that the code doesn’t make the character control accelerate upwards, for some strange reason it travels along the z axis.

Have I made an obvious calculation error here, or is it something else?

Not related to your question but you could:

  1. Use BetterCharacterControl which offers .setWalkDirection or even better use jump()
  2. Probably CharacterControl has another way of applying velocity instead of just overwriting physics values (probably it overwrites what you try to do)

Either way that code is bad because you’d at least do 9.81f * tpf * a, so for a = 1 you’d have 1 g jump force (which only counters gravity, so a > 1).

I had already tried BetterCharacterControl, but I wasn’t able to use .setPhysicsLocation(); beacuse it was protected, is there a way to acheive the same result as .setPhysicsLocation(); while using BetterCharacterControl?

Yes, it’s called warp() but it feels like bypassing the regular physics systems most of the time, so what are you trying to do?

I was also trying to avoid using jump() altogether, because I wanted to have different forces applied to the player1 depending on if it was travelling up or down. (Like in mario 64, where mario takes 18 frames to reach the apex of his jump, but only 10 to fall again.)

I would only need to use warp() to move my player to a specific location when the appstate is enabled. It would have no effect in the jumping mechanics

I don’t know if that doesn’t happen automatically: The physics Shape should be placed where the node was at addition time.
If you plan to use your own jump() extend either CharacterControl or BCC

If it were me, I’d apply an impulse to the physics control, not force a velocity.

How do you use impulses, because I can’t see it as a method for BetterCharacterControl

You get the physicscontrol. But I mean… the jump method does that already. You’re trying to fight against the physics system. The only way to it internally is set the gravity lower before you jump and higher as you fall. It’s a weird setup.

In the real world it would take roughly the same time to reach the peak of your jump as it would to hit the floor from the peak. Like a parabola. The only way to alter the physics simulation is to change the parameters for which it calculates. Otherwise you’re gonna have a really hard time with jittering and other unwanted side effects.

Change the gravity.

I think I might have to make a custom BetterCharacterControl, and implement my own jump(); where the gravity/mass changes after the apex.

Which physics library are you using: jme3-bullet or jme3-jbullet?

Actually after a bit of thought, in order to retain behaviours it would probably be best to invoke a slight negative impulse at the peak of your jump instead of gravity.

If you change gravity or mass to get it to drop faster, your character would behave differently on the downward movement if something hit it or it collided with something, but if you just applied a small impulse downward everything would remain the same whilst still getting the effect you need. With the benefit of not having to change values when you’re going up and down hitting the floor again. Makes things a lot less complicated.

From recent research, I know way more about this topic than I probably should… but a lot depends on what kind of jump you want in the end. (I even implemented several types in the sio2 bullet character demo.)

Setting the upward velocity to a jump velocity is the typical approach. You only need to kill the velocity at the “top” if you want the effect of ‘early termination’ in the case of the player stops pressing the jump.

Lots of articles on this related to 2D jumps which translate (mostly) directly. From my own recent research:

http://info.sonicretro.org/SPG:Jumping
http://info.sonicretro.org/SPG:Solid_Tiles#Jumping_At_Angles

It would be good to figure out why an up velocity is not moving your character up. For a standard rigid body it should work.

1 Like

I am using jme3-bullet

1 Like

I believe that the following code in the update(); should allow me to acheive what I need.

if (player1.getVelocity().y < 0f) {
            //falling
        } else {
            //not falling
        }

I’m still not entirely sure how to apply an impulse, as BetterCharacterControl doesn’t have it as a method since it has a fixed up axis.

https://javadoc.jmonkeyengine.org/com/jme3/bullet/control/BetterCharacterControl.html

Sorry if I’m just missing something really easy here but I would assume I need to build my own character control and include this functionality.

For BetterCharacterControl look into it’s controlUpdate Method, it dampens all forces and also applies a jump impulse there, you want to change that to apply a force over a given amount of time and after that cancel the force or even use a counter force

Thank you all for your patience! :slight_smile:

I managed to solve the problem as follows:

  1. I cloned the com.jme3.bullet.control package, and made a copy of the BetterCharacterControl class, which I renamed to CustomCharacterControl
  2. I then changed the protected PhysicsRigidBody myRigidBody; declaration to say public
  3. I then made my own method within the class to allow my appstates to have access to the rigid body:
public PhysicsRigidBody getRigidBody() {        
        return myRigidBody;
    }
  1. Finally, in my appstate update(); loop, I ran the following, which applies an impulse to whenever player1 is falling, which achieves my initial needs:
if (player1.getVelocity().y < 0f) {
            player1.getRigidBody().applyImpulse(new Vector3f(0f,-0.6f,0f),Vector3f.ZERO);
        }

Note that the best solution would be to move that code into the CustomCharacterControl.
Btw usually you’d only have to apply an impulse once and applying it multiple times (like in your code) would lead to even more speed (usually you’d also have to multiple that with tpf to have it framerate independant at least).

This works in that case, because BCC is removing all forces every frame and applies the walk force again, that is also the spot where you’d have to add your applyImpulse :slight_smile: