简体   繁体   English

如何使用 pygame 在精灵后面留下痕迹?

[英]How do I leave a trail behind a sprite with pygame?

众所周知,如果你移动一个精灵而不在它留下痕迹之前填满屏幕,但是,我想在移动其他东西的同时在我的后面留下一条很酷的痕迹(这意味着我不能简单地停止填满屏幕。提前感谢您的帮助

One solution would be to create another transparent surface (called alpha_surf here) with the size of the screen onto which you blit the objects with trails.一种解决方案是创建另一个透明表面(此处称为alpha_surf ),其大小与您使用轨迹 blit 对象的屏幕大小相同。 It needs to be a per-pixel alpha surface which you can create by passing the pygame.SRCALPHA special flag.它需要是一个每像素 alpha 表面,您可以通过传递pygame.SRCALPHA特殊标志来创建它。

Blit the objects and reduce the alpha of all pixels on the alpha_surf each frame by filling it with a transparent white and also pass the pygame.BLEND_RGBA_MULT flag so that only the alpha channel is affected. Blit 对象并通过用透明白色填充每一帧来降低alpha_surf上所有像素的 alpha,并传递pygame.BLEND_RGBA_MULT标志,以便仅影响 alpha 通道。

import pygame as pg
from pygame.math import Vector2


class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((50, 50), pg.SRCALPHA)
        pg.draw.circle(self.image, pg.Color('dodgerblue'), (25, 25), 25)
        self.rect = self.image.get_rect(center=pos)
        self.vel = Vector2(0, 0)
        self.pos = Vector2(pos)

    def update(self):
        self.pos += self.vel
        self.rect.center = self.pos


def main():
    pg.init()
    screen = pg.display.set_mode((640, 480))
    # Blit objects with trails onto this surface instead of the screen.
    alpha_surf = pg.Surface(screen.get_size(), pg.SRCALPHA)
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    player = Player((150, 150), all_sprites)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                return
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_d:
                    player.vel.x = 5
                elif event.key == pg.K_a:
                    player.vel.x = -5
                elif event.key == pg.K_w:
                    player.vel.y = -5
                elif event.key == pg.K_s:
                    player.vel.y = 5
            elif event.type == pg.KEYUP:
                if event.key == pg.K_d and player.vel.x > 0:
                    player.vel.x = 0
                elif event.key == pg.K_a and player.vel.x < 0:
                    player.vel.x = 0
                elif event.key == pg.K_w:
                    player.vel.y = 0
                elif event.key == pg.K_s:
                    player.vel.y = 0

        # Reduce the alpha of all pixels on this surface each frame.
        # Control the fade speed with the alpha value.
        alpha_surf.fill((255, 255, 255, 220), special_flags=pg.BLEND_RGBA_MULT)

        all_sprites.update()
        screen.fill((20, 50, 80))  # Clear the screen.
        all_sprites.draw(alpha_surf)  # Draw the objects onto the alpha_surf.
        screen.blit(alpha_surf, (0, 0))  # Blit the alpha_surf onto the screen.
        pg.display.flip()
        clock.tick(60)


if __name__ == '__main__':
    main()
    pg.quit()

在此处输入图片说明

Alternatively, you could create several versions of the sprite image with different alpha values and also store the previous positions of the sprite.或者,您可以使用不同的 alpha 值创建多个版本的精灵图像,并存储精灵的先前位置。 Then just blit the images with lower alpha at the previous positions.然后在之前的位置用较低的 alpha 对图像进行 blit。

You can also blit other images or particles instead of the self.image if you want to create a different kind of trail, for example smoke.如果您想创建不同类型的轨迹,例如烟雾,您还可以 blit 其他图像或粒子而不是self.image

Here's another variant with a separate, different image for the trail which gets blitted before the self.image s of the sprites are blitted, so that it'll appear below them:这是另一个变体,带有单独的、不同的轨迹图像,在精灵的self.imageself.image之前被self.image ,因此它会出现在它们下面:

import pygame as pg
from pygame.math import Vector2


class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((50, 70), pg.SRCALPHA)
        self.image.fill(pg.Color('sienna1'))
        self.rect = self.image.get_rect(center=pos)
        # A separate image for the trail (just a single-color circle).
        self.trail_image = pg.Surface((40, 40), pg.SRCALPHA)
        pg.draw.circle(self.trail_image, pg.Color('dodgerblue'), (20, 20), 20)
        self.trail_rect = self.trail_image.get_rect()

        self.vel = Vector2(0, 0)
        self.pos = Vector2(pos)

    def update(self):
        self.pos += self.vel
        self.rect.center = self.pos
        # Update the rect of the trail as well, because we'll blit it there.
        self.trail_rect.center = self.rect.center


def main():
    pg.init()
    screen = pg.display.set_mode((640, 480))
    # Blit objects with trails onto this surface instead of the screen.
    alpha_surf = pg.Surface(screen.get_size(), pg.SRCALPHA)
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    sprites_with_trails = pg.sprite.Group()
    player = Player((150, 150), all_sprites, sprites_with_trails)

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                return
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_d:
                    player.vel.x = 5
                elif event.key == pg.K_a:
                    player.vel.x = -5
                elif event.key == pg.K_w:
                    player.vel.y = -5
                elif event.key == pg.K_s:
                    player.vel.y = 5
            elif event.type == pg.KEYUP:
                if event.key == pg.K_d and player.vel.x > 0:
                    player.vel.x = 0
                elif event.key == pg.K_a and player.vel.x < 0:
                    player.vel.x = 0
                elif event.key == pg.K_w:
                    player.vel.y = 0
                elif event.key == pg.K_s:
                    player.vel.y = 0

        # Reduce the alpha of all pixels on this surface each frame.
        # Control the fade speed with the alpha value.
        alpha_surf.fill((255, 255, 255, 244), special_flags=pg.BLEND_RGBA_MULT)

        all_sprites.update()
        screen.fill((20, 50, 80))  # Clear the screen.
        # Blit the trails onto the alpha_surf.
        for sprite in sprites_with_trails:
            alpha_surf.blit(sprite.trail_image, sprite.trail_rect)
        screen.blit(alpha_surf, (0, 0))  # Blit the alpha_surf onto the screen.
        all_sprites.draw(screen)  # Draw the objects onto the alpha_surf.
        pg.display.flip()
        clock.tick(60)


if __name__ == '__main__':
    main()
    pg.quit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM