Python游戏之Pygame——太空飞机大战(一)

学习Python,最好的办法是实战,实战!我们知道,有无数的先人和大侠提供了非常多的软件包供我们选用。有时候学习是一件很枯燥的事,玩游戏就不一样了。我们玩的最多的游戏是别人开发的,能不能开发出一款自己的游戏呢?当然大型游戏是不太现实的,用二三天事件写一个飞机大战的游戏还是有可能的。
直接上效果图,由于自己一边玩一边抓图,可能抓不出最好的效果,先上两张吧。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200519174555107.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhc19hX2NvZGVy,size_16,color_FFFFFF,t_70#pic_center
Python游戏之Pygame——太空飞机大战(一)_第1张图片
Python游戏之Pygame——太空飞机大战(一)_第2张图片
好了,为什么要上图呢?都说有图有真相,对吧,不然大家以为你嘴把式。其实这里上图不光是有图有真相,而是让大家看看游戏中大概有哪些元素。
好了,有哪些元素呢?我放飞机(可以有多种)、敌方不同种类的飞机,发射不同的子弹或导弹,敌机坠毁后可能掉出来弹药包啊,医药包啊啥的,英雄战机能捡到就可以用。捡不到就浪费了。背景是流动的星空,哪些白点星星向下按照不同的速度移动,营造出战机在太空的氛围(为了更好的太空氛围,有兴趣的朋友可以自己调试一下相关参数,一定会有更逼真的效果)。
小结一下,飞机大战的元素有如下几点:
1、英雄战机
2、敌机
3、英雄战机发射的子弹(可能有子弹、导弹、核弹等),当然敌机只能发射子弹和导弹。不然危机时刻咋干他呢?
4、敌机掉出来的宝贝(各种啊,可以自己配制添加)
5、星空背景
当然,现在还没有说相关统计、得分啊什么的,有兴趣的朋友可以看完后自己添加。位置都留好了,窗口最上方一条高度为xx像素的空间已经留好了。哈哈
简单说一下,这个游戏也是用了 pygame的Layer 功能,不清楚的朋友可以看我上一篇文章(Python:模拟windows命令按钮——一文学习Pygame分层显示)了解一下,非常简单。
为了程序的可扩展性和可读性,对飞机、子弹等使用配置文件给出相关参数,有兴趣的朋友可以通过扩展配置文件增加飞机种类、子弹类型等,让自己的游戏更加炫酷,而不需要更改任何代码。
部分配置文件如下:

IMAGE_PATH = "assets/images/"

ENEMY_BULLETS_TYPE = {1: 'EBULLET_1', 2: 'EBULLET_2'}
ENEMY_MISSILE_TYPE = {11: 'EMISSILE_1'}
HERO_BULLETS_TYPE  = {21: 'HBULLET_1', 22: 'HBULLET_2', 23: 'P_BULLET'}
HERO_MISSILES_TYPE = {31: 'HMISSILE_1', 32: 'HMISSILE_2'}
HERO_NECLEAR_TYPE  = {41: 'NUCLEAR'}

BULLETS = {
    'EBULLET_1' : {'IMAGE': 'enemy_B01.png', 'SPEED':  16, 'DESTROY_VALUE': 10,    'SP_FACTOR': 1, 'LAYER': 10},
    'EBULLET_2' : {'IMAGE': 'enemy_B02.png', 'SPEED':  16, 'DESTROY_VALUE': 10,    'SP_FACTOR': 1, 'LAYER': 10},
    'EMISSILE_1': {'IMAGE': 'enemy_M01.png', 'SPEED':  16, 'DESTROY_VALUE': 50,    'SP_FACTOR': 1, 'LAYER': 10},
    'HBULLET_1' : {'IMAGE': 'hero_B01.png',  'SPEED': -22, 'DESTROY_VALUE': 30,    'SP_FACTOR': 1, 'LAYER': 10},
    'HBULLET_2' : {'IMAGE': 'hero_B02.png',  'SPEED': -22, 'DESTROY_VALUE': 30,    'SP_FACTOR': 1, 'LAYER': 10},
    'P_BULLET':   {'IMAGE': 'hero_BP.png',   'SPEED': -22, 'DESTROY_VALUE': 60,    'SP_FACTOR': 1, 'LAYER': 10},
    'HMISSILE_1': {'IMAGE': 'hero_M01.png',  'SPEED': -25, 'DESTROY_VALUE': 120,   'SP_FACTOR': 1, 'LAYER': 10},
    'HMISSILE_2': {'IMAGE': 'hero_M02.png',  'SPEED': -25, 'DESTROY_VALUE': 120,   'SP_FACTOR': 1, 'LAYER': 10},
    'NUCLEAR'  :  {'IMAGE': 'hero_N01.png',  'SPEED': -30, 'DESTROY_VALUE': 99999, 'SP_FACTOR': 1, 'LAYER': 10}}

