使用 PyGame 在移动表面上分配静态遮罩

Assign static Mask on moving Surface with PyGame

我昨天刚开始我的第一个 PyGame 项目,我找不到如何正确使用遮罩实体应用到移动的表面上。

我为动画表面制作了一个特定的class

class LabelObject():
    def __init__(self, surface, x, y, endX, speed, idleTime):
        self.surface = surface
        self.x = x
        self.y = y
        self.endX = endX
        self.speed = speed
        self.idleTime = idleTime
        self.alpha = 255
        self.timer_start = 0
        self.timer_end = 0
        self.pos = self.surface.get_rect(x=self.x,y=self.y)

    def move(self):
        self.timer_start += 1
        if self.timer_start > self.idleTime:
            if self.pos.right > self.endX:
                self.pos.x += self.speed
            elif self.pos.x < self.x:
                self.timer_end += 1
                if self.timer_end > self.idleTime:
                    self.alpha -= 25
                if self.timer_end > self.idleTime + 11:
                    self.pos = self.surface.get_rect(x=self.x, y=self.y)
                    self.timer_start = 0
                    self.timer_end = 0
                    self.alpha = 255
        self.surface.set_alpha(self.alpha)

此 class 的要点是检查表面是否超过给定区域,然后向左滑动以能够完整阅读其中呈现的文本。

在我的主循环中,我可以像这样将它 blit 到屏幕上

label = LabelObject(textSurface,20,10,100,-0.5,30)
while not over:
    for event in pygame.event.get():
         if event.type == pygame.QUIT
             over = True
    screen.fill((0,0,0))
    label.move()
    screen.blit(label.surface, label.pos)
    pygame.display.update()

这很好用,但我需要在其上应用不需要移动的遮罩。对于此示例,遮罩的矩形将为 (20, 10, 100-20, label.surface.get_height())。在网上看到了一些关于Mask的例子,但是没找到mask静止而表面运动时的使用方法

编辑: 我尝试在 blit 函数中使用区域选项,但有些奇怪,区域和表面移动不同步。

EDIT2: 最后这里是带区域选项的良好 blit 函数。只需要制作带有静态位置的blit,以及带有动画位置的区域:

self.screen.blit(label.surface, (label.x,label.y), area=pygame.Rect(label.x-label.pos.x, 0, label.endX-label.x, label.surface.get_height()))

我尝试用 subsurface 做完整的工作示例,以切断完整图像的可见部分。 Rect (sub_image_rect) 总是一样的——画在同一个地方。我只改变偏移量来切断图像的不同部分。

我使用文本和字体生成一些图像 - 每个人都可以 运行 它没有自己的图像。

import pygame

# --- constants ---

BLACK = (  0,  0,  0)
RED   = (255,  0,  0)

# --- classes ---

class Label():

    def __init__(self, text, x, y, width):

        font = pygame.font.SysFont(None, 35)

        # generate full image
        self.image = font.render(text, True, RED)
        self.rect = self.image.get_rect(x=x, y=y)

        self.width = width
        self.speed = 1

        # offset of visible part
        self.offset_x = 0
        self.max_offset_x = self.rect.width - self.width

        # visible part of image
        self.sub_image = self.image.subsurface((self.offset_x,0), (self.width, self.rect.height))
        self.sub_image_rect = self.sub_image.get_rect(x=x, y=y)


    def move(self):

        # change offset
        self.offset_x += self.speed

        # change move direction
        if self.offset_x < 0:
            self.offset_x = 0
            self.speed = -self.speed
        elif self.offset_x > self.max_offset_x:
            self.offset_x = self.max_offset_x
            self.speed = -self.speed

        print self.offset_x, self.max_offset_x
        # visible part of image
        self.sub_image = self.image.subsurface((self.offset_x, 0),(self.width, self.rect.height))

    def draw(self, surface):
        surface.blit(self.sub_image, self.sub_image_rect)

# --- main ---

pygame.init()
screen = pygame.display.set_mode((800,600))

label = Label("Hello World of Python and Pygame!", 100, 100, 200)

# --- mainloop ---

fps = pygame.time.Clock()
running = True

while running:

    # --- events ---

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key ==  pygame.K_ESCAPE:
                running = False

    # --- updates ---

    label.move()

    # --- draws ---

    screen.fill(BLACK)

    label.draw(screen)

    fps.tick(25)
    pygame.display.flip()

# --- the end ---

pygame.quit()

编辑: 我在 blit 中用 area 做了例子。我只更改了 3 行 - 请参阅代码

中的 # changed
import pygame

# --- constants ---

BLACK = (  0,  0,  0)
RED   = (255,  0,  0)

# --- classes ---

class Label():

    def __init__(self, text, x, y, width):

        font = pygame.font.SysFont(None, 35)

        # generate full image
        self.image = font.render(text, True, RED)
        self.rect = self.image.get_rect(x=x, y=y)

        self.width = width
        self.speed = 1

        # offset of visible part
        self.offset_x = 0
        self.max_offset_x = self.rect.width - self.width

        # visible part of image as 'rect' - 'width' is always the same
        self.sub_image_rect = self.image.get_rect(x=0, width=self.width) # changed

    def move(self):

        # change offset
        self.offset_x += self.speed

        # change move direction
        if self.offset_x < 0:
            self.offset_x = 0
            self.speed = -self.speed
        elif self.offset_x > self.max_offset_x:
            self.offset_x = self.max_offset_x
            self.speed = -self.speed

        # visible part of image - change only `x` 
        self.sub_image_rect.x = self.offset_x  # changed

    def draw(self, surface):
        surface.blit(self.image, self.rect, area=self.sub_image_rect)  # changed

# --- main ---

pygame.init()
screen = pygame.display.set_mode((800,600))

label = Label("Hello World of Python and Pygame!", 100, 100, 200)

# --- mainloop ---

fps = pygame.time.Clock()
running = True

while running:

    # --- events ---

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key ==  pygame.K_ESCAPE:
                running = False

    # --- updates ---

    label.move()

    # --- draws ---

    screen.fill(BLACK)

    label.draw(screen)

    fps.tick(25)
    pygame.display.flip()

# --- the end ---

pygame.quit()