【问题标题】:What is the correct way to add a surface positional argument to the pygame draw method? [duplicate]向 pygame draw 方法添加表面位置参数的正确方法是什么? [复制]
【发布时间】:2021-08-20 01:58:11
【问题描述】:

我正在尝试使用 draw 方法来更新 pygame 中的屏幕。

但是当我运行我的程序时出现以下错误:

➜  Stars python3 stars.py
pygame 2.0.1 (SDL 2.0.14, Python 3.9.6)

Traceback (most recent call last):
  File "/Users/Desktop/python/Stars/stars.py", line 93, in <module>
    st.run_game()
  File "/Users/Desktop/python/Stars/stars.py", line 31, in run_game
    self._update_screen()
  File "/Users/Desktop/python/Stars/stars.py", line 84, in _update_screen
    star_draw.draw(self.screen)
TypeError: draw() missing 1 required positional argument: 'surface'

我的程序由三个 python 文件组成:stars.py、star.py 和 settings.py。

stars.py 包含管理“游戏”的 Stars 类。

star.py 包含管理单个星的 Star 类。

settings.py 包含管理屏幕设置的 Settings 类。

stars.py:

import sys
import pygame
from settings import Settings
from star import Star
# Make a grid of stars appear on the screen
# /images/star.bmp
# A class to manage a star
class Stars:
    """Overall class to manage the game."""
    def __init__(self):
        """Initialize the game and create game resources."""
        # Initialize pygame.
        pygame.init()
        # Make an instance of the Settings class and assign it.
        self.settings = Settings()
        # Make a screen with dimensions defined in the settings module.
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        # Set a caption on the pygame.
        pygame.display.set_caption("Stars")
        # Create a group for the stars.
        self.stars = pygame.sprite.Group()
        # Add an attribute that is a method to create stars.
        self._create_stars()
        self.star = Star(self)

    def run_game(self):
        """Start the main loop for the game."""
        while True:
            self._check_events()
            self._update_screen()

    def _check_events(self):
        """Respond to keypresses and mouse events."""
        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):
        """Respond to keypresses."""
        if event.key == pygame.K_q:
            sys.exit()

    def _create_stars(self):
        """Create a sky full of stars."""
        # Create a star and find the number of stars in a row.
        # Spacing between each star is equal to two star widths.
        star = Star(self)
        star_width, star_height = star.rect.size
        available_space_x = self.settings.screen_width - (star_width)
        number_stars_x = available_space_x // (2 * star_width)

        # Determine the number of rows of stars that fit on the screen.
        # Fill most of the screen with stars.
        available_space_y = (self.settings.screen_height - (2 * star_height))
        number_rows = available_space_y // (2 * star_height)

        # Fill the sky with stars.
        # For every row in the total amount of rows.
        for row_number in range(number_rows):
            # For every star in the total amount of stars.
            for star_number in range(number_stars_x):
                # Call _create_star with the loops as arguments.
                self._create_star(star_number, row_number)

    def _create_star(self, star_number, row_number):
        """Create a star and place it in the row."""
        star = Star(self)
        star_width, star_height = star.rect.size
        star.x = star_width + (2 * star_width) * star_number
        star.rect.x = star.x
        star.rect.y = star.rect.height + (2 * star.rect.height) * row_number
        # Add the star to the group stars.
        self.stars.add(star)

    def _update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        # Redraw the screen during each pass through the loop.
        self.screen.fill(self.settings.bg_color)
        # Draw the star on the screen
        self.star.draw(self.screen)
        # Make the most recently drawn screen visible.
        pygame.display.flip()


if __name__ == '__main__':
    # Make a game instance, and run the game.
    st = Stars()
    st.run_game()

star.py:

import pygame
from pygame.sprite import Sprite

class Star(pygame.sprite.Sprite):
    """A class to manage a single star."""

    def __init__(self, star_game):
        """Initialize the star and set it's starting position."""
        super().__init__()
        self.screen = star_game.screen

        # Load the star image and set its rect attribute.
        self.image = pygame.image.load('images/star.bmp')
        self.rect = self.image.get_rect()

        # Start each new star near the top left of the screen.
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        # Store the star's exact vertical position.
        self.y = float(self.rect.y)
        self.draw = pygame.sprite.Group.draw

settings.py:

class Settings:
    """A class to store all settings for the star game."""

    def __init__(self):
        """Initialize the game's settings."""
        # Screen settings
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (50, 50, 50)

【问题讨论】:

  • 抱歉,在我有机会尝试更改之前,我最初接受了它。您建议的更改给了我另一个错误。我会重新接受答案,因为我相信它解决了一个问题,但这是我在实施更改后得到的错误,你能帮我理解吗?文件“/Users/Desktop/python/Stars/stars.py”,第 83 行,在 _update_screen self.star.draw(self.screen) AttributeError: 'Star' object has no attribute 'draw'
  • self.stars.draw(self.screen)!关注s(复数)。 Group 实例是self.stars。我在回答中提到了这一点。请仔细阅读答案。
  • 我的错,我重新接受了这个问题,如果你从我的问题中删除了一个赞成票,你介意恢复它吗?
  • 感谢您发现我的错字,它正在工作! :) 非常感谢!

标签: python class pygame


【解决方案1】:

pygame.sprite.Group.draw 是一种方法。必须使用 pygame.sprite.Group 的实例调用它。

pygame.sprite.Group.draw()pygame.sprite.Group.update()pygame.sprite.Group提供的方法。

前者将update 方法委托给包含的pygame.sprite.Sprites - 你必须实现该方法。见pygame.sprite.Group.update()

在组中的所有 Sprite 上调用 update() 方法 [...]

后者使用包含的pygame.sprite.Sprites 的imagerect 属性来绘制对象-您必须确保pygame.sprite.Sprites 具有所需的属性。见pygame.sprite.Group.draw()

将包含的 Sprite 绘制到 Surface 参数。这将Sprite.image 属性用于源表面,并使用Sprite.rect。 [...]

删除self.draw = pygame.sprite.Group.draw 行,这是误导。 Star 对象不需要 draw 方法,因为它是由 Group 绘制的。

只要打电话:

self.stars.draw(self.screen)

方法_update_screen

class Stars:
    # [...]

    def _update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        # Redraw the screen during each pass through the loop.
        self.screen.fill(self.settings.bg_color)
        
        # Draw the star on the screen
        self.stars.draw(self.screen)        # <--
        
        # Make the most recently drawn screen visible.
        pygame.display.flip()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2022-09-30
    • 2018-07-20
    • 2019-01-06
    相关资源
    最近更新 更多