0
\$\begingroup\$

TL;DR: Using a timestep method that calls update() multiple times per frame. After an event happens, need to add a wait time before it can happen again. What's the best way to do this so the wait times are always the same across all hardware?

Lets say that a bullet is spawned every time the player presses the mouse button. If the player holds the button down, a new bullet will spawn every frame (which is obviously WAY too many). The way I always got around this was to create a variable shotCoolDown and set it equal to some arbitrary number (usually 60). Then, in the update() function, I would subtract 1 from shotCoolDown every frame, and only allow the player to shoot if shotCoolDown was less than or equal to 0, and then after creating the bullet, set shotCoolDown back up to 60. At 60 FPS, this created a maximum of 1 bullet per second. This worked when calling update() once per frame. However, I'm now using a new timestep method from this article, which calls update() multiple (always different) times per frame. Because I don't know how many times update() will be called, I can no longer use my original shotCoolDown method.

I've also tried comparing the current time to the time at the mouse button press, and if the difference is more than 1000 ms (1 second), spawn a bullet. However, this doesn't exactly work. Since the computer's clock continues to tick while the game is paused, the player can simply shoot, pause the game and wait for the limit to pass, then unpause the game and shoot again.

Is there a better way to add these time limits? I know I can use timers, but some of my limits will be as small as 1/10th of a second; I'd rather not use a timer for such a small period of time.

\$\endgroup\$
2
  • \$\begingroup\$ Pause your timer when the game is paused :) \$\endgroup\$
    – Vaillancourt
    Aug 17, 2016 at 17:35
  • \$\begingroup\$ @AlexandreVaillancourt I'm using SDL_GetTicks(), which returns the amount of milliseconds since the program started. The value cannot be changed, and there's no way to stop it. \$\endgroup\$ Aug 17, 2016 at 17:54

2 Answers 2

0
\$\begingroup\$

First, stick with your shotCooldown variable but set it to (for example) 1000 ms.

Next, create a clock class. Your clock class only needs to store a tick count and have a method that when called, returns the time elapsed by subtracting the old tick count from the new tick count, and then updating the old tick count to be the new tick count. Call this method every frame/update.

By using the time elapsed, you can update your shotCooldown variable every frame/update.

Now, to get around the pause problem, you simply have to not update your cooldown variable while the game is paused. (Your clock will still be updating during the pause.) This works because the clock is not returning the absolute time that you're getting from SDL_GetTicks but the time delta instead.

Hope that helps

\$\endgroup\$
0
\$\begingroup\$

Generally speaking, for any graphics/game/physics library, there will be some way to get the amount of time that has elapsed since the last render/update call. That article that you mentioned looks like it's basically explaining how to implement this... but the overall idea is simple: just call SDL_GetTicks() with each iteration of whatever main application loop your engine is running, and calculate the difference between the current call and the value from the previous iteration. This value is what you should use to determine everything time-related: timer increments, animations steps, physics simulation steps, etc.

You don't want to rely on "number of times update/render has been called" because, as you alluded to in your question, that is prone to changes in FPS, which can vary wildly. If you want to only be able to fire "X bullets per second," you need the actual time difference since the last bullet was fired, not the frame count.

Hope this helps.

\$\endgroup\$

You must log in to answer this question.

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