pygame之《飞机大战》(五)

前言:

本章将实现:

  1. enemy0, enemy1, enemy2的实现。
  2. 飞机血量HP的实现。
  3. 不同enemy飞机发射不同子弹。

编程代码:

模块导入:

import pygame
import time
import random
from pygame.locals import *

全局变量:

#全局变量
hit_score = 0
#飞机HP
HP_list = [1, 15, 25, 5]
#敌机子弹类型
bullet_type = ["bullet1.png", "bullet-1.gif", "bullet2.png", "bullet.png"]
#飞机大小
plane_size = [{"width":51, "height":39}, {"width":69, "height":89}, {"width":165, "height":246}, {"width":100, "height":124}, ]
#敌机引用列表
enemy0_list = []#小飞机
enemy0_maximum = 6
enemy1_list = []#boss1
enemy1_maximum = 1
enemy2_list = []#boss2
enemy2_maximum = 1

1 - Base类和BasePlane类的优化:
有些类中不需要Base类的某些变量,即从《飞机大战》(四)中对Base类进行优化。

class Base(object):
    """docstring for Base"""
    def __init__(self, screen_temp, x, y, image_name):
        self.x = x
        self.y = y
        self.screen = screen_temp
        self.image = pygame.image.load(image_name)


class BasePlane(Base):
    """docstring for BasePlane"""
    def __init__(self, plane_type, screen_temp, x, y, image_name, picture_num, HP_temp):
        Base.__init__(self, screen_temp, x, y, image_name)
        self.bullet_list = [] #存储发射出去的子弹的引用
        self.plane_type = plane_type #飞机类型标示, 3是hero
        #爆炸效果用的如下属性
        self.hitted = False #表示是否要爆炸
        self.bomb_picture_list = [] #用来存储爆炸时需要的图片
        self.bomb_picture_num = picture_num #飞机爆炸效果的图片数量
        self.image_num = 0#用来记录while True的次数,当次数达到一定值时才显示一张爆炸的图,然后清空,,当这个次数再次达到时,再显示下一个爆炸效果的图片
        self.image_index = 0#用来记录当前要显示的爆炸效果的图片的序号
        self.HP = HP_temp

    def display(self):
        """显示玩家的飞机"""
        global hit_score
        global HP_list
        #如果被击中,就显示爆炸效果,否则显示普通的飞机效果
        if self.hitted == True and self.image_index < self.bomb_picture_num and self.HP <= 0:
            if self.plane_type != 3 and self.image_index == 0 and self.image_num == 0:
                hit_score += HP_list[self.plane_type]
            self.screen.blit(self.bomb_picture_list[self.image_index], (self.x, self.y))
            self.image_num += 1
            if self.image_num == 7: #每7次循环换一张图片
                self.image_num = 0
                self.image_index += 1
            # if self.image_index > self.bomb_picture_num-1:
            #     # time.sleep(1)
            #     # del_plane(self)
            #     # exit()#调用exit让游戏退出
            #     pass
        elif self.image_index < self.bomb_picture_num:
            self.screen.blit(self.image, (self.x, self.y))
        if self.hitted == True and not self.bullet_list and self.image_index >= self.bomb_picture_num:
            del_plane(self) #删除被击中敌机的对象
        bullet_list_out = []#越界子弹
        for bullet in self.bullet_list:
            bullet.display()
            bullet.move()
            if bullet.judge(): #判断子弹是否越界
                bullet_list_out.append(bullet)
        #删除越界子弹
        for bullet in bullet_list_out: 
            self.bullet_list.remove(bullet)
    #创建出爆炸效果的图片的引用
    def crate_images(self, bomb_picture_name):
            for i in range(1, self.bomb_picture_num + 1):
                self.bomb_picture_list.append(pygame.image.load("./feiji/" + bomb_picture_name + str(i) + ".png"))

    #判断是否被击中
    def isHitted(self, plane, width, height):# widht和height表示范围
        if plane.bullet_list:
            for bullet in plane.bullet_list:
                if bullet.x > self.x+8 and bullet.x < self.x + width and bullet.y+8 > self.y and bullet.y < self.y + height:
                    plane.bullet_list.remove(bullet) #删除击中的子弹
                    self.hitted = True
                    self.HP -= 1

2 - HeroPlane类:
为Hero飞机添加HP变量,以及注释无用代码。

