【问题标题】:Surface display able to properly represent opacity, but any other surface cannot表面显示能够正确表示不透明度,但任何其他表面都不能
【发布时间】:2021-01-02 23:02:27
【问题描述】:

我正在尝试使用 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())

但是我的游戏使用了另一个代表网格的图像,这就是我要使用的内容。所以我将这个板子blitting到显示器上,然后blitting板上实际的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()

【问题讨论】:

  • 您的 pygame 安装中存在错误,或者您使用 set_alpha 不当。你是什​​么操作系统?你在哪里打电话给set_alpha
  • 我认为最好将我的整个代码放在我的问题上。等一下。
  • 问题是你使用self.board。不要那样做。切勿在原始图像上绘制任何内容。

标签: python python-3.x pygame opacity pygame-surface


【解决方案1】:

问题是由以下行引起的:

self.board.blit(self.x_tile_trans, self.x_tile_trans.get_rect(center=self.grid[0].center))

你不是blit显示屏上的图像Surface,而是self.boardSurface。当Surfaceblit 时,它与目标混合。当您在 Surface 上绘图时,它会永久改变。由于您一遍又一遍地这样做,因此在每一帧中,源 Surface 看起来都是不透明的。当您降低 alpha 值(例如self.x_tile_trans.set_alpha(5))时,会出现淡入效果。

永远不要在图像上绘图表面。始终在显示 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 应用程序循环必须:

【讨论】:

  • 我不认为我的电路板图像具有每像素 alpha,因为我使用的是 .convert() 方法,而不是 .convert_alpha()
  • 抱歉,我忘了提及我对原始问题进行了编辑,并提到我使用的是 pygame 2.0.1。
猜你喜欢
  • 2011-11-01
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-08
  • 2016-10-06
  • 1970-01-01
相关资源
最近更新 更多