QinHuangYinZheng 2024-05-13 20:18 采纳率: 33.3%
浏览 10

pygame精灵编组问题

出现问题:
应为类型 '_SpriteSupportsGroup | AbstractGroup[_SpriteSupportsGroup | Any] | Iterable[_SpriteSupportsGroup | Any] | Any' (匹配的泛型类型 '_TSprite | AbstractGroup[_TSprite] | Iterable[_TSprite]'),但实际为 'Ship'

一、最底下一行为问题代码

    def prep_ship(self):
        """显示还余多少飞船"""
        self.ships=Group()
        for ship_number in range(self.stats.ships_left):
            ship=Ship(self.ai_game)
            ship.rect.x=10+ship_number*ship.rect.width
            ship.rect.y=10
            self.ships.add(ship)

二、与问题相关的模块
1.本模块的完整代码

import pygame.font
from pygame.sprite import Group
from py_03_ship import Ship

class Scoreboard():
    """显示得分信息的类"""

    def __init__(self, ai_game):
        """初始化显示得分涉及的属性"""
        self.ai_game=ai_game
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = ai_game.settings
        self.stats = ai_game.stats
        # 显示得分信息时使用的字体设置
        self.text_color = (30, 30, 30)
        self.font = pygame.font.SysFont(None, 48)  # 实例化字体对象
        # 准备最高分和当前得分的图像
        self.prep_score()
        self.prep_high_score()
        self.prep_level()
        self.prep_ship()

    def prep_score(self):
        """将得分渲染为图像"""
        #精确到小数点后某一位,第二个参数为负数,表示舍入到最近的10的整数倍
        rounded_score=round(self.stats.score,-1)
        score_str = f'Score:{rounded_score:,}'
        self.score_image = self.font.render(score_str, True,
                        self.text_color, self.settings.bg_color)
        #在屏幕的右上角显示得分
        self.score_rect=self.score_image.get_rect()
        self.score_rect.right=self.screen_rect.right-20
        self.score_rect.top=20

    def prep_high_score(self):
        """将最高分渲染为图像"""
        high_score = round(self.stats.high_score, -1)
        high_score_str = f"High Score:{high_score:,}"
        self.high_score_image = self.font.render(high_score_str, True,
                                                 self.text_color, self.settings.bg_color)
        # 将最高分放在屏幕顶部中央
        self.high_score_rect = self.high_score_image.get_rect()
        self.high_score_rect.centerx = self.screen_rect.centerx
        self.high_score_rect.top = self.score_rect.top
    def prep_level(self):
        """将等级渲染为图像"""
        level_str ='Level:'+str(self.stats.level)
        self.level_image = self.font.render(level_str, True,
                                                 self.text_color, self.settings.bg_color)
        # 将等级放在得分下方
        self.level_rect = self.level_image.get_rect()
        self.level_rect.right = self.score_rect.right
        self.level_rect.top = self.score_rect.bottom+40

    def prep_ship(self):
        """显示还余多少飞船"""
        self.ships=Group()
        for ship_number in range(self.stats.ships_left):
            ship=Ship(self.ai_game)
            ship.rect.x=10+ship_number*ship.rect.width
            ship.rect.y=10
            self.ships.add(ship)

    def check_high_score(self):
        """检查是否诞生了新的最高分"""
        if self.stats.score>self.stats.high_score:
            self.stats.high_score=self.stats.score
            self.prep_high_score()

    def show_score(self):
        """在屏幕上显示得分、等级和余下的飞船数"""
        self.screen.blit(self.score_image, self.score_rect)
        self.screen.blit(self.high_score_image, self.high_score_rect)
        self.screen.blit(self.level_image,self.level_rect)
        self.ships.draw(self.screen)#编组的draw方法

2.主代码完整代码

import sys  # 退出游戏的模块
import time
import pygame
from py_02_settings import Settings
from py_06_game_stats import GameStats
from py_03_ship import Ship
from py_04_bullet import Bullet
from py_05_alien import Alien
from py_07_button import Button
from py_08_scoreboard import Scoreboard