class HeroPlane(BasePlane):
    def __init__(self, screen_temp):
        BasePlane.__init__(self, 3, screen_temp, 210, 700, "./feiji/hero1.png", 4, HP_list[3]) #super().__init__()
        BasePlane.crate_images(self, "hero_blowup_n")
        self.key_down_list = [] #用来存储键盘左右移动键

    def move_left(self):
        self.x -= 5

    def move_right(self):
        self.x += 5

    #控制飞机左右移动范围
    def move_limit(self):
        if self.x < 0:
            self.x = -2
        elif self.x + 100 > 480:
            self.x = 380

    def fire(self):
        if len(self.bullet_list) < 5:
            # print("bullet_list=%d"%len(self.bullet_list))
            self.bullet_list.append(Bullet(self.screen, self.x, self.y))

    #键盘按下向列表添加左右按键
    def key_down(self, key):
        self.key_down_list.append(key)

    #键盘松开向列表删除左右按键
    def key_up(self, key):
        if len(self.key_down_list) != 0: #判断是否为空
            self.key_down_list.pop(0)

    #当一直按下键盘时调用移动函数
    def press_move(self):
        if len(self.key_down_list) != 0:
            if self.key_down_list[0] == K_LEFT:
                self.move_left()
            elif self.key_down_list[0] == K_RIGHT:
                self.move_right()
    def bomb(self):
        self.hitted = True

    # #是否击中hero判断
    # def hitHero(self, enemy_temp):
    #     if enemy_temp.bullet_list is not None:
    #         for bullet in enemy_temp.bullet_list:
    #             if bullet.x > self.x and bullet.x < self.x+100 and bullet.y > self.y and bullet.y < self.y + 124:
    #                 enemy_temp.bullet_list.remove(bullet)
    #                 self.bomb()

3 - enemy0、enemy1、enemy2的实现:

class Enemy0Plane(BasePlane):
    """敌机的类"""
    def __init__(self, screen_temp):
        random_num_x = random.randint(0, 430)
        random_num_y = random.randint(-50, -40)
        BasePlane.__init__(self, 0, screen_temp, random_num_x, random_num_y, "./feiji/enemy0.png", 4, HP_list[0])
        BasePlane.crate_images(self, "enemy0_down")

    def move(self):
        self.y += 2

    def fire(self):
        if not self.hitted:
            random_num = random.randint(1, 200)
            if random_num == 8 or random_num == 70 and len(self.bullet_list) < 3:
                self.bullet_list.append(EnemyBullet(self.screen, self.x, self.y, self))


class Enemy1Plane(BasePlane):
    """敌机的类"""
    def __init__(self, screen_temp):
        BasePlane.__init__(self, 1, screen_temp, 205, -90, "./feiji/enemy1.png", 4, HP_list[1])
        BasePlane.crate_images(self, "enemy1_down")
        self.direction = "right" #用来存储飞机默认显示方向


    def move(self):
        if self.direction == "right":
            self.x += 3
        elif self.direction == "left":
            self.x -= 3
        # 方向判断
        if self.x+70 > 480:
            self.direction ="left"
        elif self.x < 0:
            self.direction = "right"
        if self.y < 50:
            self.y += 3

    def fire(self):
        random_num = random.randint(1, 100)
        if random_num == 8 or random_num == 70 and len(self.bullet_list) < 6:
            self.bullet_list.append(EnemyBullet(self.screen, self.x, self.y, self))


class Enemy2Plane(BasePlane):
    """敌机的类"""
    def __init__(self, screen_temp):
        BasePlane.__init__(self, 2, screen_temp, 158, -246, "./feiji/enemy2.png", 5, HP_list[2])
        BasePlane.crate_images(self, "enemy2_down")
        self.direction = "right" #用来存储飞机默认显示方向

    def move(self):
        if self.direction == "right":
            self.x += 2
        elif self.direction == "left":
            self.x -= 2
        # 方向判断
        if self.x+165 > 480:
            self.direction ="left"
        elif self.x < 0:
            self.direction = "right"
        if self.y < 0:
            self.y += 2

    def fire(self):
        random_num = random.randint(1, 50)
        if random_num == 8 or random_num == 40 and len(self.bullet_list) < 9:
            self.bullet_list.append(EnemyBullet(self.screen, self.x, self.y, self))

4 - 子弹类的优化:
EnemyBullet通过飞机图片的大小来确定发射的位置,如x+plane_size[plane.plane_type][“width”]/2。

