Капли дождя падают не в том направлении в Pygame

Рейтинг: 2Ответов: 1Опубликовано: 28.07.2023

Всем доброго времени суток!

Я новичок в Python, познаю азы по учебнику Эрика Мэтиза. Сейчас делаю один из проектов учебника - "Alien Invasion". В конце каждого раздела есть контрольные задания. Столкнулся с проблемой в задании 13.4. Дождь: измените свой код в упражнении 13.3, чтобы при исчезновении ряда капель у нижнего края экрана новый ряд появлялся у верхнего края и начинал свое падение.

Ситуация такова, что у меня капли дождя падают не в низ, а в левую сторону экрана, не могу обнаружить ошибку. Очень буду благодарен, кто подскажет, как исправить этот баг!

Вот код:

test_rain.py

import sys
import pygame

from settings import Settings
from raindrops import Raindrop

class TestRain():
    """Класс для управления ресурсами и поведением игры."""

    def __init__(self):
        """Инициализирует игру и создает игровые ресурсы."""
        pygame.init()
        self.settings = Settings()

        """это экран игры"""
        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        self.settings.screen_width = self.screen.get_rect().width
        self.settings.screen_height = self.screen.get_rect().height
        pygame.display.set_caption("Дождик капает!")
        
        self.raindrops = pygame.sprite.Group()

        self._create_fleet()
    
    def run_game(self):
        """Запуск основного цикла игры."""
        while True:
            self._check_events()
            self._update_raindrops()
            self._update_screen()
            
    def _check_events(self):
        """Обрабатывает нажатия клавиш и события мыши."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
    
    def _check_keydown_events(self, event):
        """Реагирует на нажатие клавиш."""
        if event.key == pygame.K_q:
            sys.exit()
        
    def _create_fleet(self):
        """Создает дождь."""
        # Создание капли дождя и вычисление количества капель в ряду
        # Интервал между соседними каплями равен ширине капли.
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size
        available_space_x = self.settings.screen_width - (1 * raindrop_width)
        number_raindrops_x = available_space_x // (1 * raindrop_width)

        """Определяет количество рядов, помещающихся на экране."""
        available_space_y = (self.settings.screen_height -
                                (1 * 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 _create_raindrop(self, raindrop_number, row_number):
        """Создание капли дождя и размещение ее в ряду."""
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size

        raindrop_width = raindrop.rect.width
        raindrop.x = raindrop_width + 2 * raindrop_width * raindrop_number
        raindrop.rect.x = raindrop.x
        raindrop.rect.y = raindrop.rect.height + 2 * raindrop.rect.height * row_number
        self.raindrops.add(raindrop)

    def _create_new_row(self):
        """Создает новый ряд капель дождя."""
        raindrop = Raindrop(self)
        raindrop_width, raindrop_height = raindrop.rect.size

        raindrop_number = raindrop_width
        row_number = -1 * raindrop_height
        while raindrop_number < (self.settings.screen_width - 2 * raindrop_width):
            self._create_raindrop(raindrop_number, row_number)
            raindrop_number += 2 * raindrop_width
            
    def _update_raindrops(self):
        self.raindrops.update()

        make_new_drops = False
        for raindrop in self.raindrops.copy():
            if raindrop.check_disappeared():
                self.raindrops.remove(raindrop)
                make_new_drops = True
        
            if make_new_drops:
                self._create_new_row()


    def _update_screen(self):
        """Обновляет изображения на экране и отображает новый экран."""
        self.screen.fill(self.settings.bg_color)
        self.raindrops.draw(self.screen)

        # Отображение последнего прорисованного экрана.
        pygame.display.flip()

if __name__ == '__main__':
    # Создание экземпляра и запуск игры.
    tr = TestRain()
    tr.run_game()

Модуль settings.py:

class Settings():
    """Класс для хранения всех настроек игры Дождик капает."""

    def __init__(self):
        """Инициализирует графические настройки игры."""
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230,230,230)

        # Настройки капель
        self.raindrop_speed = 1.0

Модуль raindrops.py:

import pygame
from pygame.sprite import Sprite

class Raindrop(Sprite):
    """Класс, представляющий одну каплю дождя."""

    def __init__(self, tr_game):
        """Инициализирует каплю и задает ее начальную позицию."""
        super().__init__()
        self.screen = tr_game.screen
        self.settings = tr_game.settings

        # Загрузка изображения капли и назначение атрибута rect.
        self.image = pygame.image.load('images/raindrop.png')
        self.rect = self.image.get_rect()

        # Каждая новая капля появляется в левом верхнем углу экрана.
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        # Сохранение точной горизонтальной позиции капли.
        self.y = float(self.rect.y)

    def check_disappeared(self):
        """Проверяет исчезла ли капля в нижней части экрана"""
        if self.rect.top > self.screen.get_rect().bottom:
            return True
        else:
            return False

    def update(self):
        """Перемещает каплю вниз по вертикали"""
        self.x -= self.settings.raindrop_speed
        self.rect.x = self.x

Заранее спасибо!

Ответы

▲ 5Принят

Ошибка направления каплей в последних 2 строках кода:

Вместо

    self.x -= self.settings.raindrop_speed
    self.rect.x = self.x

используйте

    self.y += self.settings.raindrop_speed         # заметите тоже  +=  вместо  -=
    self.rect.y = self.y

т.к. x означает не вертикальное, а горизонтальное направление:

введите сюда описание изображения