[Python] Pygame Timer Not Resetting on Restart [duplicate]

Discussão em 'Python' iniciado por Stack, Março 5, 2025.

  1. Stack

    Stack Membro Participativo

    This is my first post, so I'm sorry if I do anything wrong. I'm developing a car game in Pygame (inspired by @javidx9 on YouTube), and I've run into an issue with the game timer. When the player reaches the end of the track, the timer (stored in self.elapsed_time) stops as expected. However, when the game restarts (by pressing space on the "game over" screen), the timer continues from the original program start time instead of resetting to 0.

    In my restart() method, I set self.elapsed_time to 0, but the timer shows the overall program run time rather than restarting from 0. I have also looked in simular threads like this from stack overflow and this from reddir.

    Thank you!

    import pygame
    import math

    class game:
    def __init__(self):
    pygame.init()

    # Screen settings
    self.width, self.height = 160, 100
    self.scale = 6
    self.scaled_width, self.scaled_height = self.width * self.scale, self.height * self.scale
    self.screen = pygame.display.set_mode((self.scaled_width, self.scaled_height))
    self.surface = pygame.Surface((self.width, self.height))
    pygame.display.set_caption("Bilspel")
    pygame.display.set_icon(pygame.image.load('icon.png'))

    # Track
    self.track = [
    (0, 100)
    ]

    self.restart()

    self.run()

    def restart(self):
    # Game state
    self.running = True
    self.clock = pygame.time.Clock()
    self.elapsed_time = 0

    # Car properties
    self.car_position = 0 # -1 = left, 0 = center, 1 = right
    self.speed = 0
    self.car_direction = 0
    self.car_shape = []

    # Track properties
    self.curvature = 0
    self.track_curvature = 0
    self.player_curvature = 0
    self.distance = 0
    self.track_distance = sum(section[1] for section in self.track)

    # Finish line
    self.finish_line_top = -1
    self.finish_line_bottom = -1
    self.finish_line_offset = int(sum(value[1] for value in self.track) - self.height / 2)

    # Controls
    self.up_pressed = False
    self.down_pressed = False
    self.left_pressed = False
    self.right_pressed = False
    self.shift_pressed = False
    self.space_pressed = False

    # Fading at the end of a game
    self.fade_alpha = 0 # Start with no fade

    # Text
    self.font = pygame.font.Font("PxPlus_IBM_CGA.ttf", 8)

    def run(self):
    while self.running:
    self.update()
    self.draw()

    # Scale and display the game surface
    self.screen.blit(pygame.transform.scale(self.surface, (self.scaled_width, self.scaled_height)), (0, 0))
    pygame.display.flip()

    # Maintain 60 FPS and update time
    self.clock.tick(60)
    self.update_elapsed_time()

    pygame.quit()

    def update(self):
    # The end of a game
    if self.distance > self.track_distance:
    self.fade_alpha += 0.85

    if self.space_pressed:
    self.restart()


    # Reset car direction
    self.car_direction = 0

    # Finish line
    self.finish_line_top = self.distance - self.finish_line_offset - 10 # Edit 10 to change the thickness
    self.finish_line_bottom = self.distance - self.finish_line_offset

    # Handle events
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    self.running = False
    elif event.type == pygame.KEYDOWN:
    if event.key == pygame.K_UP:
    self.up_pressed = True
    elif event.key == pygame.K_DOWN:
    self.down_pressed = True
    elif event.key == pygame.K_LEFT:
    self.left_pressed = True
    elif event.key == pygame.K_RIGHT:
    self.right_pressed = True
    elif event.key == pygame.K_LSHIFT:
    self.shift_pressed = True
    elif event.key == pygame.K_SPACE:
    self.space_pressed = True

    elif event.type == pygame.KEYUP:
    if event.key == pygame.K_UP:
    self.up_pressed = False
    elif event.key == pygame.K_DOWN:
    self.down_pressed = True
    elif event.key == pygame.K_LEFT:
    self.left_pressed = False
    elif event.key == pygame.K_RIGHT:
    self.right_pressed = False
    elif event.key == pygame.K_LSHIFT:
    self.shift_pressed = False
    elif event.key == pygame.K_SPACE:
    self.space_pressed = False

    # Adjust speed
    if self.up_pressed:
    self.speed += 0.05
    elif self.down_pressed:
    self.speed -= 0.025
    self.speed *= 0.8
    else:
    self.speed *= 0.975

    if self.speed < 0:
    self.speed = 0
    elif self.speed > 8:
    self.speed = 8

    # Handle turning
    if self.speed > 0.1:
    if self.left_pressed:
    if self.shift_pressed:
    self.player_curvature -= 0.0375
    self.car_direction = -2
    if self.speed > 2:
    self.speed *= 0.99
    else:
    self.player_curvature -= 0.025
    self.car_direction = -1

    if self.right_pressed:
    if self.shift_pressed:
    self.player_curvature += 0.0375
    self.car_direction = 2
    if self.speed > 2:
    self.speed *= 0.99
    else:
    self.player_curvature += 0.025
    self.car_direction += 1

    # Reduce speed if car is on the grass
    if abs(self.car_position) > 0.5:
    self.speed *= 0.9

    self.distance += self.speed

    # Stop track updates if speed is zero
    if self.speed == 0:
    return

    offset, n_track_section = 0, 0
    while n_track_section < len(self.track) and offset <= self.distance:
    offset += self.track[n_track_section][1]
    n_track_section += 1

    self.target_curvature = self.track[n_track_section - 1][0] if n_track_section > 0 else 0.0

    # Smooth transition using linear interpolation (lerp)
    self.curvature = self.lerp(self.curvature, self.target_curvature, 0.01 * self.speed)

    def lerp(self, start, end, t):
    return start + (end - start) * t

    def update_elapsed_time(self):
    elapsed_ms = pygame.time.get_ticks()

    # Only update the the time when the track is not finished
    if self.distance < self.track_distance:
    self.elapsed_time = elapsed_ms / 1000

    self.track_curvature += self.curvature * self.speed * 0.05

    def draw(self):
    self.draw_sky()
    self.draw_mountains()
    self.draw_road()
    self.draw_car()
    self.draw_text()

    # Create a semi-transparent black surface to overlay
    if self.fade_alpha > 0:
    overlay = pygame.Surface(self.surface.get_size())
    overlay.fill((0, 0, 0))
    overlay.set_alpha(self.fade_alpha)
    self.surface.blit(overlay, (0, 0))
    self.draw_text()

    text = self.font.render("Press space", True, (255, 255, 255))
    self.surface.blit(text, (4.5, (self.height / 2 - 5)))
    text = self.font.render("to continue", True, (255, 255, 255))
    self.surface.blit(text, (8.5, (self.height / 2 + 5)))

    def draw_sky(self):
    """Draws the gradient sky."""
    for y in range(self.height // 2):
    if y < self.height // 12:
    color = (0, 0, 128)
    elif y < self.height * 3 // 12:
    color = (0, 0, 192)
    else:
    color = (0, 0, 255)

    for x in range(self.width):
    self.surface.set_at((x, y), color)

    def draw_mountains(self):
    """Draws background and foreground mountains."""
    for x in range(self.width):
    # Background mountains
    height_bg = int(abs(math.sin(x * 0.025 + self.track_curvature)) * (self.height // 2) * 0.2)
    for y in range(self.height // 2 - height_bg, self.height // 2):
    self.surface.set_at((x, y), (64, 0, 0))

    # Foreground mountains
    height_fg = int(abs(math.sin(x * 0.015 + self.track_curvature * 2)) * (self.height // 2) * 0.25)
    for y in range(self.height // 2 - height_fg, self.height // 2):
    self.surface.set_at((x, y), (128, 64, 0))

    def draw_road(self):
    """Draws the road and surrounding elements."""
    for y in range(self.height // 2):
    perspective = y / (self.height / 2)
    middle_point = 0.5 + self.curvature * (1 - perspective) ** 3
    road_width = 0.05 + perspective * 0.4
    clip_width = road_width * 0.3

    n_grass = int((middle_point - road_width - clip_width) * self.width)
    n_clip = int((middle_point - road_width) * self.width)

    # Layer 1
    n_finish_line_layer1 = int((middle_point - road_width * 7 / 7) * self.width)
    n_finish_line_layer1_right = int((middle_point + road_width * 7 / 7) * self.width)
    # Layer 2
    n_finish_line_layer2 = int((middle_point - road_width * 5 / 7) * self.width)
    n_finish_line_layer2_right = int((middle_point + road_width * 5 / 7) * self.width)
    # Layer 3
    n_finish_line_layer3 = int((middle_point - road_width * 3 / 7) * self.width)
    n_finish_line_layer3_right = int((middle_point + road_width * 3 / 7) * self.width)
    # Layer 4
    n_finish_line_layer4 = int((middle_point - road_width * 1 / 7) * self.width)
    n_finish_line_layer4_right = int((middle_point + road_width * 1 / 7) * self.width)

    n_clip_right = 2 * int(middle_point * self.width) - n_clip
    n_grass_right = 2 * int(middle_point * self.width) - n_grass

    n_row = self.height // 2 + y

    grass_color = (0, 255, 0) if math.sin(20 * (1 - perspective) ** 3 + self.distance * 0.1) > 0 else (0, 128, 0)
    clip_color = (255, 0, 0) if math.sin(80 * (1 - perspective) ** 3 + self.distance * 0.1) > 0 else (255, 255, 255)

    # Layer 1 and 3
    finish_line_odd_layer_color = (255, 255, 255) if math.sin(70 * (1 - perspective) ** 3 + self.distance * 0.1) > 0 else (0, 0, 0)
    # Layer 2 and 4
    finish_line_even_layer_color = (0, 0, 0) if math.sin(70 * (1 - perspective) ** 3 + self.distance * 0.1) > 0 else (255, 255, 255)

    for x in range(self.width):
    if x < n_grass:
    color = grass_color
    elif x >= n_grass_right:
    color = grass_color
    elif x < n_clip:
    color = clip_color
    elif x >= n_clip_right:
    color = clip_color

    elif y > self.finish_line_top and y < self.finish_line_bottom:
    # Layer 4
    if n_finish_line_layer4 <= x <= n_finish_line_layer4_right:
    color = finish_line_even_layer_color
    # Layer 3
    elif n_finish_line_layer3 <= x <= n_finish_line_layer3_right:
    color = finish_line_odd_layer_color
    # Layer 2
    elif n_finish_line_layer2 <= x <= n_finish_line_layer2_right:
    color = finish_line_even_layer_color
    # Layer 1
    elif n_finish_line_layer1 <= x <= n_finish_line_layer1_right:
    color = finish_line_odd_layer_color

    else:
    color = (128, 128, 128) # Grey for road
    self.surface.set_at((x, n_row), color)

    def draw_text(self):
    """Draws the text"""
    text = self.font.render(f"Time: {self.elapsed_time:.2f} s", True, (255, 255, 255))
    self.surface.blit(text, (4, 4))

    def draw_car(self):
    if self.car_direction == -2:
    self.car_shape = [
    "1"
    ]
    elif self.car_direction == -1:
    self.car_shape = [
    "1"
    ]
    elif self.car_direction == 1:
    self.car_shape = [
    "1"
    ]
    elif self.car_direction == 2:
    self.car_shape = [
    "1"
    ]
    else:
    self.car_shape = [
    "1"
    ]

    self.car_position = self.player_curvature - self.track_curvature

    car_x = int((self.car_position * (self.width // 2)) + 30)
    car_y = self.height - 34 - 9

    for row_index, row in enumerate(self.car_shape):
    for col_index, pixel in enumerate(row):
    if pixel == '1':
    self.surface.set_at((car_x + col_index, car_y + row_index), (0, 0, 0)) # Black for '1'
    elif pixel == '2':
    self.surface.set_at((car_x + col_index, car_y + row_index), (192, 0, 0)) # Red for '2'

    if __name__ == "__main__":
    game_instance = game()

    Continue reading...

Compartilhe esta Página