制作原因

做这个小游戏是因为学校的实训内容,老师给的要求是飞机大战,当时我感觉飞机大战这个题材太多了,就做了个飞艇大战,图片也是很久之前学习前端时攒下的素材,自己用ps改了改拿来用效果还不错

因为实训项目不光这一个游戏项目,所有没有很多的事件来做,满打满算从接触pygame这个库开始学习到做完,一共经历了一天半,所以应该会有一些没发现的bug,欢迎来github提交代码

效果展示

python飞机大战飞机不爆炸 python飞机大战难吗_游戏

玩法介绍

  1. 玩家控制的飞艇只能上下移动,移动按w或s(或↑与↓),按下空格发出子弹
  2. 敌方飞艇从屏幕右侧向玩家飞来,且会上下移动,无论是水平移动的速度还是上下移动的速度都是随机的,且移动区间也是随机的
  3. 游戏设计了难度,每出现五个敌方飞艇,就会增加一个难度等级,难度是有上限的,但我估计没人能看得到。。
    因为最终难度是地狱模式:
  4. python飞机大战飞机不爆炸 python飞机大战难吗_文字颜色_02

代码

import pygame
import sys
#导入所有pygame.locals里的变量(比如下面大写的QUIT变量)
from pygame.locals import *
import random


class flyShip(object):
    """定义一个飞艇类"""
    def __init__(self):
        """定义初始化方法"""
        self.shipStatus = pygame.image.load("飞艇.png")#飞艇图片
        self.width = self.shipStatus.get_width()  # 飞艇宽度
        self.height = self.shipStatus.get_height()  # 飞艇高度
        self.shipX = 50  # 飞艇所在X轴坐标
        self.shipY = 220  # 飞艇所在Y轴坐标,即上下飞行高度
        self.Speed = 10  # 单次移动高度
        self.dead = False  # 默认飞艇生命状态为活着
    def isDead(self):# 检测飞艇是否需要死亡
        for badship in badShips:
            #碰撞检测
            if(badship.shipX <= self.shipX + self.width and badship.shipX + badship.width >= self.shipX and badship.shipY <= self.shipY + self.height and badship.shipY + badship.height >= self.shipY ):
                self.dead = True# 飞艇置死
                self.shipStatus = pygame.image.load("飞艇dead.png")#更换飞艇图片



class BadFlyShip(object):
    """定义一个敌对飞艇类"""
    def __init__(self):
        """定义初始化方法"""
        self.shipStatus = pygame.image.load("飞艇2.png")#飞艇图片
        self.width = self.shipStatus.get_width()#飞艇宽度
        self.height = self.shipStatus.get_height()#飞艇高度
        self.shipX = 1030  # 飞艇所在X轴坐标,即左右飞行高度
        self.shipY = random.randint(0,510-self.height)  # 飞艇所在Y轴坐标,即上下飞行高度
        self.Speed = random.randint(1,5)  # 移动速度
        self.SpeedY = random.randint(1,2)  # 垂直移动速度
        self.range = random.randint(50,100) # 上下移动范围
        self.rangeT = self.shipY - self.range if  ((self.shipY - self.range) > 0) else 0 # 上范围
        self.rangeB = self.shipY + self.range if  ((self.shipY + self.range) < size[1]-self.height) else size[1]-self.height # 上范围
        self.dead = False  # 默认飞艇生命状态为活着

    def updateX(self):
        """水平移动"""
        self.shipX-=self.Speed
        if(self.shipX<=-50 or self.shipY>= size[1]):
            badShips.remove(self)
    def updateY(self):
        """垂直移动"""
        if(self.SpeedY>0):#向下移动
            #检测是否触底
            if(self.shipY+self.SpeedY>self.rangeB):
                self.shipY = self.rangeB
                self.SpeedY=-self.SpeedY
            else:
                self.shipY += self.SpeedY
        elif(self.SpeedY<0):#向上移动
            #检测是否触顶
            if (self.shipY + self.SpeedY < self.rangeT):
                self.shipY = self.rangeT
                self.SpeedY = -self.SpeedY
            else:
                self.shipY += self.SpeedY
    def isDead(self):# 检测飞艇是否需要死亡
        for bullet in bullets:
            #碰撞检测
            if(bullet.bulletX <= self.shipX + self.width and bullet.bulletX + bullet.width >= self.shipX and bullet.bulletY <= self.shipY + self.height and bullet.bulletY + bullet.height >= self.shipY ):
                self.Speed = 0#飞艇坠落
                self.rangeB = size[1]#飞艇坠落
                self.SpeedY = 2 #飞艇坠落
                self.shipStatus = pygame.image.load("飞艇dead2.png")#更换飞艇图片
                bullets.remove(bullet) # 子弹使用
                if (not self.dead):
                    global point
                    point += 1
                self.dead = True #飞艇置死


