Python飞机大战

一、项目准备

在开发游戏前,我们需要安装一个pygame模块

  • pygame 就是一个 Python 模块,专为电子游戏设计

安装pygame

sudo pip3 install pygame

验证安装

python3 -m pygame.examples.aliens

二、文件职责

首先我们需要两个文件编写代码 plane_main 和 plane_sprites

  • plane_main
    1. 封装 主游戏类
    2. 创建 游戏对象
    3. 启动游戏
  • plane_sprites
    1.封装游戏中 所有 需要使用的 精灵子类
    2.提供游戏的 相关工具

三、搭建游戏框架

第一部分----游戏初始化

  • 设置游戏窗口
  • 创建游戏时钟
  • 创建精灵、精灵组

第二部分----游戏循环

  • 设置刷新帧率
  • 事件监听
  • 碰撞检测
  • 更新精灵组
  • 更新屏幕显示

四、代码整理1----在plane_main游戏主程序中

  • 导入模块
#导入Python本身提供的pygame模块
import pygame
#导入精灵文件Plan_sprites模块
from PlanSprite import *
  • 创建一个类
#运用面向对象思想创建主游戏类
class PlaneGame(object):
  • 游戏初始化
#初始化方法
def __init__(self):
    #创建游戏窗口
    self.screen = pygame.display.set_mode(SCREEN_RECT.size) 
    #创建游戏时钟
    self.clock = pygame.time.Clock()
    #创建精灵组
    self.__create_sprites()
    #得分显示,(默认为0)
    self.wanjia = 0
    #定时器 毫秒  第一个参数是事件的名字  第二个参数是多长时间执行一次时间
    pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)
  • 创建精灵组
def __create_sprites(self):
    #背景精灵组
    bg1 = Background()
    bg2 = Background(True)
    self.back_group = pygame.sprite.Group(bg1,bg2)
    #敌机的精灵组
    self.enemy_group = pygame.sprite.Group()
    #英雄的精灵组
    self.hero = Hero()
    self.hero_group = pygame.sprite.Group(self.hero)
  • 游戏循环部分
def start_game(self):
    print("游戏开始...")
    while  True:
        #设置帧率
        self.clock.tick(FRAME_PER_SEC)
        #事件监听
        self.__event_handler()
        #碰撞检测
        self.__check_collide()
        #更新精灵和精灵组
        self.__update_sprites()
        #分数
        self.__print_score()
        #更新显示
        pygame.display.update() 
  • 事件监听
def __event_handler(self)
    for event in pygame.event.get():
        #判断是否退出游戏
        if event.type == pygame.QUIT:
            PlaneGame.__game_over()
        elif event.type == CREATE_ENEMY_EVENT: #敌机定时器事件
            enemy = Enemy()
            self.enemy_group.add(enemy)
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: #子弹定时器事件
            self.hero.fire()
  • 碰撞检测
def __check_collide(self):
    # 1. 子弹摧毁敌机
    if pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True):
        self.wanjia +=2

    # 2. 敌机撞毁英雄
    enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True) 

    # 判断列表时候有内容
    if len(enemies) > 0: 

        # 让英雄牺牲
        self.hero.kill()
        print("英雄牺牲")

        # 结束游戏
        PlaneGame.__game_over()
        print("游戏结束")
  • 更新精灵组
def __update_sprites(self):
    #更新背景精灵组
    self.back_group.update()
    self.back_group.draw(self.screen)

    #更新敌机精灵组
    self.enemy_group.update()
    self.enemy_group.draw(self.screen)

    #更新玩家飞机精灵组  
    self.hero_group.update()
    self.hero_group.draw(self.screen)

    #更新子弹精灵组
    self.hero.bullets.update()
    self.hero.bullets.draw(self.screen)
  • 打印分数
def __print_score(self):
    pygame.font.init()
    #位置
    pos = (20,0)
    #颜色
    color = (255,255,255)
    #显示内容
    text = "score:" + str(self.wanjia)
    #字体
    cur_font = pygame.font.SysFont("楷体",30)
    text_fort = cur_font.render(text,1,color)
    self.screen.blit(text_fort,pos)
  • 结束游戏
#退出游戏
@staticmethod       
def __game_over():
    #卸载所有 pygame 模块
    pygame.quit
    #python本身提供的退出脚本的功能
    exit()
  • 调用主函数
if __name__ == '__main__':
    #创建游戏对象
    game = PlaneGame()
    #开始游戏
    game.start_game()       

五、代码整理2----在plane_sprites游戏精灵中

