python - 如何解决退出暂停屏幕后时钟显示不正确的问题?

标签 python pygame

我在 pygame 中创建了迷宫游戏(这是我的第一个)。然而,当我进入然后离开暂停屏幕时,时钟停留在 00:00:-15。更奇怪的是,如果我再次进入并离开暂停屏幕,代码就会按照我预期的方式工作(在进入暂停视频之前继续时钟的位置。

这是生成时钟的代码:

# creates the string that displays time
def get_time(hours,minutes,seconds):
    if len(str(hours)) > 1:
        a = str(hours)
    else:
        a = "0" + str(hours)

    if len(str(minutes)) > 1:
        b = str(minutes)
    else:
        b = "0" + str(minutes)

    if len(str(seconds)) > 1:
        c = str(seconds)
    else:
        c = "0" + str(seconds)

    return a + ":" + b + ":" + c

# creates the time counter
def draw_time(start_time,pause_time):
    hours = 0
    minutes = 0
    seconds = 0
    current_time = time.time() - pause_time - start_time
    if current_time > 3600:
        while True:
            if current_time - 3600 > 0:
                hours += 1
                current_time -= 3600
            else:
                while True:
                    if current_time - 60 > 0:
                        minutes += 1
                        current_time -= 60
                    else:
                        seconds += int(current_time)
                        break
                break

    else:
        while True:
            if current_time - 60 > 0:
                minutes += 1
                current_time -= 60
            else:
                seconds += int(current_time)
                break

    return [font1.render(get_time(hours, minutes, seconds), True, (0, 0, 0), (255, 255, 255)), get_time(hours, minutes, seconds)]

这会显示它:

screen.blit(text[0], (700, 15))

这将激活/停用暂停屏幕:

for event in pygame.event.get():

    if event.type == pygame.QUIT:
        done = True
        running = False

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE or event.key == pygame.K_p:
            if pause:
                pause = False
                pause_time = time.time() - pause_time_start
            else:
                pause = True
                pause_time_start = time.time() - game_time - start

        if event.key == pygame.K_RETURN:
            done = True

这是整个代码:

import pygame
import random
import time

pygame.init()
# all fonts used
font1 = pygame.font.SysFont("comicsansms", 49, True)
font2 = pygame.font.SysFont("comicsansms", 150, True)
font3 = pygame.font.SysFont("comicsansms", 28, True)

# creates the string that displays time
def get_time(hours,minutes,seconds):
    if len(str(hours)) > 1:
        a = str(hours)
    else:
        a = "0" + str(hours)

    if len(str(minutes)) > 1:
        b = str(minutes)
    else:
        b = "0" + str(minutes)

    if len(str(seconds)) > 1:
        c = str(seconds)
    else:
        c = "0" + str(seconds)

    return a + ":" + b + ":" + c

# creates the time counter
def draw_time(start_time,pause_time):
    hours = 0
    minutes = 0
    seconds = 0
    current_time = time.time() - pause_time - start_time
    if current_time > 3600:
        while True:
            if current_time - 3600 > 0:
                hours += 1
                current_time -= 3600
            else:
                while True:
                    if current_time - 60 > 0:
                        minutes += 1
                        current_time -= 60
                    else:
                        seconds += int(current_time)
                        break
                break

    else:
        while True:
            if current_time - 60 > 0:
                minutes += 1
                current_time -= 60
            else:
                seconds += int(current_time)
                break

    return [font1.render(get_time(hours, minutes, seconds), True, (0, 0, 0), (255, 255, 255)), get_time(hours, minutes, seconds)]

class cell:
    def __init__(self,up,down,left,right):
        self.visited = False
        self.walls = [up,down,left,right]

class labyrinth:
    # generates the maze
    def __init__(self,id):
        self.id = id
        self.walls = []
        self.maze_walls = []
        self.cells = []

        x = 0
        t = 0

        # creates all cell within the maze
        for f in range(22):
            for s in range(28):
                # if command makes sure no cellls are created where the clock is supposed to be
                if not (f in (0,1,2) and s > 20):
                    self.cells.append(cell((x + 8, t, 25, 8), (x + 8, t + 33, 25, 8), (x, t + 8, 8, 25), (x + 33, t + 8, 8, 25)))
                x += 33
            x = 0
            t += 33

        # generates maze using prim's algorithm
        for v in self.cells[0].walls:
            self.maze_walls.append(v)
            self.walls.append(v)

        self.cells[0].visited = True

        while len(self.walls) > 0:
            wall = random.choice(self.walls)
            # checks which cells are divided by the wall
            divided_cells = []
            for u in self.cells:
                if wall in u.walls:
                    divided_cells.append(u)

            if len(divided_cells) > 1 and (not ((divided_cells[0].visited and divided_cells[1].visited) or ((not divided_cells[0].visited) and (not divided_cells[1].visited)))):
                # checks which cells have been visited
                for k in divided_cells:
                    k.walls.remove(wall)

                    if k.visited == False:
                        k.visited = True

                    for q in k.walls:
                        if not q in self.walls:
                            self.walls.append(q)

                        if not q in self.maze_walls:
                            self.maze_walls.append(q)

                    if wall in self.maze_walls:
                        self.maze_walls.remove(wall)

            self.walls.remove(wall)

        for j in range(0,736,33):
            for i in range(0,951,33):
                self.maze_walls.append((i, j, 8, 8))

    # draws the maze
    def draw(self, goal):
        screen.fill((0, 0, 0))

        for k in self.maze_walls:
            pygame.draw.rect(screen, color, pygame.Rect(k[0],k[1],k[2],k[3]))

        pygame.draw.rect(screen, color, pygame.Rect(695, 0, 300, 105)) # clock background
        pygame.draw.rect(screen, (0, 255, 0), goal) # finish

id = 0
running = True
while running:
    screen = pygame.display.set_mode((930, 733))
    done = False
    color = (0, 128, 255) # color of the walls
    x = 16
    y = 16
    clock = pygame.time.Clock()
    start = time.time()
    id += 1
    maze = labyrinth(id)
    goal = pygame.Rect(899,701,25,25)
    victory = False
    speed = 4 # movement speed
    pause = False
    pause_time = 0 # time spent in pause menue
    game_time = 0 # time spent playingg

    while not done:
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                done = True
                running = False

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE or event.key == pygame.K_p:
                    if pause:
                        pause = False
                        pause_time = time.time() - pause_time_start
                    else:
                        pause = True
                        pause_time_start = time.time() - game_time - start

                if event.key == pygame.K_RETURN:
                    done = True

        if pause:
            screen.fill((0, 0, 0))
            pause_text = font2.render("PAUSE",True,(255,255,255))
            screen.blit(pause_text, (468 - (pause_text.get_width() // 2), 368 - (pause_text.get_height() // 2)))

        # the actual game
        if not victory and not pause:
            game_time = time.time() - pause_time - start
            move_up = True
            move_down = True
            move_left = True
            move_right = True
            pressed = pygame.key.get_pressed()

            # movment
            if pressed[pygame.K_w] or pressed[pygame.K_UP]:
                # checks if their is a overlap with the wall
                for m in maze.maze_walls:
                    player = pygame.Rect(x, y - speed, 10, 10)
                    if player.colliderect(pygame.Rect(m[0],m[1],m[2],m[3])):
                        move_up = False
                        break
                if move_up:
                    y -= speed

            if pressed[pygame.K_s] or pressed[pygame.K_DOWN]:
                player = pygame.Rect(x, y + speed, 10, 10)
                for m in maze.maze_walls:
                    if player.colliderect(pygame.Rect(m[0],m[1],m[2],m[3])):
                        move_down = False
                        break
                if move_down:
                    y += speed

            if pressed[pygame.K_a] or pressed[pygame.K_LEFT]:
                player = pygame.Rect(x - speed, y, 10, 10)
                for m in maze.maze_walls:
                    if player.colliderect(pygame.Rect(m[0],m[1],m[2],m[3])):
                        move_left = False
                        break
                if move_left:
                    x -= speed

            if pressed[pygame.K_d] or pressed[pygame.K_RIGHT]:
                player = pygame.Rect(x + speed, y, 10, 10)
                for m in maze.maze_walls:
                    if player.colliderect(pygame.Rect(m[0],m[1],m[2],m[3])):
                        move_right = False
                        break
                if move_right:
                    x += speed

            # checks if player has reached the goal
            if goal.colliderect((x, y, 10, 10)):
                victory = True

            # draws the screen
            maze.draw(goal)
            text = draw_time(start, pause_time)
            pygame.draw.rect(screen, (255, 100, 0), pygame.Rect(x,y,10,10))
            screen.blit(text[0], (700, 15))

        # victory screen
        if victory:
            screen.fill((0, 0, 0))
            time_text = font1.render("Time Taken: " + text[1],True,(255,255,255))
            victory_text = font2.render("VICTORY!",True,(255,255,255))
            reset = font3.render("(Press Enter to Start New Game)",True,(255,255,255))

            screen.blit(victory_text,(468 - (victory_text.get_width() // 2), 328 - (victory_text.get_height() // 2)))
            screen.blit(time_text, (468 - (time_text.get_width() // 2), (248 - (time_text.get_height() // 2)) + victory_text.get_height()))
            screen.blit(reset, (468 - (reset.get_width() // 2), (248 - (reset.get_height() // 2)) + victory_text.get_height() + time_text.get_height()))

        clock.tick(60)
        pygame.display.flip()

最佳答案

您在这里处理两种不同类型的时间测量:瞬间和持续时间。从 time.time() 中得到的是一个瞬间 - 它描述了一个特定的时间点。当你减去两个瞬间时,你会得到一个持续时间——这两个特定点之间耗时。如果混淆两者,您会看到令人困惑的结果。

start = time.time()
# ...
pause_time = 0 # time spent in pause menue
game_time = 0 # time spent playingg

这里你说的开始是瞬间,即游戏开始的那一刻。您是说pause_time 和game_time 是持续时间。它们是自游戏开始以来在暂停/未暂停模式下耗时。

在没有暂停的每一帧,您都会更新 game_time:

game_time = time.time() - pause_time - start

这里 starttime.time() 是瞬时值,pause_time 是持续时间。这是可行的,尽管读起来有点尴尬。从 time.time() 中减去 start 可以得到自游戏以暂停或未暂停模式开始以来的总耗时,减去 pause_time 可以得到处于未暂停模式的时间。太棒了。

这是您的暂停行为:

pause = True
pause_time_start = time.time() - game_time - start

所以 time.time()start 又是瞬间。减去它们就可以得到任何游戏中的总耗用时间。减去 game_time 即可得出暂停模式下的总运行时间(持续时间)。我不确定这是否是您真正想要的,因为下次您在取消暂停代码中使用它时:

pause = False
pause_time = time.time() - pause_time_start

所以 time.time() 是一个瞬间,而 pause_time_start 是一个持续时间。像这样减去它们会给你另一个瞬间,游戏开始前的某个时刻。但你却把这一刻当作一段持续时间!瞬间仍然是一个数字,但通常来说这是一个相当大的数字。 (从技术上讲,它是自纪元以来的秒数,即在您可能运行 Pygame 的大多数操作系统中,即 1970 年 1 月 1 日午夜的特定时刻。)

再次更新 game_time 时,情况明显出错:

game_time = time.time() - pause_time - start

现在 pause_time 的值不正确,您尝试添加一个时刻 (time.time()) 并减去另外两个时刻。这会给你带来巨大的负值。当您尝试渲染它时,您的时间渲染代码非常困惑,因为它不期望负数。它不显示“-15”秒。它显示的数字类似于“-1545616400”,该数字不适合屏幕!

它在第二轮起作用的原因是错误被抵消了。此计算使 game_time 变得非常负,从而影响 pause_start_time 的下一次计算,使其变得非常正,最终导致 pause_time 的下一次计算回到一个小的持续时间。

<小时/>

您可以通过确定 pause_time_start 应该是什么并修复相应的计算来最小化解决此问题。我想你的意思可能是游戏暂停的瞬间。如果是这样,您可以更新您的取消暂停/暂停代码:

if pause:
    pause = False
    pause_time += time.time() - pause_time_start
else:
    pause = True
    pause_time_start = time.time()

在我们暂停的那一刻,我们所做的就是记住那一刻以备后用。当我们取消暂停时,我们将暂停所花费的时间添加到累计暂停时间中。我们的瞬间保持瞬间,我们的持续时间保持持续时间。

关于python - 如何解决退出暂停屏幕后时钟显示不正确的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53907425/

相关文章:

python - 考虑到 p 在 python 中是素数,当我执行 p/p+1 + p+1/p 操作时出错

python - 怎样才能增加难度呢? (例如增加敌人的速度、增加敌人的数量)

python - pygame 错误 : DLL load failed (Win32)

c++ - 导入错误:没有名为 _tkinter 的模块

python - pygame中的 Sprite 掩码碰撞问题

python - pygame.draw 和 pygame.gfxdraw 之间的区别

python - PyOpenGL。 x = glGetDoublev(GL_MODELVIEW_MATRIX) 返回内存地址

python - pandas read_csv 每隔一列都有索引

python - 将 'input' 插入未知位置

python - 由于 : file does not start with RIFF id,无法将文件 file.wav 作为 WAV 打开