python - pygame不刷新屏幕

标签 python python-3.x pygame

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

为了简化这个问题,我给出了一个相关的较短示例: 我想将 Controller 显示为由 Controller 图像表示的附加设备,或者在这段缩短的代码中显示为白色垂直线。 我已经使用列表 bgd[] 构建了背景图像。 当我按下任一操纵杆上的按钮时,我希望看到相关 Controller (白线)出现一条临时灰线,当按下键时该线应该消失。我的问题是我无法让灰线消失。 我以为我只需要用内容 blit over everything 不变的背景图片 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()  

我包括一张解释性图片:

The code in action

最佳答案

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

顺便说一句,您示例中的reDraw 函数不绘制任何东西。您必须在 for 循环中调用 pygame.draw.rect,但随后它只会绘制几个白色矩形。您可以将 [color, rect] 列表放入 bgd 列表中,而不仅仅是矩形,然后使用 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()

您提到您实际上想要显示与不同游戏 handle 按钮对应的图像(例如 playstation 游戏 handle 上的正方形或圆形)。您可以通过将图像添加到以按钮编号作为键的字典(或列表)来实现。然后像前面的示例一样遍历按钮编号,使用它们在 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))

关于python - pygame不刷新屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52461148/

相关文章:

python - 属性错误 : 'module' object has no attribute 'createFisherFaceRecognizer'

python - 如何在 Tortoise-ORM 中使用 Postgresql Array 字段

python - 无法使用 crontab 安排 python 脚本

python-3.x - 如何在 Windows 上安装 OpenJPEG 并将其与 Pillow 一起使用?

python - "no matching architecture in universal wrapper"导入pygame时

python - 通过单击面向对象的 PyGame 按钮来调用 PyGame 函数

python - pygame窗口打开后立即关闭

python - 如何在Python中存储没有日期的时间以便比较方便?

c++ - glibc 检测到 *** free() : invalid pointer: Python c++ and Swig

python-3.x - 接受pylint的R1705的真正好处是什么?代码真的更安全吗?