class BaseBullet(Base):
    """docstring for BaseBullet"""
    def __init__(self, screen_temp, x, y, image_name):
        Base.__init__(self, screen_temp, x, y, image_name)

    def display(self):
        self.screen.blit(self.image, (self.x, self.y))


class Bullet(BaseBullet):
    def __init__(self, screen_temp, x, y):
        BaseBullet.__init__(self, screen_temp, x+40, y-14, "./feiji/bullet.png")

    def move(self):
        self.y -= 12

    def judge(self):
        if self.y < 0:
            return True
        else:
            return False


class EnemyBullet(BaseBullet):
    global bullet_type
    global plane_size
    def __init__(self, screen_temp, x, y, plane):
        BaseBullet.__init__(self, screen_temp, x+plane_size[plane.plane_type]["width"]/2, y+plane_size[plane.plane_type]["height"]/2, "./feiji/"+bullet_type[plane.plane_type])

    def move(self):
        self.y += 5

    def judge(self):
        if self.y > 852:
            return True
        else:
            return False

函数:

1 - 回收被击中的飞机:

def del_plane(plane):
    """回收被击中的敌机的对象"""
    global hit_score
    global enemy0_list
    global enemy1_list
    global enemy2_list

    if plane in enemy0_list:
        enemy0_list.remove(plane)
    elif plane in enemy1_list:
        enemy1_list.remove(plane)
    elif plane in enemy2_list:
        enemy2_list.remove(plane)

填充main()函数:

def main():
    global hit_score
    global HP_list
    global enemy0_list
    global enemy0_maximum
    global enemy1_list
    global enemy1_maximum
    global enemy2_list
    global enemy2_maximum

    hit_score_temp = hit_score

    #1. 创建窗口
    screen = pygame.display.set_mode((480,852),0,32)

    #2. 创建一个背景图片
    background = pygame.image.load("./feiji/background.png")

    #3. 创建一个飞机对象
    hero = HeroPlane(screen)

    #4. 创建一个敌机
    # enemy = Enemy0Plane(screen)

    while True:
        if hit_score > hit_score_temp:
            hit_score_temp = hit_score
            print("得分: %d"%hit_score)
        #创建敌机
        random_num = random.randint(1, 100)
        if random_num == 29 or random == 50 and len(enemy0_list) < enemy0_maximum:
            enemy0_list.append(Enemy0Plane(screen))
            enemy0_maximum += 1
        if hit_score >= 20 and (hit_score%20) == 0 and len(enemy1_list) < enemy1_maximum:
            enemy1_list.append(Enemy1Plane(screen))
        # if len(enemy1_list) < enemy1_maximum:
        #     enemy1_list.append(Enemy1Plane(screen))
        if hit_score >= 85 and (hit_score%85) == 0 and len(enemy2_list) < enemy2_maximum:
            enemy2_list.append(Enemy2Plane(screen))

        screen.blit(background, (0,0))

        #hero
        hero.display() #hero展示
        hero.press_move()
        hero.move_limit() #hero移动范围判断

        if enemy0_list:
            for enemy0 in enemy0_list:
                enemy0.move() #控制敌机的移动
                enemy0.fire() #敌机开火
                enemy0.display() #enemy展示
                hero.isHitted(enemy0, 92, 116) #是否击中hero
                enemy0.isHitted(hero, 43, 31) #是否击中enemy
        if enemy1_list:
            for enemy1 in enemy1_list:
                enemy1.move() #控制敌机的移动
                enemy1.fire() #敌机开火
                enemy1.display() #enemy展示
                hero.isHitted(enemy1, 92, 116) #是否击中hero
                enemy1.isHitted(hero, 61, 71) #是否击中enemy
        if enemy2_list:
            for enemy2 in enemy2_list:
                enemy2.move() #控制敌机的移动
                enemy2.fire() #敌机开火
                enemy2.display() #enemy展示
                hero.isHitted(enemy2, 92, 116) #是否击中hero
                enemy2.isHitted(hero, 147, 238) #是否击中enemy

        # print("enemy2: %d"%len(enemy2_list))

        pygame.display.update()

        key_control(hero)

        time.sleep(0.01)

if __name__ == "__main__":
    main()

效果截图:
这里写图片描述

本章结束。

到此,飞机大战的1.0版本可以说已经实现,以后的章节即进行某些代码优化,和功能添加的讲解。

猜你喜欢

转载自blog.csdn.net/qq_38038143/article/details/80042563