nsccs / pygames

Collection of games created with pygame.
4 stars 4 forks source link

Use Delta Time Instead of Approximate Time Per Frame #18

Open 1deolson opened 10 months ago

1deolson commented 10 months ago

Currently the game uses approximate time per frame as a simple way to make it work at multiple frame rates. A better practice is to use the actual time between frames, which is delta time (change in time). I already implemented dt in the Game class, it's just not used.

I think this is what needs to be done:

At the moment if the game is running at a lower frame rate than it's supposed to, the change in time will be greater than the approximate predicted change in time defined in the constant APPROX_TIME_PER_FRAME. This should result in the ship going slower than it's supposed to.

jaredscarr commented 10 months ago

This is for asteroids right? Do you think that it would be a good time to add a config file for global settings? or is this a utility class where the frame rate is calculated each time? Or something else?

1deolson commented 10 months ago

Yes, I forgot to say this is for asteroids. A config file could be convenient for tuning the game. Currently there are some constants at the top of the program, but not everything can be controlled, so more could be added. I don't think a utility class needs to be added. Delta time is already implemented in Game.__init__ in main.py, just not used:

def __init__(self, title: str = "NSCCSC Asteroid Clone") -> None:
    ...
    self.dt = 0  # delta time
    self.clock = pygame.time.Clock()
    ...

In Game.run:

def run(self) -> None:
    ...
    while True:
        ...
        # use delta time, which is the amount of time that has passed between each frame.
        # this allows behaviour like velocity to be based on actual time passed instead of the amount of frames.
        seconds_per_millisecond = 1000
        self.dt = (
            self.clock.tick(FRAME_RATE) / seconds_per_millisecond
        )  # NOTE: not currently used

Here's an example of how it could be used in Game.handle_input:

def handle_input(self):
    ...
    if keys[pygame.K_w]:
        # multiply by dt to make the increase based on the amount of time that has passed between frames
        self.ship.add_forward_velocity(VELOCITY_INCREASE_ON_KEYPRESS * self.dt)
    ...