class AlienInversion:
    """管理游戏资源和行为的类"""

    def __init__(self):
        """初始化游戏,并创建游戏资源"""
        pygame.init()
        self.clock = pygame.time.Clock()  # 控制帧率
        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
        """
        # 指定幕布宽与高
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        # 设置当前窗口的标题栏
        pygame.display.set_caption('Alien Invasion')
        # 创建一个用于存储游戏统计信息的实例,并创建记分牌
        self.stats = GameStats(self)
        self.sb = Scoreboard(self)
        # 创建飞船实例
        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()  # 存储子弹的编组
        # 创建外星人实例
        self.aliens = pygame.sprite.Group()  # 存储外星人的编组
        self._create_fleet()
        # 让游戏一直处于非活动的状态
        self.game_active = False
        # 创建play按钮
        self.play_button = Button(self, 'Play')

    def run_game(self):
        """开始游戏的主循环"""
        while True:
            self._check_events()  # 响应按键和鼠标事件
            if self.game_active:
                self.ship.update()  # 根据移动的标志来调整飞船的位置
                self._update_bullets()  # 更新子弹的位置并删除已消失的子弹
                self._update_aliens()  # 更新外星人位置
            self._update_screen()  # 更新屏幕上的图像,并切换到新屏幕
            self.clock.tick(60)  # 保证循环一次60秒

    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_event(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_event(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

    def _check_play_button(self, mouse_pos):
        """在玩家单击Play按钮时开始新游戏"""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.game_active:
            # 还原游戏设置
            self.settings.initialize_dynamic_settings()
            # 重置游戏的统计信息
            self.stats.reset_stats()
            self.sb.prep_score()  # 分数
            self.sb.prep_level()#等级
            self.sb.prep_ship()#飞船数
            self.game_active = True
            # 清空外星人列表和子弹
            self.bullets.empty()
            self.aliens.empty()
            # 创建一个新的外星舰队,并将飞船放在屏幕中央
            self._create_fleet()
            self.ship.center_ship()
            # 隐藏光标
            pygame.mouse.set_visible(False)

    def _check_keydown_event(self, event):
        """响应按下"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_event(self, event):
        """响应释放"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _fire_bullet(self):
        """创建一颗子弹,并将其加入bullets编组"""
        if len(self.bullets) < self.settings.bullets_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        """更新子弹的位置并删除已消失的子弹"""
        # 更新子弹的位置
        self.bullets.update()
        # 删除已经消失的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)
        self._check_bullet_alien_collisions()

    def _check_bullet_alien_collisions(self):
        """响应子弹和外星人的碰撞"""
        # 删除发生碰撞的子弹和外星人,如果发生碰撞,返回字典collisions
        collisions = pygame.sprite.groupcollide(
            self.bullets, self.aliens, True, True)
        if collisions:
            # 如果击落,更新得分,保证每个被击落的外星人都计入得分
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
            self.sb.prep_score()
            self.sb.check_high_score()
        if not self.aliens:
            # 删除现有子弹并创建一个新的外星人舰队
            self.bullets.empty()
            self._create_fleet()
            self.settings.inscrease_speed()
            #提高等级
            self.stats.level+=1
            self.sb.prep_level()

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新屏幕"""
        self.screen.fill(self.settings.bg_color)  # 每次循环都重新绘制屏幕,fill()背景色填充
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()  # 子弹绘制到屏幕
        self.ship.blitme()  # 将飞船绘制到屏幕(没有编组)
        self.aliens.draw(self.screen)  # 编组的draw方法
        # 显示得分
        self.sb.show_score()
        # 如果游戏处于非活动状态,就绘制Play按钮
        if not self.game_active:
            self.play_button.draw_button()
        pygame.display.flip()  # 让最近绘制的屏幕可见

    def _create_fleet(self):
        """创建一个外星舰队"""
        # 创建一个外星人,再不断地添加,直到没有空间为止;外星人的间距为外星人的宽度
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size

        current_x, current_y = alien_width, alien_height
        while current_y < (self.settings.screen_height - 3 * alien_width):
            while current_x < (self.settings.screen_width - 2 * alien_width):
                self._creat_alien(current_x, current_y)
                current_x += 2 * alien_width
            # 添加一行外星人后,重置x值,并传递y值
            current_x = alien_width
            current_y += 2 * alien_height

    def _creat_alien(self, x_position, y_position):
        """创建一个外星人,并将其放在当前行中"""
        new_alien = Alien(self)
        new_alien.x = x_position
        new_alien.rect.x = x_position
        new_alien.rect.y = y_position
        self.aliens.add(new_alien)

    def _update_aliens(self):
        """检测是否有外星人位于屏幕边缘,并更新外星舰队的位置"""
        self._check_fleet_edges()
        self.aliens.update()
        # 检测外星人和飞船之间的碰撞
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()
        # 检查是否有外星人到达了屏幕的下边缘
        self._check_aliens_bottom()

    def _check_fleet_edges(self):
        """在有外星人到达边缘时采取相应的措施"""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """将整个外星舰队向下移动,并改变它们的方向"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _ship_hit(self):
        """响应飞船和外星人的碰撞"""
        if self.stats.ships_left > 0:
            # 将飞船数量减1,并更新积分牌
            self.stats.ships_left -= 1
            self.sb.prep_ship()
            # 清空外星人列表和子弹
            self.aliens.empty()
            self.bullets.empty()
            # 创建一个新的外星舰队,将飞船放在屏幕底部的中央
            self._create_fleet()
            self.ship.center_ship()
            # 暂停
            time.sleep(0.5)
        else:
            self.game_active = False
            pygame.mouse.set_visible(True)

    def _check_aliens_bottom(self):
        """检查是否有外星人到达了屏幕的下边缘"""
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= self.settings.screen_height:
                # 像飞船被撞到一样处理
                self._ship_hit()
                break


if __name__ == '__main__':
    ai = AlienInversion()
    ai.run_game()
  • 写回答

3条回答 默认 最新

  • 笑面虎 2024-05-13 20:20
    关注

    以下内容由CHATGPT及笑面虎共同生成、有用望采纳:


    您想要解决的问题

    您提问的目的是解决在使用pygame库开发游戏时遇到的一个关于精灵编组(Group)的问题。具体来说,您在尝试将创建的Ship对象添加到Group中时,遇到了类型不匹配的错误。

    问题出现原因

    根据您提供的错误信息和代码,问题出现的原因是在创建Group对象时,您可能没有正确地从pygame.sprite模块导入Group类。在Python中,如果导入了错误的类型或者没有正确地导入所需的类,就会出现类型不匹配的错误。

    问题解决方案

    要解决这个问题,您需要确保正确地从pygame.sprite模块导入了Group类。以下是解决这个问题的步骤:

    1. 确保在文件顶部正确导入了Group类。
    2. 在创建Group对象时,使用正确的类型。

    提供代码

    以下是修改后的Scoreboard类中的prep_ship方法的代码:

    import pygame
    from pygame.sprite import Group
    from py_03_ship import Ship
    
    class Scoreboard():
        # ... [其余代码保持不变] ...
    
        def prep_ship(self):
            ""“显示还余多少飞船”""
            # 确保self.ships是Group类的实例
            if not isinstance(self.ships, Group):
                self.ships = Group()
            for ship_number in range(self.stats.ships_left):
                ship = Ship(self.ai_game)
                ship.rect.x = 10 + ship_number * ship.rect.width
                ship.rect.y = 10
                self.ships.add(ship)
    

    代码运行方式

    要运行您的代码,您需要有Python环境,并且安装了pygame库。您可以在命令行中运行您的主程序文件,通常是AlienInversion.py

    代码预期运行结果

    预期中,修改后的代码将能够成功创建Group对象,并将Ship对象添加到该编组中,而不会遇到类型不匹配的错误。游戏的其他部分应该能够正常运行,显示得分、等级和剩余的飞船数量。

    推荐相关链接

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 5月13日

悬赏问题

  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 在虚拟机环境下完成以下,要求截图!
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见