0
\$\begingroup\$

I'm trying to create a small 2D RPG-type engine using C++, SDL/OpenGL and Tiled. My little demo looks very similar to a Pokemon or Zelda game.

I was curious how to go about regulating FPS and how many times a certain event action is processed. For example, each iteration of my main loop handles events (such as if an arrow key is pressed, move the character up one tile, et cetera), then draws, and then updates then screen.

If I wanted the game to draw 24 frames every second, but only run the keyboard actions 6 times per second, how would I go about doing that? Is this even reasonable? Should I regulate everything to process 6 frames per second? Or would it make sense to create two threads, one for drawing and one for event handling?

This is my main game loop:

    while (!theGame->getQuit()) {
        fps.start();

        handleEvents();

        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    theGame->setQuit(true);
                    break;
                case SDL_KEYDOWN:
                    handleKeyDown(event.key.keysym.sym);
                case SDL_KEYUP:
                    handleKeyUp(event.key.keysym.sym);
                    break;
                default:
                    break;
            }
        }
        update();

        render();

        // FRAMES_PER_SECOND = 6 OR 24
        if (fps.get_ticks() < 1000 / FRAMES_PER_SECOND) {
            SDL_Delay((1000 / FRAMES_PER_SECOND) - fps.get_ticks());
        }
    }
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

To run things at different frequencies -- commonly used for reducing costly processing like AI so that it is intermittent -- maintain a counter that persists between game loop iterations, and on every frame, increment the counter by 1. Check if it has reached 4; if so, call your input function, and reset the counter to 0. It will then recount up to 4 and repeat this logic, till the game loop stops cycling.

The number is 4 because 24 / 6 == 4. I assume that your game loop runs at 24 fps: Set your main loop frequency to be that of whatever task you need to do most frequently, in your case, drawing; and from there you may divide up this, your highest frequency, into lower ones, using counters, for other tasks. No multithreading required.

EDIT To regulate how quickly your character moves, there'd be two ways:

  • For real-time / continuous motion, pick the velocity (say half a tile per second) and apply that based on the delta time, e.g. velocityTilesPerSec = 0.5; player.position.x += velocityTilesPerSec * deltaSec; deltaSec may be fixed or variable timestep, see Fix Your Timestep for an introduction to these.
  • For turn-based motion, ensure that you move your character in x and/or z one half-tile per key hit, e.g. player.position.x += velocityTilesPerSec

N.B. there is another concept involved here, i.e. how do you want to deliver the input? Continuous input (key / button held down with ongoing response) is normal for controlling characters using keyboard or gamepad. Single-hit input is the other approach: You hit a key but it doesn't create continuous response, it has a single-frame response; e.g. hitting F1 for help in-game.

\$\endgroup\$
3
  • \$\begingroup\$ Ahh, that makes sense! Such a simple concept, I don't know why I didn't think of that. Thanks. As far as regulating the input rate...I guess I want to regulate how fast these "event functions" run as opposed to the events themselves. I only want the character to be able to move half a tile at a time (so it can be in a tile, or in between two, but not something else). What should the movement function be dependent on so that all users have the same experience? \$\endgroup\$
    – ttay24
    Commented Jan 10, 2014 at 2:02
  • \$\begingroup\$ use a variable that holds the time the event last fired and wrap code in the event in an if statement, Example: if (eventLastFiredTime + waitTime < currentTime) { \\ run move code } \$\endgroup\$ Commented Jan 10, 2014 at 3:42
  • \$\begingroup\$ @ttay24 See my edit. Let me know if that's clear. \$\endgroup\$
    – Engineer
    Commented Jan 10, 2014 at 10:22
0
\$\begingroup\$

The following is an example solution that will provide a frame rate independent event fire:

const int SECONDS_TO_WAIT = 5
DateTime eventLastFiredTime = null;    

public void myEvent()
{
    if (eventLastFiredTime + SECONDS_TO_WAIT < DateTime.Now() 
        || eventLastFiredTime == null)
    {
        eventTimeLastFired = DateTime.Now();

        // movement code here
    } 

}

Please not that this code in not syntactically correct, it is just a basic C# style solution to give you an idea.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .