【问题标题】:Pygame window isn't updatingPygame 窗口没有更新
【发布时间】:2021-02-02 18:51:07
【问题描述】:

我正在编写一个小型 Python 游戏,只是为了学习如何更好地使用 Python。我想尝试开始使用多个脚本,因为将所有代码保存在一个脚本中可能会有点拥挤。我制作了第二个脚本,创建了一个函数 main(scrn),一切似乎都运行良好。在我的主脚本 game.py 中调用该函数,它将创建屏幕并且 main(scrn) 函数中的所有内容都会显示出来。但是,什么都不会更新。我的角色根本不会移动,使用我之前测试过的重力控制器,或者向左或向右。我尝试将角色控制器从 hi.py 脚本 (main(scrn)) 移动到 while Running: 函数,但仍然没有移动。然后我尝试将 main(scrn) 函数移回我的原始脚本,但它仍然无法正常工作。似乎什么都没有更新。 这是组合脚本,描述中最后提到的一个

import pygame
from pygame.locals import *

pygame.init()
SIZE = 800, 600
screen = pygame.display.set_mode(SIZE)
def main(scrn):
#VARIABLES
    RED = (255, 0, 0)
    GRAY = (150, 150, 150)
    DGRAY = (75, 75, 75)
    rx = 0
    ry = 450
    x = 50
    y = 50
    grounded = False
    grv = 0
    acc = .1
    ground = Rect(rx, ry, 200, 800)
    ch = Rect(x, y, 50, 50)

#INPUT MOVEMENT
    pressed = pygame.key.get_pressed()

    if pressed[pygame.K_RIGHT]:
        x += 3
    if pressed[pygame.K_LEFT]:
        x -= 3
    if pressed[pygame.K_UP] and grounded:
        for z in range(1):
            grv = -5
            grounded = False

#GRAVITY
    self = ch
    if ch.colliderect(ground):
        grounded = True
    if not grounded:
        acc = .1
        y += grv 
        grv += acc
    if grounded:
        y = 400
        acc = 0
    if y > 600:
        return False

#UPDATE
    scrn.fill(GRAY)
    pygame.draw.rect(scrn, DGRAY, ground)
    pygame.draw.rect(scrn, RED, ch)
    pygame.display.update()

#RUNNING
running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            if event.key == pygame.K_r and main:
                main
    main(screen)
pygame.quit()

【问题讨论】:

    标签: python visual-studio-code while-loop pygame


    【解决方案1】:

    实际上,窗口的更新工作正常。但是,变量是在每一帧中初始化的。

    您必须在应用程序循环之前初始化变量,但在循环中更改变量。由于您使用函数,因此您必须在全局名称空间中初始化变量。您必须使用 global statement 将变量解释为全局变量并在函数中更改它们。

    def main(scrn):
        global x, y, grounded, rx, ry, grv, acc
    
        # [...]
    

    在更改变量xy 之后,但在碰撞测试之前创建pygame.Rect 对象:

    def main(scrn):
        # [...]
    
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_RIGHT]:
            x += 3
        if pressed[pygame.K_LEFT]:
            x -= 3
        # [...]
        
        ground = Rect(rx, ry, 200, 800)
        ch = Rect(x, y, 50, 50)
        if ch.colliderect(ground):
            # [...]
    

    您可以使用init_varaibles 函数来初始化变量。如果要重置变量并重新开始游戏,请再次调用此函数。

    def init_varaibles():
        global x, y, grounded, rx, ry, grv, acc
        rx = 0
        ry = 450
        x = 50
        y = 50
        grounded = False
        grv = 0
        acc = .2
    

    使用pygame.time.Clock 控制每秒帧数,从而控制游戏速度。

    pygame.time.Clock 对象的方法tick() 以这种方式延迟游戏,即循环的每次迭代消耗相同的时间段。见pygame.time.Clock.tick()

    这个方法应该每帧调用一次。

    这意味着循环:

    clock = pygame.time.Clock()
    running = True
    while running:
       clock.tick(100)
    

    每秒运行 100 次。


    完整示例:

    import pygame
    from pygame.locals import *
    
    pygame.init()
    SIZE = 800, 600
    screen = pygame.display.set_mode(SIZE)
    clock = pygame.time.Clock()
    
    RED = (255, 0, 0)
    GRAY = (150, 150, 150)
    DGRAY = (75, 75, 75)
    
    def init_varaibles():
        global x, y, grounded, rx, ry, grv, acc
        rx = 0
        ry = 450
        x = 50
        y = 50
        grounded = False
        grv = 0
        acc = .2
    
    def main(scrn):
        global x, y, grounded, rx, ry, grv, acc
    
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_RIGHT]:
            x += 3
        if pressed[pygame.K_LEFT]:
            x -= 3
        if pressed[pygame.K_UP] and grounded:
            grv = -5
            grounded = False
    
        y += grv 
        grv += acc
        
        ground = Rect(rx, ry, 200, 800)
        ch = Rect(x, y, 50, 50)
        if ch.colliderect(ground):
            grounded = True
            ch.bottom = ground.top
            grv = 0
            y = ch.y
    
        scrn.fill(GRAY)
        pygame.draw.rect(scrn, DGRAY, ground)
        pygame.draw.rect(scrn, RED, ch)
        pygame.display.update()
    
        return y > 600
    
    init_varaibles()
    
    running = True
    while running:
        clock.tick(100)
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                if event.key == pygame.K_r and main:
                    init_varaibles()
        
        game_over = main(screen)
        if game_over:
            break
    
    pygame.quit()
    

    【讨论】:

    • @Loaphs 我添加了一个完整的工作示例。该代码基于您的问题的代码。我看不到您的更改,也无法猜测您的新代码有什么问题。将我的代码与您的代码进行比较以发现问题。
    • @Loaphs 在更改变量xy 之后,但在碰撞测试之前创建pygame.Rect 对象:
    • 首先,你很了不起,在 5 分钟内回复。其次,将 main 函数保留在不同的脚本中会更好吗?
    • @Loaphs 让你的代码先运行。代码运行后,保存它。然后考虑改进它。了解ClassesInstance Objects。为游戏创建类。为玩家开设的课程。 ob 对象的另一个类,如地面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    相关资源
    最近更新 更多