class Bullet:
    """定义子弹飞艇类"""
    def __init__(self):
        self.bulletStatus = pygame.image.load("子弹.png")  # 子弹图片
        self.width = self.bulletStatus.get_width()  # 子弹宽度
        self.height = self.bulletStatus.get_height()  # 子弹高度
        self.bulletX = 50 + ship.width  # 子弹所在X轴坐标,即左右飞行高度
        self.bulletY = ship.shipY + ship.height / 2 # 子弹所在Y轴坐标,即上下飞行高度
        self.Speed = 3  # 移动速度
        self.dead = False  # 检测子弹是否被激发
    def updateX(self):
        """水平移动"""
        self.bulletX+=self.Speed
        if(self.dead or self.bulletX>= size[0]):
            bullets.remove(self)
def createMap():
    """定义创建地图的方法"""
    screen.blit(bg, bgPosition)  # 将背景图片画到窗口上
    if(not ship.dead):# 我方飞艇存活
        # 显示飞艇
        screen.blit(ship.shipStatus, (ship.shipX, ship.shipY))
        # 显示子弹
        for bullet in bullets:
            screen.blit(bullet.bulletStatus, (bullet.bulletX, bullet.bulletY))
            # 子弹水平移动
            bullet.updateX()

        if(Play):#检测是否点击开始游戏
            play_text = "PLAY" #play
            play_font = pygame.font.SysFont("Arial", 70)
            play_surf = play_font.render(play_text, 1, (255, 255, 255))
            screen.blit(play_surf, [screen.get_width() / 2 - play_surf.get_width() / 2, 200])
            rule_text = "使用上下或ws键控制飞艇躲避来袭敌人,按下空格发射子弹击落敌方飞艇"  # 玩法
            rule_font = pygame.font.SysFont("simHei", 20)
            rule_surf = rule_font.render(rule_text, 1, (255, 255, 255))
            screen.blit(rule_surf, [screen.get_width() / 2 - rule_surf.get_width() / 2, 50])
        else:
            # 积分板
            showPoint()
            createBadShip()  # 向敌人列表中添加敌人对象
            # 遍历敌人列表
            for badShip in badShips:
                # 显示敌人
                screen.blit(badShip.shipStatus, (badShip.shipX, badShip.shipY))
                # 敌人水平移动
                badShip.updateX()
                # 敌人垂直移动
                badShip.updateY()
                # 检测是否被击中
                badShip.isDead()

        # 检测飞艇是否死亡
        ship.isDead()
    else:#我方飞艇死亡,显示结束信息等待关闭窗口
        # 遍历敌人列表
        for badShip in badShips:
            # 显示敌人
            screen.blit(badShip.shipStatus, (badShip.shipX, badShip.shipY))
        # 显示飞艇
        screen.blit(ship.shipStatus, (ship.shipX, ship.shipY))
        final_text1 = "Game Over"
        final_text2 = " GitHub: https://github.com/queuecat/Airship-war"
        final_text3 = "© QueueCat"
        ft1_font = pygame.font.SysFont("Arial", 70)  # 设置第一行文字字体
        ft1_surf = ft1_font.render(final_text1, 1, (255, 255, 255))  # 设置第一行文字颜色
        ft2_font = pygame.font.SysFont("Arial", 30)  # 设置第二行文字字体
        ft2_surf = ft2_font.render(final_text2, 1, (255, 255, 255))  # 设置第二行文字颜色
        ft3_font = pygame.font.SysFont("Arial", 30)  # 设置第三行文字字体
        ft3_surf = ft3_font.render(final_text3, 1, (255, 255, 255))  # 设置第三行文字颜色
        screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])  # 设置第一行文字显示位置
        screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 300])  # 设置第二行文字显示位置
        screen.blit(ft3_surf, [screen.get_width() / 2 - ft3_surf.get_width() / 2, 400])  # 设置第三行文字显示位置


    # 背景移动
    if(-(bgPosition[0]-1)<bgsize[0]-size[0]):
        bgPosition[0]-=1
    else:
        bgPosition[0]=0
    pygame.display.flip()  # 更新全部显示
