Skip to content

Commit 6e87a96

Browse files
committed
init
0 parents  commit 6e87a96

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__pycache__/

example/main.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import time
2+
import pygame
3+
from pygame.locals import *
4+
import timestep
5+
6+
pgvec2 = pygame.math.Vector2
7+
8+
pygame.init()
9+
10+
RESOLUTION = pygame.math.Vector2(1000, 600)
11+
screen = pygame.display.set_mode(RESOLUTION)
12+
pygame.display.set_caption("Timestep Test")
13+
SCREEN_WIDTH, SCREEN_HEIGHT = screen.get_size()
14+
15+
font = pygame.font.SysFont("Calibri", 40)
16+
start = False
17+
start_time = 0
18+
19+
20+
class Player(timestep.Character):
21+
def __init__(self, x: int, y: int) -> None:
22+
self.image = pygame.Surface((100, 100))
23+
self.image.fill("red")
24+
super().__init__(x, y, self.image)
25+
self.gravity = pgvec2(0, 0.1)
26+
27+
def update(self) -> None:
28+
super().update()
29+
30+
self.vel.y += self.gravity.y
31+
self.rect.y += round(self.vel.y)
32+
33+
34+
player = Player(500, 0)
35+
36+
37+
class game_loop(timestep.Timestep):
38+
def update(self):
39+
global game_running, start_time, start
40+
for event in pygame.event.get():
41+
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
42+
game_running = False
43+
if event.type == KEYDOWN:
44+
if event.key == K_SPACE and not start:
45+
start = True
46+
start_time = time.time()
47+
48+
if start:
49+
player.update()
50+
51+
def render(self, alpha):
52+
global game_running
53+
54+
screen.fill((0, 0, 0))
55+
56+
player.draw(screen, alpha)
57+
58+
if player.rect.y >= SCREEN_HEIGHT:
59+
finish = time.time() - start_time
60+
print(finish)
61+
game_running = False
62+
63+
pygame.display.flip()
64+
65+
66+
game = game_loop(1/60)
67+
68+
game_running = True
69+
while game_running:
70+
game.run_game()
71+
pygame.quit()

timestep.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""Timestep is a module based on Pygame that implements a decoupled update and rendering to make any code framerate independant. Based on https://gafferongames.com/post/fix_your_timestep/#the-final-touch. Created so you never have to worry about multiplying by deltatime again."""
2+
3+
import pygame
4+
import time
5+
6+
7+
class Character:
8+
"""Base class for any sprites or objects"""
9+
10+
def __init__(self, x: int, y: int, image: pygame.Surface) -> None:
11+
self.image = image
12+
self.rect = self.image.get_rect()
13+
self.rect.topleft = x, y
14+
self.vel = pygame.math.Vector2(0, 0)
15+
self.prev_pos = pygame.math.Vector2(self.rect.topleft)
16+
17+
def update(self) -> None:
18+
"""Update """
19+
self.prev_pos = self.__get_rect_pos()
20+
21+
def draw(self, surface: pygame.Surface, alpha: float) -> None:
22+
pos = self.prev_pos.lerp(self.__get_rect_pos(), alpha)
23+
surface.blit(self.image, pos)
24+
25+
def __get_rect_pos(self) -> pygame.math.Vector2:
26+
"""Return the position of the Charater's rect as a Vec2"""
27+
return pygame.math.Vector2(self.rect.topleft)
28+
29+
30+
class Timestep:
31+
"""Class that does all the calculations to make the game framerate independant"""
32+
33+
def __init__(self, step: float) -> None:
34+
self.__step = step
35+
self.__accumulator = 0
36+
self.__last_time = time.time()
37+
38+
def __calc_dt(self) -> float:
39+
now = time.time()
40+
dt = now - self.__last_time
41+
self.__last_time = now
42+
return dt
43+
44+
def update(self) -> None:
45+
"""Override this function with event loop and movement"""
46+
pass
47+
48+
def render(self, alpha: float) -> None:
49+
"""Override this function with blits and drawing of sprites"""
50+
pass
51+
52+
def run_game(self) -> None:
53+
"""Updates and renders the game framerate independantly. Should only be called within a while loop."""
54+
dt = self.__calc_dt()
55+
self.__accumulator += dt
56+
57+
while self.__accumulator >= self.__step:
58+
self.update()
59+
60+
self.__accumulator -= self.__step
61+
62+
alpha = self.__accumulator / self.__step
63+
64+
self.render(alpha)

0 commit comments

Comments
 (0)