ENEMY_PLANES = {
    'ENEMY_F01': {'IMAGE': 'enemy_F01.png', 'DEFENCE': 100, 'X_SPD': 6, 'Y_SPD': 10, 'B_COUNT': 2, 'M_COUNT': 0, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 500},
    'ENEMY_F02': {'IMAGE': 'enemy_F02.png', 'DEFENCE': 110, 'X_SPD': 6, 'Y_SPD': 12, 'B_COUNT': 1, 'M_COUNT': 0, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 400},
    'ENEMY_F03': {'IMAGE': 'enemy_F03.png', 'DEFENCE': 120, 'X_SPD': 6, 'Y_SPD': 14, 'B_COUNT': 2, 'M_COUNT': 1, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 500},
    'ENEMY_F04': {'IMAGE': 'enemy_F04.png', 'DEFENCE': 130, 'X_SPD': 6, 'Y_SPD': 15, 'B_COUNT': 2, 'M_COUNT': 0, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 600},
    'ENEMY_F05': {'IMAGE': 'enemy_F05.png', 'DEFENCE': 140, 'X_SPD': 6, 'Y_SPD': 13, 'B_COUNT': 1, 'M_COUNT': 0, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 700},
    'ENEMY_F06': {'IMAGE': 'enemy_F06.png', 'DEFENCE': 150, 'X_SPD': 6, 'Y_SPD': 11, 'B_COUNT': 2, 'M_COUNT': 0, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 500},
    'ENEMY_F07': {'IMAGE': 'enemy_F07.png', 'DEFENCE': 160, 'X_SPD': 6, 'Y_SPD': 12, 'B_COUNT': 2, 'M_COUNT': 1, 'SP_FACTOR': 0.5, 'LAYER': 20, 'COLLISION': 600}}

HERO_PLANES = {
    'HERO_F01': {'IMAGE': 'hero_F01.png', 'DEFENCE': 9999, 'X_SPD': 50, 'Y_SPD': 20, 'B_COUNT': 4, 'M_COUNT': 1, 'SP_FACTOR': 1, 'QUANTITY': 3, 'LAYER': 30},
    'HERO_F02': {'IMAGE': 'hero_F02.png', 'DEFENCE': 9999, 'X_SPD': 50, 'Y_SPD': 20, 'B_COUNT': 2, 'M_COUNT': 2, 'SP_FACTOR': 1, 'QUANTITY': 3, 'LAYER': 30},
    'HERO_F03': {'IMAGE': 'hero_F03.png', 'DEFENCE': 9999, 'X_SPD': 50, 'Y_SPD': 20, 'B_COUNT': 4, 'M_COUNT': 1, 'SP_FACTOR': 1, 'QUANTITY': 3, 'LAYER': 30}}

HERO_PLANE_MOVE = {K_a: 'GO_LEFT', K_w: 'GO_UP', K_s: 'GO_DOWN', K_d: 'GO_RIGHT'}
HERO_PLANE_SHOOT = {K_j: 'BULLET', K_k: 'MISSILE', K_l: 'P_BULLET', K_i: ' NUCLEAR'}

HERO_PLANE_QTY = 5

PACKAGE_LIST = [None, 'P_BULLET', 'DEFENCE', 'NUCLEAR']

PACKAGES = {
    'P_BULLET': {'IMAGE': 'bulletBox.png',  'QUANTITY': 1000, 'X_SPD': 5, 'Y_SPD': 10, 'SP_FACTOR': 0.5, 'LAYER': 50},
    'DEFENCE':  {'IMAGE': 'healthBox.png',  'QUANTITY': 1000, 'X_SPD': 5, 'Y_SPD': 10, 'SP_FACTOR': 0.5, 'LAYER': 50},
    'NUCLEAR':  {'IMAGE': 'nuclearBox.png', 'QUANTITY': 1,    'X_SPD': 5, 'Y_SPD': 10, 'SP_FACTOR': 0.5, 'LAYER': 50}}

有了配置文件,我们来做一个子弹类。直接上代码:

class Bullet(Sprite):
    def __init__(self, bulletType, position, layerGroup, bGroup):
        self.type = bulletType
        self._layer = BULLETS[self.type]['LAYER']
        self.groups = layerGroup, bGroup
        super().__init__(self.groups)

        self.image = pygame.image.load(IMAGE_PATH + BULLETS[self.type]['IMAGE']).convert_alpha()
        self.rect = Rect(position, self.image.get_size())

        self.destroyValue = BULLETS[self.type]['DESTROY_VALUE']
        self.speed = BULLETS[self.type]['SPEED']
        self.speedupFactor = BULLETS[self.type]['SP_FACTOR']

        self.lastTick = 0

    # 目前 子弹 和 导弹都是从发射点开始直线运行,可以考虑将 英雄 的导弹 改为制导模式
    def update(self, *args):
        tick = args[0]
        if tick < self.lastTick:
            return

        self.lastTick = tick

        self.rect.top += self.speed * self.speedupFactor

        # 处理飞出游戏界面的子弹(包含敌我双方子弹)
        # GAME_AREA_START_HEIGHT 高度用于未来显示游戏状态相关信息。
        if self.rect.top >= SCREEN_SIZE[1] or self.rect.bottom <= GAME_AREA_START_HEIGHT:
            self.kill()

Bullet类的初始化第一部分定义了自己所在的groups,一个是 Layer groups,用于显示和更新位置时使用,一个是 功能组。子弹类是通用的,适用英雄战机发射,也适用敌机发射。子弹的类型、子弹造型、子弹的速度等通过配置文件来增删改。
子弹速度目前只提供Y轴的,如果想使用制导导弹(需要添加X 速度,并引入相关的math包,以及使用pygame的transform功能调整导弹的角度等) 有兴趣的朋友可以自行探索。
子弹的基本属性就是破环力,加速因子未来可以用于设置难度。
子弹的唯一方法就是update(),用于更新自己的位置,以及出界后自毁。
好了第一部分就到这里。下一部分我将给出英雄战机和敌机类以及相关方法。

你可能感兴趣的:(Pygame,Sprite,Group,Sprite)