def createBadShip():#创建敌方飞机
    global oldTime,count,createTime,fps
    # if((int)(time.time()) % createTime == 0 and (int)(time.time()) != oldTime):
    if(oldTime == 0):
        badShips.append(BadFlyShip())
        oldTime = createSurface+1
    if (createSurface % (createTime*fps) == 0 and createSurface != oldTime):
        oldTime=createSurface
        badShips.append(BadFlyShip())
        count -= 1
        if(count<=0):
            count=5
            fps = 1 if fps-1<=0  else fps-1
def keydown(key):#用于每隔50毫秒按下一次键盘
    if (createSurface % 4 == 0):
        if (key == 1073741906 or key == 119):  # 上将或W键
            ship.shipY = ship.shipY - ship.Speed if ((ship.shipY - ship.Speed) > 0) else 0
        elif (key == 1073741905 or key == 115):  # 下键或S键
            ship.shipY = ship.shipY + ship.Speed if ((ship.shipY + ship.Speed) < size[1] - ship.shipStatus.get_height()) else size[1] - ship.shipStatus.get_height()

def showPoint():
    global point
    point_text1 = "积分:"+str(point)
    point_font = pygame.font.SysFont("simHei", 20)  # 设置第一行文字字体
    point_surf = point_font.render(point_text1, 1, (255, 255, 255))  # 设置第一行文字颜色
    screen.blit(point_surf, [0, 0])  # 设置第一行文字显示位置
if __name__ == '__main__':
    pygame.init()  # 初始化pygame
    pygame.font.init()  # 初始化字体
    fpsClock = pygame.time.Clock() # 获得pygame的时钟
    size = width, height = 1030, 510  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    pygame.display.set_caption('飞艇大战')  # 设置标题
    pygame.display.set_icon(pygame.image.load('飞艇.png'))  # 设置窗口图标
    font = pygame.font.SysFont("Arial", 50)  # 设置字体和大小
    bg = pygame.image.load('bg.jpg')  # 加载背景图片
    bgsize = bg.get_size() # 存储图片大小
    bgPosition = [0,0]# 存储背景图片偏移量
    ship = flyShip()# 实例化飞艇
    #badShip = BadFlyShip()#实例化敌人
    badShips = []#敌人序列
    bullets = [] # 子弹序列
    count = 5  # 每5个飞船后增加难度
    createTime = 6 #创建飞艇间隔
    fps = 60 # 更新时间
    oldTime = 0 # 互斥锁
    createSurface = 1 # 充当计算机时间
    Play = True #显示游戏开始界面
    pygame.key.set_repeat(250,50)
    isdowbKey = False # 上下按键检测变量
    point = 0 # 积分
    while True:  # 循环确保窗口一直显示
        # 检测上下键是否被按下,按下则调用方法使其继续运动(防止其他事件打断该事件)
        if(isdowbKey and not ship.dead):
            downKeys = pygame.key.get_pressed()
            if (downKeys[K_UP] == 1 or downKeys[K_w] == 1):
                keydown(K_UP)
            elif (downKeys[K_DOWN] == 1 or downKeys[K_s] == 1):
                keydown(K_DOWN)
            else:
                isdowbKey = False
        for event in pygame.event.get():  # 遍历所有事件

            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()

            if event.type == pygame.KEYDOWN and not ship.dead:# 键盘按下事件
                #获取所有按键元组
                keys = pygame.key.get_pressed()
                if(event.key==1073741906 or event.key==119):#上将或W键
                    # ship.shipY = ship.shipY - ship.Speed if ((ship.shipY - ship.Speed) > 0) else 0
                    isdowbKey = True
                elif(event.key==1073741905 or event.key==115):#下键或S键
                    # ship.shipY = ship.shipY + ship.Speed if ((ship.shipY + ship.Speed) < size[1] - ship.shipStatus.get_height()) else size[1] - ship.shipStatus.get_height()
                    isdowbKey = True
            if event.type == KEYUP and not ship.dead:
                if (event.key == K_SPACE):
                    bullets.append(Bullet())
            if event.type ==  MOUSEBUTTONDOWN:
                pressed_array = pygame.mouse.get_pressed()
                for index in range(len(pressed_array)):
                    if pressed_array[index]:
                        if index == 0:
                            Play = False# 鼠标点击后,进入游戏



        createMap()# 更新地图
        createSurface += 1

        fpsClock.tick(60)  # 设置时钟间隔
    pygame.quit()  # 退出pygame