问题描述
我是 Python 新手,我正在尝试创建从屏幕底部落下并在到达终点后消失的雨滴网格(这来自 Python Crash Course 书).
I am brand new in Python and I am trying to create grids of raindrops falling down the bottom of the screen and dissapearing after they reach the end (This is from Python Crash Course book).
我已经设法让网格和水滴下落,但是水滴在屏幕上留下了痕迹,我一直在寻找原因.
I have managed to make the grids and drops falling, however the drops are leaving a trail on the screen and I am stuck at figuring out why.
我检查了很多我能找到的类似问题,但仍然找不到解决方案
I have checked many similar issues that I could found, but still could not find a resolution
这是我的游戏和随机实例代码:
Here is my code for the game and randrop instance:
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)
我非常感谢您对此的任何帮助,如果需要,这里是我所看到问题的屏幕截图:
I would really appreciate any help with this, and if needed here is a screenshot of the issue I am seeing:
推荐答案
我测试了它,问题是因为你在每个循环中创建了新的雨滴,因为你有 self._create_fleet()
内部循环.您必须在循环之前使用它来仅创建第一个雨滴.
I tested it and problem is because you create new Raindrops in every loop because you have self._create_fleet()
inside loop. You have to use it before loop to create only first raindrops.
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
我的版本几乎没有其他变化
My version with few other changes
- 我使用
Clock()
始终保持 25 FPS - 我不检查雨滴是否在顶部离开屏幕
- 我检查雨滴的顶部(而不是雨滴的底部)是否离开屏幕,以便看起来更好
- 我不去除雨滴,而是移到顶部
- I use
Clock()
to have always 25 FPS - I don't check if raindrop leave screen at the top
- I check if top of raindrop (not bottom of raindrom) leaves screen so it looks better
- I don't remove raindrops but move to the top
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()
图像:
Images:
clouds.bmp
raindrop.bmp
这篇关于Pygame - 图像模糊/在屏幕上留下痕迹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!