StandardGame controlling framerate

Is there any simple way to force StandardGame to adhere to a maximum framerate - or execute logic at a fixed rate similar to FixedLogicrateGame?  The issue I'm having is that things like movement/turning speed are highly dependent on the fps - so when a large block of terrain or complex object goes out of the frustum, my turn speed shoots up massively.  (e.g. from 20fps to 80 or even 700fps)

you need to always multiply by the time per frame (parameter of the update method) to make your movements and rotation, framerate independent.

I'm not sure what you mean multiply by it - I'm already passing it to the ChaseCamera and ThirdPersonHandler update methods, but that doesn't seem to properly compensate for anything.



Here's a small example from some testing I was doing:


import com.jme.input.ChaseCamera;
import com.jmex.game.state.DebugGameState;
import com.jme.input.ThirdPersonHandler;

public class TestCamState extends DebugGameState
{
   ChaseCamera cc = null;
   ThirdPersonHandler tph = null;
   
   public TestCamState(ChaseCamera ChaseCam, ThirdPersonHandler ThirdPerson)
   {
      input.removeAllFromAttachedHandlers();
      input.removeAllActions();
      cc = ChaseCam;
      tph = ThirdPerson;
   }

   public void update(float tpf)
   {
      super.update(tpf);
      tph.update(tpf);
      tph.getCamera().update();
      cc.update(tpf);
   }
}



It seemed from the javadocs that the time value in the update methods would properly compensate - and when it didn't that was rather confusing.

What he means is, if you are trying to move forward do something like this:


float distance = tpf * multiplier;



Specify multiplier as the adjustable value for how fast you want to move and tpf would be a float representation of the time between the last call to update and this call to update.  This will allow you to adjust at the same rate no matter what the FPS is.  You should *ALWAYS* do it based on time or your game will be incredibly inconsistent and people with slow computers will hate you and people with really fast computers will hate you.  :P

Also, you can specify a framerate desired in StandardGame...I don't remember the setting off the top of my head though. However, the problem with it is that though it will keep it from going above, it cannot keep it from going below.

I understand the concept, I just wasn't seeing any methods to allow that type of control (it would be nice if update compensated automatically since you already feed it the time).



I'm guessing I have to call setActionSpeed with a speed ratio before I call update, for both my ChaseCamera and ThirdPersonHandler?  (Obviously I never set distances directly in this case).



I'm hoping that method is the right one, because I'm not seeing anything else to control these properly.

i didnt verify it but i think the existing ThirdPersonHandler should already take the tpf into account, if not it should be changed.

Yeah, I can see the code for performAction seems to factor in the speed and event time.  Theoretically it seems like it should be right - I'm not sure why I'm seeing different results.



I merely have a ChaseCamera that stays behind a box controlled by a ThirdPersonHandler. 



To test, I set this box near the edge of a few large pieces of geometry, in such a way that 180 degrees is filled with geometry and the other 180 is empty space.  Rotating through the geometry area takes somewhere around 2 seconds - the other 180 degrees takes half a second or less. (the framerates in this area shoot up to 700 or so, which is probably why it goes so fast)



That seems to indicate that it is not properly compensating for the framerate, but maybe there is something else I am missing.



I already posted the GameState class, here is the setup code for the objects in the main thread, in case this is somehow relevant to the issue (some of this code is verbatim from examples):



   Box b = new Box("box", new Vector3f(), 1,1,1);
   b.setModelBound(new BoundingBox());
   b.updateModelBound();
   m_character = new Node("char node");
   chaser = new ChaseCamera(game.getCamera(), m_character);
   tph = new ThirdPersonHandler(m_character, game.getCamera());
   tph.setActionSpeed(30f);
   tph.setCameraAlignedMovement(true);
   tph.setRotateOnly(true);
   tph.setLockBackwards(true);
   chaser.setMaxDistance(20);
   chaser.setMinDistance(15);
   chaser.setStayBehindTarget(true);
   chaser.getMouseLook().setEnabled(false);
   state = new TestCamState(chaser, tph);
   GameStateManager.getInstance().attachChild(state);
   KeyInput.get().removeListeners();
   MouseInput.get().removeListeners();



All of this is basically single-threaded, but since it's supposed to factor in the framerate I don't really see why that would matter.

It will be in GameSettings that you specify framerate stuff.

Yeah, it sort of works as a quick fix, but does anyone have any ideas about fixing the real problem?

clarify, what's the real problem?

The problem is that rotation/movement speed are tied to framerate at all.



As you said earlier - limiting the framerate will fix the high end, but doesn't do anything for the low end.  Even if I limit it to 60fps, if the game dips to 30fps then you only end up spinning half as fast. 





Here is what confuses me - let's take a look at ThirdPersonLeftAction:


    /**
     * <code>performAction</code> moves the node along it's positive direction
     * vector at a speed of movement speed * time. Where time is the time
     * between frames and 1 corresponds to 1 second.
     *
     * @see com.jme.input.action.InputActionInterface#performAction(InputActionEvent)
     */
    public void performAction(InputActionEvent event) {
        if (handler.getPermitter() != null
                && !handler.getPermitter().canBeMoved())
            return;
        handler.setTurning(true);
        Vector3f loc = handler.getTarget().getLocalTranslation();
        if (handler.isCameraAlignedMovement()) {
            rot.set(handler.getCamera().getLeft());
            rot.y = 0;
        } else {
            handler.getTarget().getLocalRotation().getRotationColumn(2, rot);
            rot.negateLocal();
        }
        rot.normalizeLocal();
        loc.addLocal(rot.multLocal((speed * event.getTime())));
    }



That seems to indicate that it is already taking into account when I pass the ThirdPersonHandler.update method the timeperframe

import com.jme.input.ChaseCamera;
import com.jmex.game.state.DebugGameState;
import com.jme.input.ThirdPersonHandler;

public class TestCamState extends DebugGameState
{
   ChaseCamera cc = null;
   ThirdPersonHandler tph = null;
   
   public TestCamState(ChaseCamera ChaseCam, ThirdPersonHandler ThirdPerson)
   {
      input.removeAllFromAttachedHandlers();
      input.removeAllActions();
      cc = ChaseCam;
      tph = ThirdPerson;
   }

   public void update(float tpf)
   {
      super.update(tpf);
      tph.update(tpf);
      tph.getCamera().update();
      cc.update(tpf);
   }
}



Frankly, I do not know if it is the ChaseCamera or the ThirdPersonHandler causing the problem, and I can't think of a good way to test it.  If you still do not understand I can take a video to illustrate the problem quite clearly.

I agree, its bugged. I use my own implementation as I didnt get anywhere before when I argued the point

sorry to necro an old post, but I am having trouble with this and I dont see a real solution on here.



I noticed this problem because when I had a networked game running, my brothers fast computer was moving his character around multiple times faster than my friends slow computer.



So, what would  be an honest way to solve this problem?



One way I was imagining (dont know if it is a real solution) would be to multiply all the movement vectors by (prefferredframerate/actual framerate)



so, if you want the player to move at Vector3f(12,0,0) and one player is going at 15 FPS while another is up at 60 FPS



during the period of 1 second they would both travel at 720 units per second?

because 60 FPS player would be moving at 12 units * 1 (scalar) * 60 frames while player 2 would be moving at 12 units * 4 (60 frames/ 15 actual) * 15 frames per second. yes?



however, how does this speak for someone who during 1 second goes from 15 frames per second to 60 frames? they would round up extra units per second?



I am confused how this all works. Is there a simple straightforward answer to all of this? Thanks (again sorry for the necro)

Well,…as already pointed out you have to take the timeperframe in acount that is given you by the update-method


public void update(float tpf){ box.getLocalTranslation().add(direction.mult(tpf));}



Something like this. With this you guaranty that in one second the box goes one unit of direction. The difference between framerates would be how fluent the movment would be.

let's say one computer has a framerate of 3fps = 0.33(time per frame) and the direction-vector would be (1,0,0). The box-node should move in one second one unit. That means the update call is accessed 3times and moves (0.33f,0,0) in the first call, again (0.33f,0,0) in second and again in third.

If another computer has 30fps = 0.033(tpf) it moves 30times (0.033f,0,0). After one second it moved the same distance with more calls. so the movment is much more fluent than the 3fps-action.

Hope that helps.