我正在使用 pygame 构建一个国际象棋 gui,其中主游戏循环调用单独类中的一个方法(GameState 类中的移动),然后进一步调用同一类中的另一个方法(pawn_promotion)。在pawn_promotion 方法中,一个表面promotion_menu 被blit 到窗口中。
但它只出现在屏幕上一帧。如果我在这里错了,请纠正我,但我认为正在发生的是表面正在被 blit 但是当游戏循环再次迭代时,它会被棋盘覆盖到窗口上。
class GameWindow:
def __init__(self):
load()
gs = GameState()
m = MoveList
run = True
square_selected = ()
clicks = []
while run:
win.blit(board_surface, (467, 132))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
MainMenu()
run = False
# Mouse ui
if event.type == pygame.MOUSEBUTTONDOWN: # checking for clicks
location = (pygame.mouse.get_pos()[0] - 467, pygame.mouse.get_pos()[1] - 132)
if 600 >= location[0] >= 0 and 600 >= location[1] >= 0:
column = location[0] // Square_size
row = location[1] // Square_size
# checking for repeat clicks
if square_selected == (row, column):
square_selected = ()
clicks = [] # if click is repeat, clear previous click
else:
# Player selects a square
square_selected = (row, column)
clicks.append(square_selected)
if len(clicks) == 2:
# second click moves the piece
self.move = m(clicks[0], clicks[1], gs.board)
gs.Move(self.move)
square_selected = ()
clicks = []
if gs.close_window:
run = False
class GameState:
...irrelavant code...
def pawn_promotion(self, move):
print(move.endrow, move.endcol)
self.is_prmt = True
promotion_menu = pygame.Surface((int(Square_size), int(Square_size * 4)))
promotion_menu.fill(white)
prmt_confirm = ''
if self.white_turn:
prmt_white_queen = Button(board_surface, (move.endcol + 1) * Square_size, 50, pieces_dict['wQ'], 1)
prmt_white_rook = Button(board_surface, (move.endcol + 1) * Square_size, 50 + Square_size,
pieces_dict['wR'], 1)
prmt_white_knight = Button(board_surface, (move.endcol + 1) * Square_size, 50 + (2 * Square_size),
pieces_dict['wN'], 1)
prmt_white_bishop = Button(board_surface, (move.endcol + 1) * Square_size, 50 + (3 * Square_size),
pieces_dict['wB'], 1)
if self.run_promote_menu:
print(self.run_promote_menu)
board_surface.blit(promotion_menu, ((move.endcol + 1) * Square_size, (move.endrow * Square_size) + 50))
prmt_queen = Button.draw(prmt_white_queen)
prmt_rook = Button.draw(prmt_white_rook)
prmt_knight = Button.draw(prmt_white_knight)
prmt_bishop = Button.draw(prmt_white_bishop)
if prmt_queen:
prmt_confirm = 'wQ'
# run_promote_menu = False
if prmt_rook:
prmt_confirm = 'wR'
# run_promote_menu = False
if prmt_knight:
prmt_confirm = 'wN'
# run_promote_menu = False
if prmt_bishop:
prmt_confirm = 'wB'
# run_promote_menu = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.run_promote_menu = False
close_window = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_z:
self.run_promote_menu = False
if prmt_confirm != '':
self.run_promote_menu = False
self.board[move.endrow][move.endcol] = prmt_confirm
pygame.display.update()
我正在使用以下类在表面上创建 4 个按钮
class Button:
def __init__(self, surface, x, y, image, scale):
image_width = image.get_width()
image_height = image.get_height()
self.image = pygame.transform.scale(image, (int(image_width * scale), int(image_height * scale)))
self.image_rect = image.get_rect(topleft=(x, y))
self.surface = surface
self.clicked = False
self.image_bg = pygame.Surface((self.image_rect.width + 10, self.image_rect.height + 5))
self.image_bg.set_alpha(0)
def draw(self):
action = False
pos = pygame.mouse.get_pos()
if self.image_rect.collidepoint(pos):
self.image_bg.set_alpha(1)
for event in pygame.event.get():
if pygame.mouse.get_pressed()[0] == 1 and not self.clicked:
self.clicked = True
action = True
if pygame.mouse.get_pressed()[1] == 0:
self.clicked = False
else:
self.image_bg.set_alpha(0)
self.surface.blit(self.image_bg, (self.image_rect.x - 5, self.image_rect.y))
self.surface.blit(self.image, (self.image_rect.x, self.image_rect.y))
return action
我对这个类还有另一个小问题, set_alpha() 行似乎在每帧增加 alpha 的值,而不是将其设置为常数值。是否有另一个命令可以保持 alpha 不变?
如果我在 pawn_promotion 中使用 while 循环,它可以完美运行,但由于它本质上是两个嵌套的 while 循环,因此会产生很多滞后。我试图通过使用 clock.tick() 来减少这种滞后,但它并没有完全摆脱它。