【问题标题】:Pygame - Image smudging / leaving a trail on the screenPygame - 图像弄脏/在屏幕上留下痕迹
【发布时间】:2021-05-20 21:26:57
【问题描述】:

我是 Python 的新手,我正在尝试创建从屏幕底部落下并在它们到达终点后消失的雨滴网格(来自 Python 速成课程书)。

我设法让网格和水滴掉落,但是水滴在屏幕上留下了痕迹,我一直在弄清楚为什么。

我已经检查了许多我可以找到的类似问题,但仍然找不到解决方案

这是我的游戏代码和 randrop 实例:

import pygame
import sys
from settings import Settings
from raindrop import Raindrop

class RaindropsGame:
    """Overall class to manage game"""

    def __init__(self):
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
        self.raindrops = pygame.sprite.Group()
        self.screen_caption = pygame.display.set_caption("Raindrops")
        self.BackGround = pygame.image.load('images/clouds.bmp')

    def run_game(self):
        while True:
            self._update_screen()
            self._create_fleet()
            self.check_events()
            self._update_raindrops()



    def _update_screen(self):
        self.screen.blit(self.BackGround, (0, 0))
        self.raindrops.draw(self.screen)
        pygame.display.flip()

    def _update_raindrops(self):
        self._check_fleet_edges()
        self.raindrops.update()
        if not self.raindrops:
            self._create_fleet()


    def check_events(self):
        """Check keyboard key presses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    sys.exit()

    def _create_raindrop(self, raindrop_number, row_number):
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size
        raindrop.x = 1 * raindrop_width * raindrop_number
        raindrop.rect.x = raindrop.x
        raindrop.y = raindrop.rect.height + raindrop.rect.height * row_number
        raindrop.rect.y = raindrop.y
        self.raindrops.add(raindrop)

    def _create_fleet(self):
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size
        available_space_x = self.settings.screen_width - 2* raindrop_width
        number_raindrops_x = available_space_x // (1 * raindrop_width)
        available_space_y = (self.settings.screen_height - 5 * raindrop_height)
        number_rows = available_space_y // (2 * raindrop_height)
        for row_number in range(number_rows):
            for raindrop_number in range(number_raindrops_x):
                self._create_raindrop(raindrop_number, row_number)

    def _check_fleet_edges(self):
        for raindrop in self.raindrops.sprites():
            if raindrop.check_edges():
                self.raindrops.remove(raindrop)

if __name__ in '__main__':
    ai = RaindropsGame()
    ai.run_game()

雨滴实例:

import pygame
from pygame.sprite import Sprite
from settings import Settings


class Raindrop(Sprite):
    """Class to manage raindrops"""

    def __init__(self, ai_game):
        super().__init__()
        self.settings = ai_game.settings
        self.screen = ai_game.screen
        self.image = pygame.image.load('images/raindrop.bmp').convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.y = self.rect.height
        self.y = float(self.rect.y)


    def check_edges(self):
        screen_rect = self.screen.get_rect()
        if self.rect.bottom >= screen_rect.bottom or self.rect.top <=0:
            return True


    def update(self):
        """Move the raindrop down."""
        self.y += self.settings.raindrop_speed
        self.rect.y = self.y

    def blitme(self):
        self.screen.blit(self.image, self.rect)

我非常感谢任何帮助,如果需要,这里是我看到的问题的屏幕截图:

【问题讨论】:

  • 你必须在每个循环中清除screen。你应该在每个教程中看到它。 IE。 screen.fill( (0, 0, 0) ) 填充黑色。或者你必须在每个循环中绘制免费。
  • 使用print() 来查看变量中的值以及执行了哪部分代码——也许你没有绘制背景,或者你添加了新的雨滴但你没有删除旧的。您应该只移动现有的雨滴,但可能会在新的地方创建新的雨滴。您只能创建一次所有雨滴 - 在开始时 - 然后只移动它们。当它们移动到底部时,再将它们移动到顶部。

标签: python python-3.x pygame trail


【解决方案1】:

我对其进行了测试,问题是因为您在每个循环中都创建了新的雨滴,因为您在循环内有 self._create_fleet()。您必须在循环之前使用它才能仅创建第一个雨滴。

def run_game(self):
    clock = pygame.time.Clock()

    self._create_fleet()

    while True:
        self._update_screen()
        self.check_events()
        self._update_raindrops()

        clock.tick(25)  # the same speed 25 FPS (Frames Per Seconds) on old and new computers

编辑:

我的版本几乎没有其他变化

  • 我使用 Clock() 始终保持 25 FPS
  • 我不检查雨滴是否在顶部留下屏幕
  • 我检查了雨滴的顶部(不是雨滴的底部)是否离开屏幕,这样看起来更好
  • 我不移除雨滴,而是移到顶部

import os
import pygame

APP_HOME = os.path.dirname(os.path.abspath(__file__))


class Settings():
    screen_width = 800
    screen_height = 600
    raindrop_speed = 5

    
class Raindrop(pygame.sprite.Sprite):
    """Class to manage raindrops"""

    def __init__(self, ai_game):
        super().__init__()
        self.settings = ai_game.settings
        self.screen = ai_game.screen
        self.image = pygame.image.load(os.path.join(APP_HOME, 'images', 'raindrop.bmp')).convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.y = self.rect.height
        self.y = float(self.rect.y)


    def check_edges(self):
        screen_rect = self.screen.get_rect()
        #if self.rect.bottom >= screen_rect.bottom or self.rect.top <= 0:
        #    return True
        
        # check only bottom edge
        # and use `top` instead of `botton` check when full dropdown leaves screen
        if self.rect.top >= screen_rect.bottom:
            return True

    def update(self):
        """Move the raindrop down."""
        self.y += self.settings.raindrop_speed
        self.rect.y = self.y

    def blitme(self):
        self.screen.blit(self.image, self.rect)


class RaindropsGame:
    """Overall class to manage game"""

    def __init__(self):
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
        self.raindrops = pygame.sprite.Group()
        self.screen_caption = pygame.display.set_caption("Raindrops")
        self.BackGround = pygame.image.load(os.path.join(APP_HOME, 'images', 'clouds.bmp'))

    def run_game(self):
        clock = pygame.time.Clock()
        self._create_fleet()
        while True:
            self._update_screen()
            self.check_events()
            self._update_raindrops()
            clock.tick(25)  # 25 FPS


    def _update_screen(self):
        self.screen.blit(self.BackGround, (0, 0))
        self.raindrops.draw(self.screen)
        pygame.display.flip()

    def _update_raindrops(self):
        self._check_fleet_edges()
        self.raindrops.update()
        if not self.raindrops:
            self._create_fleet()


    def check_events(self):
        """Check keyboard key presses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    exit()

    def _create_raindrop(self, column_number, row_number):
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size
        
        raindrop.x = (1.1 * raindrop_width) * column_number
        raindrop.rect.x = raindrop.x
        
        raindrop.y = (1.2 * raindrop_height) * row_number
        raindrop.rect.y = raindrop.y
        
        self.raindrops.add(raindrop)

    def _create_fleet(self):
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size
        
        available_space_x = self.settings.screen_width - (2 * raindrop_width)
        number_raindrops_x = available_space_x // (1 * raindrop_width)
        
        available_space_y = self.settings.screen_height - (5 * raindrop_height)
        number_rows = available_space_y // (1 * raindrop_height)
        
        for row_number in range(number_rows):
            for raindrop_number in range(number_raindrops_x):
                self._create_raindrop(raindrop_number, row_number)
                
    def _check_fleet_edges(self):
        for raindrop in self.raindrops.sprites():
            if raindrop.check_edges():
                #self.raindrops.remove(raindrop)
                
                # move to top instead of removing
                raindrop.rect.bottom = 0
                raindrop.y = raindrop.rect.y
                
if __name__ in '__main__':
    ai = RaindropsGame()
    ai.run_game()

图片:

clouds.bmp

raindrop.bmp

【讨论】:

  • 谢谢,解决了。早该知道的,我在一个while循环中创建了drop。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
  • 2011-09-09
  • 1970-01-01
  • 2019-06-09
  • 2013-09-07
  • 1970-01-01
相关资源
最近更新 更多