【问题标题】:pygame doesn't refresh the screenpygame 不刷新屏幕
【发布时间】:2018-09-22 21:45:25
【问题描述】:

我实际上正在制作一个程序,它可以识别两个 PS3 控制器并将它们的图像连同它们的控制器名称和其他“背景精灵”一起传送到屏幕上。我希望用户单击一个控制器,然后他们的控制器上会出现一个圆圈或类似的东西 - 这样他们就知道他们已经拿起了哪个,然后当他们的按钮被释放时,圆圈会消失(或者被我所有的背景艺术有效地从屏幕上删除圆圈)。我想这个背景列表以及它似乎没有像我想要的那样更新屏幕的方式是这里的基础......

为了简化这个问题,我给出了一个相关的简短示例: 我想将控制器显示为由控制器图像表示的附加设备,或者在这段缩短的代码中显示为白色垂直线。 我已经使用列表 bgd[] 构建了背景图像。 当我按下任一操纵杆上的按钮时,我希望看到相关控制器(白线)出现一条临时灰线,当按键被抬起时它应该消失。我的问题是我无法让灰线消失。 我以为我只需要用内容覆盖所有内容 不变的背景图片 bgd[].

import pygame
from pygame.locals import *
import os

# Place the display 'screen' at top. 
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (0,10) 
# Iterate over all graphics which make up the 'unalterable background'
# This should put graphics into memory ready for blitting later...
# 
def reDraw(background):
    for r in (range (len(background))):
        background[r]

pygame.init()    
size = display_width, display_height = 100,100
screen = pygame.display.set_mode(size)
# List of 'unalterable background graphics/sprites
bgd = []
# Bottom of the virtual z-stack of screen graphics - a black background
bgd.append(screen.fill((0,0,0)))
# Count the number of Joysticks
joystick_count = pygame.joystick.get_count()
# One joystick is represented by a grey line on the left of the screen
if joystick_count == 1:
        bgd.append(pygame.draw.rect(screen, (255,255,255), (10,20,10,60)))
        reDraw(bgd) #Ready to display.update later
# A second joystick is represented by a grey line on the right of the screen
if joystick_count == 2:
        bgd.append(pygame.draw.rect(screen, (255,255,255), (10,20,10,60)))
        bgd.append(pygame.draw.rect(screen, (255,255,255), (80,20,10,60)))
        reDraw(bgd) #Ready to display.update later

# Now to create TEMPORARY SCREEN FEATURES, which should only be present 
# Whilst the buttons are pressed on each PS3 controller joystick :
run = True
while run == True:
    for j in range(joystick_count):
        joystick = pygame.joystick.Joystick(j)
        joystick.init()
        buttons = joystick.get_numbuttons()
        reDraw(bgd) #Ready to display.update later

        #Now to put all the queued draw statements onto the screen
        pygame.display.update() 


        for i in range( buttons ):
            button = joystick.get_button( i )
            if button != 0 and j == 0 :        
                pygame.draw.rect(screen, (150,150,150), (20,20,30,10))
            if button != 0 and j == 1 :        
                pygame.draw.rect(screen, (150,150,150), (50,70,30,10))

    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            pygame.quit()
            quit()  

我附上一张解释性图片:

【问题讨论】:

  • 能否更正代码缩进?
  • 完成 - 对不起!

标签: python python-3.x pygame


【解决方案1】:

我会检查是否在主循环中按下了特定按钮,然后只绘制相应的矩形。

顺便说一句,您示例中的 reDraw 函数没有绘制任何内容。您必须在for 循环中调用pygame.draw.rect,但它只会绘制几个白色矩形。您可以将 [color, rect] 列表放入 bgd 列表中,而不仅仅是 rects,然后使用 for 循环来绘制它们。

另外,最好在主循环之前创建游戏杆实例(如果其中一个游戏杆不存在,您仍然需要在主循环中进行一些检查以防止崩溃)。

import pygame
from pygame.locals import *


pygame.init()
screen = pygame.display.set_mode((100,100))
clock = pygame.time.Clock()
# A list of [color, rect] lists.
bgd = []
# Count the number of Joysticks.
joystick_count = pygame.joystick.get_count()
# Instantiate a joystick and initialize it.
if joystick_count == 1:
    joystick0 = pygame.joystick.Joystick(0)
    joystick0.init()
    # Append the color and the rect.
    bgd.append([(255,255,255), (10,20,10,60)])

run = True
while run:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT
                or event.type == KEYDOWN and event.key == K_ESCAPE):
            run = False

    screen.fill((0,0,30))  # Clear the screen each frame.
    # Iterate over the [color, rect] lists and pass them to draw.rect.
    for color, rect in bgd:
        pygame.draw.rect(screen, color, rect)
    # Check if button 0 is pressed, if True, draw the rect.
    if joystick0.get_button(0):
        pygame.draw.rect(screen, (150,150,150), (20,20,30,10))

    pygame.display.update()
    clock.tick(60)  # Limit the frame rate to 60 FPS.

pygame.quit()

reDraw 函数的问题在于它实际上什么都不做,因为bgd 列表只包含pygame.draw.rect 返回的矩形,而不是pygame.draw.rect 函数调用自身。要更新屏幕,您需要每帧清除它,然后再次绘制每个可见对象,最后调用pygame.display.flip() 或pygame.display.update()。

list.append 只会附加您传递给它的对象。在这种情况下,您附加 pygame.draw.rect 返回的值(一个矩形)。如果pygame.draw.rect 只是绘制一些东西而不返回任何内容,那么它将附加None,因为不返回任何内容的函数会隐式返回None。

这是另一个更接近原始示例的示例:

import pygame
from pygame.locals import *


def reDraw(background, screen):
    for color, rect in background:
        pygame.draw.rect(screen, color, rect)


pygame.init()
size = display_width, display_height = 100,100
screen = pygame.display.set_mode(size)
# List of 'unalterable background graphics/sprites
bgd = []
# Count the number of Joysticks
joystick_count = pygame.joystick.get_count()
if joystick_count == 1:
    bgd.append([(255,255,255), (10,20,10,60)])
if joystick_count == 2:
    bgd.append([(255,255,255), (10,20,10,60)])
    bgd.append([(255,255,255), (80,20,10,60)])

# Create the joystick instances.
joysticks = [pygame.joystick.Joystick(x)
             for x in range(pygame.joystick.get_count())]
# Initialize them.
for joystick in joysticks:
    joystick.init()

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT or (
                event.type == KEYDOWN and event.key == K_ESCAPE):
            run = False

    screen.fill((0, 0, 0))  # Clear the screen.
    reDraw(bgd, screen)  # Draw the joystick rects.

    for joystick in joysticks:
        for i in range(joystick.get_numbuttons()):
            button = joystick.get_button(i)
            # Draw the gray rects.
            if button and joystick.get_id() == 0:
                pygame.draw.rect(screen, (150,150,150), (20,20,30,10))
            if button and joystick.get_id() == 1:
                pygame.draw.rect(screen, (150,150,150), (50,70,30,10))

    pygame.display.update()  # Show everything we've drawn this frame.

pygame.quit()

您提到您实际上希望显示与不同游戏手柄按钮相对应的图像(例如 playstation 游戏手柄上的正方形或圆形)。您可以通过将图像添加到以按钮编号作为键的字典(或列表)中来做到这一点。然后像前面的例子一样遍历按钮编号,使用它们在 dict 中获取关联的图像,并在 while 循环中对它们进行 blit:

# Create or load the symbol images/surfaces.
CIRCLE_IMG = pygame.Surface((30, 30), pygame.SRCALPHA)
pygame.draw.circle(CIRCLE_IMG, (150, 0, 80), (15, 15), 14, 2)
# Add the images to a dictionary. The keys are the associated
# button numbers.
# You could also use a list if you have images for all buttons.
BUTTON_SYMBOLS = {1: CIRCLE_IMG, 2: SQUARE_IMG}  # etc.

# In the while loop use the button numbers to get the images in the dict and blit them.
for joystick in joysticks:
    for x in range(joystick.get_numbuttons()):
        if x in BUTTON_SYMBOLS and joystick.get_button(x):
            screen.blit(BUTTON_SYMBOLS[x], (20, 20))

【讨论】:

  • 在给出 pygame.display.update() 命令之前,我的 reDraw 函数并不打算重绘任何东西。也许是一个糟糕的函数名,但它确实做了它应该做的事情。您的代码很棒并且有效,谢谢您 - 但我更愿意扫描所有操纵杆上的所有按钮 - 然后确定按钮按下来自哪个操纵杆,然后显示与操纵杆相关的图像(灰色矩形)。
  • 作为 pygame 的新手,我收到了一个关于 SO 的评论,有人建议保存一个更永久的背景图形列表,这样他们就可以完全覆盖临时精灵以有效地将它们从屏幕上删除- 我喜欢这种方法,我在这里尝试使用它,带有背景列表 bgd[]。
  • reDraw 函数真的没有任何作用。您只是在范围内进行迭代,但不要对 r (这只是一个数字)做任何事情。我仍然不确定您要达到的目标。你能多谈谈你的实际目标吗?这应该成为一个游戏还是你只是在测试操纵杆功能?
  • 那仍然没有任何效果。 ;) 它只会给你背景列表中的矩形。 pygame.draw.rect 返回一个 pygame.Rect 对象,因此您的 bgd 列表实际上只包含矩形。你真的要在reDraw函数中重复调用pygame.draw.rect吗?
  • 您之前的评论会使问题更加清晰(符号内容)。最好将其添加到问题中。我稍后会编辑我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多