#导入随机包
import random
#导入pygame模块
import pygame
#设置游戏屏幕大小
SCREEN_RECT = pygame.Rect(0,0,480,700)
#刷新帧率
FRAME_PER_SEC = 60
#敌机事件的常量
CREATE_ENEMY_EVENT = pygame.USEREVENT
  • 创建游戏精灵的基础类
 class GameSprite(pygame.sprite.Sprite):
    #给基础类的速度设置一个默认值为1
    def __init__(self,image_name,speed=1):
        #继承父类的初始化
        super().__init__()
        #pygame.image.load(pygame提供的方法) 加载图片
        self.image = pygame.image.load(image_name)
        #设置尺寸
        self.rect = self.image.get_rect()
        #记录速度
        self.speed = speed

    #每次更新屏幕时在游戏循环内调用
    def update(self):
        #默认在垂直方向移动
        self.rect.y += self.speed   
  • 创建背景精灵类
class Background(GameSprite):

    #is_alt判断是否为另外一张图像(False表示第一张图像 True表示另外一张图像)
    def __init__(self,is_alt=False):
        #传入背景图片
        image_name = "./images/timg.jpeg"
        super().__init__(image_name)
        #如果是另一张图像,讲图片设置到屏幕顶部
        if is_alt:
            self.rect.y = -self.rect.height


    def update(self):
        #调用父类的方法实现
        super().update()
        #判断是否移出屏幕,如果移出屏幕,将图像设置到屏幕的上方
        if self.rect.y > SCREEN_RECT.height:
            self.rect.y = -self.rect.height
  • 创建敌机精灵类
class Enemy(GameSprite):
    def __init__(self):
        #传入敌机图片
        image_name = "./images/enemy-1.gif"
        super().__init__(image_name)
        #设置敌机的随机初始速度
        self.speed = random.randint(1,3)
        #敌机x轴最大值 需要用屏幕的宽度-敌机自身的宽度

        max_x = SCREEN_RECT.width - self.rect.width
        self.rect.x = random.randint(0,max_x)#随机位置
        self.rect.bottom = 0 #敌机底部位置

    def update(self):
        super().update()
        #判断是否飞出屏幕,如果是,需要将敌机从精灵组删除
        if self.rect.y >= SCREEN_RECT.height: 
            self.kill()
            print("敌机飞出屏幕...")
    #删除敌机后打印(可忽略)
    def __del__(self): 
        print("敌机挂了 %s" % self.rect) 
  • 创建英雄精灵类
class Hero(GameSprite):
    def __init__(self):
        #传入玩家飞机图片
        image_name = "./images/plane.png"
        super().__init__(image_name,0)
        #设置初始位置
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom - 80
        #创建子弹精灵组
        self.bullets = pygame.sprite.Group()

        self.speed1 = 0


    def update(self):
        #key.get_pressed(pygame提供的方法)设置按键
        keys_pressed = pygame.key.get_pressed()
        
        if keys_pressed[pygame.K_RIGHT]:
            self.rect.x += 10
        elif keys_pressed[pygame.K_LEFT]:
            self.rect.x -= 10
        elif keys_pressed[pygame.K_UP]:
            self.rect.y -= 10
        elif keys_pressed[pygame.K_DOWN]:
            self.rect.y += 10
        if keys_pressed[pygame.K_c]:
            self.fire()
        

        # 判断屏幕边界
        if self.rect.left < 0: 
            self.rect.left = 0 
        elif self.rect.right > SCREEN_RECT.right: 
            self.rect.right = SCREEN_RECT.right
        elif self.rect.top < 0:
            self.rect.top = 0
        elif self.rect.bottom > SCREEN_RECT.bottom:
            self.rect.bottom = SCREEN_RECT.bottom

    #发射子弹
    def fire(self):
        bullet = Bullet()
        bullet1 = Bullet()
        bullet2 = Bullet()
        #子弹发射位置
        bullet.rect.bottom = self.rect.y -30
        bullet.rect.centerx = self.rect.centerx
        bullet1.rect.bottom = self.rect.y -20
        bullet1.rect.centerx = self.rect.centerx + 15
        bullet2.rect.bottom = self.rect.y -20
        bullet2.rect.centerx = self.rect.centerx - 15
        #将子弹添加到精灵组
        self.bullets.add(bullet,bullet1,bullet2)
  • 创建子弹精灵
class Bullet(GameSprite):
    def __init__(self):
        #传入子弹图片
        image_name = './images/bullet1.png'
        super().__init__(image_name,-10)

    #判断子弹超出屏幕后删除
    def update(self):
        super().update()    
        if self.rect.bottom < 0:
            self.kill() 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容