表面显示能够正确表示不透明度,但任何其他表面都不能
Surface display able to properly represent opacity, but any other surface cannot
我正在尝试用 pygame 制作井字游戏。我想要的一件重要事情是能够让我的图像(例如 X 和 O)在我的用户仅将鼠标悬停在网格图块上时略微半透明。我还使用不透明度直观地显示轮到谁了。
这是我试过的:
x_tile = pygame.image.load('x_tile').convert()
x_tile.set_alpha(100)
当我像这样直接将 x_tile
传送到显示器上时,效果很好:
# This is for simplicity's sake. The actual blit process is all being done in an infinite loop
screen = pygame.display.set_mode((300, 300))
screen.blit(x_file, x_file.get_rect())
但我的游戏正在使用另一个代表网格的图像,这就是我要复制的内容。所以我将这个板块传输到显示器上,然后将实际的 X 和 O 块块传输到板上。
screen = pygame.display.set_mode((300, 300))
screen.blit(board, board_rect)
board.blit(x_tile, x_tile.get_rect(center=grid[0].center)) # I have a list of Rects that make a grid on the board image. grid[0] is the top left
我这样做的时候,x_tile.set_alpha(100)
好像没有效果,我不知道怎么办。
编辑:我正在使用 pygame 2.0.1。我在 Windows 10.
这是完整的代码
import os
import pygame
from pygame.locals import *
# Game constants
WIN_SIZE = WIN_WIDTH, WIN_HEIGHT = 800, 600
BLACK = 0, 0, 0
WHITE = 255, 255, 255
RED = 255, 0, 0
BLUE = 0, 0, 255
# Game functions
class NoneSound:
"""dummy class for when pygame.mixer did not init
and there is no sound available"""
def play(self): pass
def load_sound(file):
"""loads a sound file, prepares it for play"""
if not pygame.mixer:
return NoneSound()
music_to_load = os.path.join('sounds', file)
try:
sound = pygame.mixer.Sound(music_to_load)
except pygame.error as message:
print('Cannot load following sound:', music_to_load)
raise SystemExit(message)
return sound
def load_image(file, colorkey=None, size=None):
"""loads image into game"""
image_to_load = os.path.join('images', file)
try:
image = pygame.image.load(image_to_load).convert()
except pygame.error as message:
print('Cannot load following image:', image_to_load)
raise SystemExit(message)
if colorkey is not None:
if colorkey == -1:
colorkey = image.get_at((0, 0))
image.set_colorkey(colorkey, RLEACCEL)
if size is not None:
image = pygame.transform.scale(image, size)
return image
# Game class
class TTTVisual:
"""Controls game visuals"""
def __init__(self, win: pygame.Surface):
self.win = win
# Load in game images
self.board = load_image('board.png', size=(600, 450), colorkey=WHITE)
self.x_tile = load_image('X_tile.png', size=(100, 100), colorkey=BLACK)
self.o_tile = load_image('O_tile.png', size=(100, 100), colorkey=BLACK)
# Translucent for disabled looking tile
self.x_tile_trans = self.x_tile.copy()
self.o_tile_trans = self.o_tile.copy()
self.x_tile_trans.set_alpha(100)
self.o_tile_trans.set_alpha(100)
# Used to let user know whose turn it is
self.x_turn = pygame.transform.scale(self.x_tile, (50, 50))
self.o_turn = pygame.transform.scale(self.o_tile, (50, 50))
self.x_turn_trans = pygame.transform.scale(self.x_tile_trans, (50, 50))
self.o_turn_trans = pygame.transform.scale(self.o_tile_trans, (50, 50))
self.get_rects()
self.grid = self.setup_grid()
def get_rects(self):
"""Creates coords for some visual game assets"""
self.board_rect = self.board.get_rect(
center=self.win.get_rect().center)
self.x_turn_rect = self.x_turn.get_rect(top=10, left=10)
self.o_turn_rect = self.o_turn.get_rect(top=10, left=WIN_WIDTH-60)
def setup_grid(self):
grid = []
left = 0
top = 150
row = 0
for i in range(9):
if (i != 0) and (i % 3 == 0):
row += 1
left = 0
grid.append(pygame.Rect(left, row*top, 200, 150))
left += 200
return grid
def update_turn_status(self):
"""Updates the X and O tiles on the top left and right to
let user know whose turn it is"""
self.win.blits((
(self.x_turn_trans, self.x_turn_rect),
(self.o_turn, self.o_turn_rect)
))
def update_grid(self):
"""Updates board"""
self.win.blit(self.board, self.board_rect)
# Here is where you could change board to win and see that the tile changes in opacity
self.board.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=self.grid[0].center))
def update(self):
self.win.fill(WHITE)
self.update_turn_status()
self.update_grid()
pygame.display.flip()
def main():
pygame.init()
win = pygame.display.set_mode(WIN_SIZE)
tttvisual = TTTVisual(win)
tttfunc = TTTFunc(tttvisual)
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
running = False
tttvisual.update()
pygame.quit()
if __name__ == "__main__":
main()
问题是由以下行引起的:
self.board.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=self.grid[0].center))
您没有 blit
显示器上的图像 Surface,而是 self.board
Surface .当 Surface 为 blit
时,它与目标混合。当您在 Surface 上绘图时,它会永久改变。由于您一遍又一遍地执行此操作,因此在每一帧中,源 Surface 都显得不透明。当您减小 alpha 值时(例如 self.x_tile_trans.set_alpha(5)
),将出现淡入淡出效果。
切勿在图像 Surface 上绘图。始终在显示器 Surface 上绘制。在帧开始时清除显示。在每一帧中绘制整个场景,并在帧结束时更新一次显示。
class TTTVisual:
# [...]
def update_grid(self):
"""Updates board"""
self.win.blit(self.board, self.board_rect)
# Here is where you could change board to win and see that the tile changes in opacity
x, y = self.grid[0].center
x += self.board_rect.x
y += self.board_rect.y
self.win.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=(x, y)))
典型的 PyGame 应用程序循环必须:
- 通过
pygame.event.pump()
or pygame.event.get()
处理事件。
- 根据输入事件和时间(分别为帧)更新对象的游戏状态和位置
- 清除整个显示或绘制背景
- 绘制整个场景(
blit
所有对象)
- 通过
pygame.display.update()
or pygame.display.flip()
更新显示
我正在尝试用 pygame 制作井字游戏。我想要的一件重要事情是能够让我的图像(例如 X 和 O)在我的用户仅将鼠标悬停在网格图块上时略微半透明。我还使用不透明度直观地显示轮到谁了。
这是我试过的:
x_tile = pygame.image.load('x_tile').convert()
x_tile.set_alpha(100)
当我像这样直接将 x_tile
传送到显示器上时,效果很好:
# This is for simplicity's sake. The actual blit process is all being done in an infinite loop
screen = pygame.display.set_mode((300, 300))
screen.blit(x_file, x_file.get_rect())
但我的游戏正在使用另一个代表网格的图像,这就是我要复制的内容。所以我将这个板块传输到显示器上,然后将实际的 X 和 O 块块传输到板上。
screen = pygame.display.set_mode((300, 300))
screen.blit(board, board_rect)
board.blit(x_tile, x_tile.get_rect(center=grid[0].center)) # I have a list of Rects that make a grid on the board image. grid[0] is the top left
我这样做的时候,x_tile.set_alpha(100)
好像没有效果,我不知道怎么办。
编辑:我正在使用 pygame 2.0.1。我在 Windows 10.
这是完整的代码
import os
import pygame
from pygame.locals import *
# Game constants
WIN_SIZE = WIN_WIDTH, WIN_HEIGHT = 800, 600
BLACK = 0, 0, 0
WHITE = 255, 255, 255
RED = 255, 0, 0
BLUE = 0, 0, 255
# Game functions
class NoneSound:
"""dummy class for when pygame.mixer did not init
and there is no sound available"""
def play(self): pass
def load_sound(file):
"""loads a sound file, prepares it for play"""
if not pygame.mixer:
return NoneSound()
music_to_load = os.path.join('sounds', file)
try:
sound = pygame.mixer.Sound(music_to_load)
except pygame.error as message:
print('Cannot load following sound:', music_to_load)
raise SystemExit(message)
return sound
def load_image(file, colorkey=None, size=None):
"""loads image into game"""
image_to_load = os.path.join('images', file)
try:
image = pygame.image.load(image_to_load).convert()
except pygame.error as message:
print('Cannot load following image:', image_to_load)
raise SystemExit(message)
if colorkey is not None:
if colorkey == -1:
colorkey = image.get_at((0, 0))
image.set_colorkey(colorkey, RLEACCEL)
if size is not None:
image = pygame.transform.scale(image, size)
return image
# Game class
class TTTVisual:
"""Controls game visuals"""
def __init__(self, win: pygame.Surface):
self.win = win
# Load in game images
self.board = load_image('board.png', size=(600, 450), colorkey=WHITE)
self.x_tile = load_image('X_tile.png', size=(100, 100), colorkey=BLACK)
self.o_tile = load_image('O_tile.png', size=(100, 100), colorkey=BLACK)
# Translucent for disabled looking tile
self.x_tile_trans = self.x_tile.copy()
self.o_tile_trans = self.o_tile.copy()
self.x_tile_trans.set_alpha(100)
self.o_tile_trans.set_alpha(100)
# Used to let user know whose turn it is
self.x_turn = pygame.transform.scale(self.x_tile, (50, 50))
self.o_turn = pygame.transform.scale(self.o_tile, (50, 50))
self.x_turn_trans = pygame.transform.scale(self.x_tile_trans, (50, 50))
self.o_turn_trans = pygame.transform.scale(self.o_tile_trans, (50, 50))
self.get_rects()
self.grid = self.setup_grid()
def get_rects(self):
"""Creates coords for some visual game assets"""
self.board_rect = self.board.get_rect(
center=self.win.get_rect().center)
self.x_turn_rect = self.x_turn.get_rect(top=10, left=10)
self.o_turn_rect = self.o_turn.get_rect(top=10, left=WIN_WIDTH-60)
def setup_grid(self):
grid = []
left = 0
top = 150
row = 0
for i in range(9):
if (i != 0) and (i % 3 == 0):
row += 1
left = 0
grid.append(pygame.Rect(left, row*top, 200, 150))
left += 200
return grid
def update_turn_status(self):
"""Updates the X and O tiles on the top left and right to
let user know whose turn it is"""
self.win.blits((
(self.x_turn_trans, self.x_turn_rect),
(self.o_turn, self.o_turn_rect)
))
def update_grid(self):
"""Updates board"""
self.win.blit(self.board, self.board_rect)
# Here is where you could change board to win and see that the tile changes in opacity
self.board.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=self.grid[0].center))
def update(self):
self.win.fill(WHITE)
self.update_turn_status()
self.update_grid()
pygame.display.flip()
def main():
pygame.init()
win = pygame.display.set_mode(WIN_SIZE)
tttvisual = TTTVisual(win)
tttfunc = TTTFunc(tttvisual)
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
running = False
tttvisual.update()
pygame.quit()
if __name__ == "__main__":
main()
问题是由以下行引起的:
self.board.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=self.grid[0].center))
您没有 blit
显示器上的图像 Surface,而是 self.board
Surface .当 Surface 为 blit
时,它与目标混合。当您在 Surface 上绘图时,它会永久改变。由于您一遍又一遍地执行此操作,因此在每一帧中,源 Surface 都显得不透明。当您减小 alpha 值时(例如 self.x_tile_trans.set_alpha(5)
),将出现淡入淡出效果。
切勿在图像 Surface 上绘图。始终在显示器 Surface 上绘制。在帧开始时清除显示。在每一帧中绘制整个场景,并在帧结束时更新一次显示。
class TTTVisual:
# [...]
def update_grid(self):
"""Updates board"""
self.win.blit(self.board, self.board_rect)
# Here is where you could change board to win and see that the tile changes in opacity
x, y = self.grid[0].center
x += self.board_rect.x
y += self.board_rect.y
self.win.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=(x, y)))
典型的 PyGame 应用程序循环必须:
- 通过
pygame.event.pump()
orpygame.event.get()
处理事件。 - 根据输入事件和时间(分别为帧)更新对象的游戏状态和位置
- 清除整个显示或绘制背景
- 绘制整个场景(
blit
所有对象) - 通过
pygame.display.update()
orpygame.display.flip()
更新显示