我实际上正在编写一个程序,该程序可以识别两个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()
我附上一张说明图:
答案 0 :(得分:3)
I'd check if the specific button is pressed in the main loop and then just draw the corresponding rect.
By the way, the reDraw
function in your example doesn't draw anything. You would have to call pygame.draw.rect
in the for
loop, but then it would just draw several white rects. You could put [color, rect] lists into the bgd
list instead of just the rects and then use a for loop to draw them.
Also, better create the joystick instances ahead of the main loop (you'd still need some checks in the main loop to prevent crashes if one of the joysticks doesn't exist).
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()
The problem with the reDraw
function is that it is practically doing nothing, because the bgd
list only contains rects that pygame.draw.rect
returns and not the pygame.draw.rect
function calls themselves. To update the screen, you need to clear it each frame, then draw every visible object again and finally call pygame.display.flip()
or pygame.display.update()
.
list.append
will just append the object that you pass to it. In this case you append the value that pygame.draw.rect
returns (a rect). If pygame.draw.rect
would just draw something and return nothing, it would append None
because functions that return nothing return None
implicitly.
Here's another example that's closer to your original one:
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()
You mentioned that you actually want to display images that correspond to the different joypad buttons (for example the square or the circle on a playstation gamepad). You could do that by adding the images to a dictionary (or list) with the button numbers as the keys. Then iterate over the button numbers as in the previous example, use them to get the associated images in the dict and blit them in the while loop:
# 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))