Fight Aliens 子弹夹清除和限制子弹数量功能

基础版我们用数组list来保存创建的子弹实现,但是有很多问题,我们这里使用pygame里的sprite里提供的一个容器Group来实现
# Group对象相当于一个列表,在列表中可以保存游戏中的Surface对象
# 特点:
#     1.可以对group中的对象做统一的操作
#     2.可以直接通过元素删除自己,而不需要获取group
# group() 中存放的元素必须继承 Sprite 
具体实现如下:
在bullet模块中bullet.py文件中调整如下: 
 1 # -*- coding: utf-8 -*-
 2 # 作者: guos
 3 # 日期: 2023/3/29
 4 import pygame
 5 from pygame.sprite import Sprite
 6 
 7 class Bullet(Sprite):
 8     """
 9         表示子弹的类
10     """
11     def __init__(self, screen, gc, ship):
12         # 因为继承Sprite, 而没有调用父类Sprite的init方法,导致其无法初始化父类的属性, 所以需要调用如下方法
13         super().__init__()
14         # fill(color, rect)
15         self.color = gc.bullet_color  # 子弹的颜色
16         # Rect(left, top, width, height), left -> x轴; top -> y轴; width -> 宽度; height -> 高度;
17         self.rect = pygame.Rect(0, 0, gc.bullet_width, gc.bullet_height)  # 表示子弹矩形位置 和大小
18         # 设置子弹的位置,子弹的x和y和飞船保持一致
19         self.rect.centerx = ship.rect.centerx
20         self.rect.centery = ship.rect.centery
21 
22 
23         self.screen = screen
24         self.gc = gc
25 
26     def draw_bullet(self):
27         """
28             在屏幕中绘制子弹
29         :return:
30         """
31         self.screen.fill(self.color, self.rect)
32 
33     def update(self):
34         """
35             更新子弹的位置,实现飞出去的效果
36         :return:
37         """
38         self.rect.y -= self.gc.bullet_speed
39         # 将飞出屏幕的子弹销毁
40         if self.rect.bottom < 0:
41             # 销毁子弹 --> 从弹夹中删除
42             # list.remove(item), 但是列表管理比较麻烦不合适
43             self.kill()
44         # 重绘一下子弹
45         self.draw_bullet()

main.py模块中修改如下:

# -*- coding: utf-8 -*-
# 作者: guos
# 日期: 2023/3/29

# 游戏的主文件,使用该文件来启动游戏
import pygame
from pygame.sprite import Group
import sys

from game_config import GameConfig
from ship import Ship
from bullet import Bullet

# 创建配置对象
gc = GameConfig()

# 初始化
pygame.init()
# 设置窗口大小
screen = pygame.display.set_mode(gc.size)
# 设置窗口的标题
pygame.display.set_caption(gc.title)

# 创建一个飞船实例对象
ship = Ship(screen, gc)

#  弹夹 -- 存放子弹的列表
# bullets = []
bullets = Group()

# 创建主循环
while True:
    # 处理事件
    for event in pygame.event.get():
        # 处理退出的事件
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            # 键盘按下
            if event.key == pygame.K_LEFT:
                # 向左移动,设置飞船的移动方向,而不是控制飞船移动 -1
                # 这里把这个方向 放入到 配置对象里
                gc.ship_dir = -1
            elif event.key == pygame.K_RIGHT:
                # 向右移动 1
                gc.ship_dir = 1
            elif event.key == pygame.K_SPACE:
                # 限制子弹数量
                if len(bullets) < gc.bullet_count:
                    # 点击空格键开跑 创建子弹实例对象
                    # 当我们按下空格键后创建,并append到弹夹中
                    # bullets.append(Bullet(screen, gc, ship))
                    bullets.add(Bullet(screen, gc, ship))
        elif event.type == pygame.KEYUP:
            # 何时将 ship_dir 设置为0
            # 当键盘松开,如果此时为向左移动或者向右移动时
            if gc.ship_dir == 1 and event.key == pygame.K_RIGHT or gc.ship_dir == -1 and event.key == pygame.K_LEFT:
                gc.ship_dir = 0

    # 设置窗口背景颜色, rgb值
    screen.fill(gc.bg_color)

    # 更新飞船的位置 必须在显示之前
    ship.update()

    # # 遍历弹夹实现子弹无限发射,而不是按一下发一个
    # for bl in bullets:
    #     # 更新子弹的位置
    #     bl.update()
    #     # 子弹显示 子弹在飞船后面展示会显示在飞船上面,如果想在飞船下面,先展示子弹
    #     bl.draw_bullet()
    # 只更新类位置,但无法调用 bullets里每个元素的draw_bullet, 所以需要自己调用的都写到update里来实现
    bullets.update()
    # 查看子弹数量是否有变化
    # print(len(bullets))

    # 飞船显示
    ship.blit_ship()

    # 对窗口进行重绘
    pygame.display.flip()

 game_config.py文件中的配置调整如下:

# -*- coding: utf-8 -*-
# 作者: guos
# 日期: 2023/3/29

# 该模块[即一个py文件就是一个模块,命名小写开头]用来存储游戏的配置信息
class GameConfig:
    # 类名:大驼峰
    def __init__(self):
        # 直接将配置信息,存储到GameConfig实例对象中
        self.width = 800  # 宽度
        self.height = 600  # 高度
        self.title = 'Fight Aliens'  # 外星人入侵 游戏标题
        self.bg_color = (230, 230, 230)  # 窗口背景颜色
        self.ship_dir = 0  # 飞船移动的方向 -1 向左 1 向右
        self.ship_speed = 1  # 飞船移动的速度
        # 可以根据充值来提升武器的配置参数
        self.bullet_color = (0, 0, 0)  # 子弹的颜色
        self.bullet_width = 3  # 子弹的宽度
        self.bullet_height = 15  # 子弹的高度
        self.bullet_speed = 1  # 子弹的速度
        self.bullet_count = 3  # 限制子弹的数量【即满屏最多有三个】

    @property
    def size(self):
        #  @property 使 size变为属性,可以直接 对象.size 来获取值
        # 这里使用来属性方法,返回元组 来动态计算窗口的大小
        return self.width, self.height

 

posted @ 2023-03-30 11:23  以赛亚  阅读(12)  评论(0编辑  收藏  举报