专栏首页佛系编程人实战项目:飞机大战

实战项目:飞机大战

实战项目:飞机大战

项目目标:

实现基本的飞机大战

项目描述:

运行程序,英雄飞机出现在屏幕底边的中央区域,飞机中央每隔一秒会自动发射一枚子弹。随着游戏的开始,敌机会在屏幕上方随机不定时的出现在屏幕内向下飞行。英雄飞机需要通过移位躲避敌机或用子弹消灭敌机,避免碰撞导致游戏结束。

项目实现环境:

  • 编辑器:vscode编辑器
  • 操纵系统:win10
  • 编辑语言:python3.7

项目中所使用的库或模块:

  • pygame:第三方模块,用于编写游戏
  • random:python自带的模块,在指定的数字范围内随机产生相应结果

项目需求:

  • 绘制游戏背景图并实现背景图滚动
  • 绘制敌机并实现出现的时间随机
  • 绘制英雄飞机,并实现上下左右移动
  • 实现英雄飞机自动发射子弹
  • 实现英雄飞机与敌机、子弹与敌机的碰撞检测

项目准备:创建文件

  • 创建专门调用功能实现飞机大战的主文件main.py
  • 创建为飞机大战提供功能的类文件tools.py,包含的内容有:
    • 精灵类
    • 背景类
    • 敌机类
    • 子弹类
    • 英雄飞机类

代码编写

如何创建屏幕

# 导入第三方模块
import pygame
# 导入pygame库中的所有模块并进行初始化
pygame.init()

# 创建屏幕,设置屏幕大小(应根据背景图大小设置)
surface = pygame.display.set_mode((480,580))

# 卸载所有模块,退出程序
pygame.quit()

以上代码必须写入,否则无法正常运行

如何导入图片,创建图片对象

image = pygame.image.load('图片的地址')

如何将图片绘制到屏幕上

surface.blit(image,(0,0))
  • 第一个参数为图片对象
  • 第二个参数为绘制的初始位置

如何更新屏幕

pygame.display.update()

每次绘制完所有图片后一定要更新屏幕

如何创建精灵组

group = pygame.sprite.Group(精灵1对象,精灵2对象)

精灵组的三个方法

# 同时调用精灵组中所有精灵的update方法
group.update()
# 同时绘制精灵组中所有精灵的位置,需要传入屏幕对象
group.draw(屏幕对象)
# 向精灵组中添加精灵的方法
group.add(精灵)

如何碰撞检测

# 精灵组与精灵组之间的碰撞检测,比如子弹与敌机之间
pygame.sprite.groupcollide('精灵组1','精灵组2',True,True)

# 精灵与精灵组之间的碰撞检测,比如敌机与英雄飞机
pygame.sprite.spritecollide('精灵','精灵组',True)

其中,True代表碰撞的精灵或精灵组内的精灵会消失

编写tools.py文件代码

常量部分

# 480\580是图片的宽高SCREEN = pygame.Rect(0,0,480,580)# 创建敌机事件
CREAT_EVENT = pygame.USEREVENT
# 发射子弹事件
FIRE_BULLET = pygame.USEREVENT+1

pygame.Rect可以用来描述矩形区域,从左到右的参数分别代表 x、y、矩形区域的宽、矩形区域的高

pygame.USEREVENT代表定时事件的编号,通过后面+1、+2、+3.....的方式添加多个事件

编写精灵类

# 精灵类
class SpriteParent(pygame.sprite.Sprite):
    def __init__(self,imgae,speed=1)
         super().__init__()
         self.image = pygame.image.load(image)
        self.rect = self.image.get_rect()
        self.speed = speed
        
    def update(self):
         self.rect.y += self.speed
  • 该类继承了精灵类,需要包含两种方法:初始化方法和update()方法。
  • 在初始化方法中要添加三个属性,分别是:加载的图片对象、图片的矩形区域,图片的移动速度。其中图片的矩形区域可以使用图片对象的 get_rect() 来获取,速度自定义设置,这里设置成 每次移动1像素。
  • 这里要注意的是,我们是扩展父类的初始化方法,而不是重写父类的初始化方法
  • update()方法的作用是更新图片的位置
  • self.rect.y 代表矩形区域在y轴的位置

编写背景类

class BackGround(SpriteParent):

    def __init__(self,is_alt=False):
        super().__init__('./images/background.png')
        # 如果is_alt为True,则设置图片的初始位置为图片高度的负值
        if is_alt:
            self.rect.y = -self.rect.height
            
    def update(self):
        # 继承父类的update方法,使图片每次向下移动1像素
        super().update()
        # 当图片顶部的位置等于屏幕的高度时,将该图片返回到屏幕上方,与上方图片进行衔接
        if self.rect.y >= SCREEN.height:
            self.rect.y = -self.rect.height

要实现背景图片循环上下交替滚动,所以需要实例化两个背景图片对象,其中一个对象的初始位置位于y轴的负方向,且y为背景图片的高度的负值

编写敌机类

import random
class Enemy(SpriteParent):
    def __init__(self):
         super().__init__('./images/enemy.png')
         max_x = SCREEN.width - self.rect.width
         # 设置敌机在x轴随机出现的范围
         self.rect.x = random.randint(0,max_x)
         # 固定敌机在y轴出现的位置
         self.rect.y = -self.rect.height
        def update(self):         super().update()
        # 如果敌机飞出屏幕,则杀死该敌机对象,然后会自动调用__del__方法将其从内存中删除
        if self.rect.y >= SCREEN.height:
             self.kill()
            
    def __del__(self):
        print("敌机已经从内存中销毁..")

编写子弹类

class Bullet(SpriteParent):
    def __init__(self):
         super().__init__('./images/bullet.png')
        def update(self):         self.rect.y -= self.speed
         if self.rect.y <= -self.rect.height:
             self.kill()
            
     def __del__(self):
         print("子弹已经从内存中销毁...")

编写英雄飞机类

class Hero(SpriteParent):
     def __init__(self):
         super().__init__('./images/hero1.png')
         # centerx代表矩形区域在x轴的中心位置
         # 这里设置英雄飞机的初始位置为屏幕底端位于x轴的中间
         self.rect.centerx = SCREEN.rect.centerx
         self.rect.y = SCREEN.rect.height - self.rect.height
         self.bullet_group = pygame.sprite.Goup()
    
     def update(self):
         # 获取从键盘上按下的值
           key_down = pygame.key.get_pressed()
         # 判断按下的值,向对应的方向移动
         # 内部是设置英雄飞机上下左右移动的边界
         if key_down[pygame.K_DOWN]:
             if self.rect.bottom >= SCREEN.height:
                 self.rect.bottom = SCREEN.height
             self.rect.y += 2
         elif key_down[pygame.K_UP]:
             if self.rect.y <= 0:
                 self.rect.y = 0
             self.rect.y -= 2
          elif key_down[pygame.K_LEFT]:
             if self.rect.x <= 0:
                 self.rect.x = 0
             self.rect.x -= 2
         elif key_down[pygame.K_RIGHT]:
             if self.rect.right >= SCREEN.width:
                 self.rect.right = SCREEN.width
             self.rect.x += 2
                
     def fire(self):
        bullet = Bullet()
        # 设置子弹出现的初始位置
        bullet.rect.centerx = self.rect.centerx
        bullet.rect.y = self.rect.y-20
        # 向子弹精灵组中添加子弹精灵
        self.bullet_group.add(bullet)

编写main.py文件

from tools import *
import pygame

class PlaneGame(object):
     def __init__(self):
          pygame.init()
          self.surface = pygame.display.set_mode(0,0,SCREEN.size)
         # 设置游戏时钟对象
         self.clock = pygame.time.Clock()
         self.__create_sprite()
         # 设置定时创建敌机和发射子弹的定时器,1000代表1s
         # 第一个参数为事件编号,第二个参数是定时的时间
         pygame.time.set_timer(CREAT_EVENT,1000)
         pygame.time.set_timer(FIRE_BULLET,1000)
        
     def __create_sprite(self):
          bg1 = Background()
         bg2 = Backgroud(True)
         self.bg_group = pygame.sprite.Group(bg1,bg2)
        
         self.enemy_group = pygame.sprite.Group()
        
         self.hero = Hero()
         self.hero_group = pygame.sprite.Group(self.hero)
        
     def startGame(self):
          # 循环代表游戏开始
          while True:
             # 设置屏幕刷新频率为每秒更新60次,这种频率足以使动画流畅运行
              self.clock.tick(60)
               self.__event_handler()
              self.__check_collide()
              self.__update_sprites()
           # 每次绘制完就要更新一次
            pygame.display.update()
            
     def __event_handler(self):
          # 获取屏幕事件
          for event in pygame.event.get():
              # 如果点击屏幕的退出按钮,则结束游戏
             if event.type == pygame.QUIT:
                  PlaneGame.gemeover()
              # 定时创建敌机
             elif event.type == CREAT_EVENT:
                  enemy = Enemy()
                 self.enemy_group.add(enemy)
              # 定时发射子弹,实现自动射击的效果
             elif event.type == FIRE_BULLET:
                  self.hero.fire()
                    def __check_collide(self):        
        '''碰撞检测'''        pygame.sprite.groupcollide(self.enemy_group,self.hero.bullet_group,True,True)
          # 精灵与精灵组内的精灵产生碰撞,会返回与精灵碰撞的精灵对象
         enemies = pygame.sprite.spritecollide(self.hero,self.enemy_group,True)
         # 如果enemies有值,说明敌机与英雄飞机产生碰撞,那么杀死英雄飞机,游戏结束
         if enemies:
             self.hero.kill()
             PlaneGame.gemeover()
                def __update_sprites(self):        # 更新和绘制精灵组中所有精灵的位置
        self.bg_group.update()
         self.bg_group.draw(self.surface)
        
         self.enemy_group.update()
         self.enemy_group.draw(self.surface)
        
         self.hero_group.update()
         self.hero_group.draw(self.surface)
        
         self.hero.bullet_group.update()
         self.hero.bullet_group.draw(self.surface)
        
     # 静态方法,因为该方法内不需要传入任何属性或类对象    
     @ staticmethod
     def gameOver():
          print("游戏结束...")
         pygame.quit()
         exit()
# 主程序的入口    
if __name__ == "__main__":    pg = PlaneGame()    pg.startGame()

总结

虽然这是一个不完整的飞机大战,但是基本功能已经实现,对于刚入门的人(比如我)来说,做完还是会有点小小成就感的。游戏素材可以自行去网上下载,里面有些参数需要根据图片的大小来进行设置。

本文分享自微信公众号 - 佛系编程人(py520llj),作者:佛系小卢

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 猜数字游戏

    我已经玩了几局了,自己设置的范围是0~10,所以难度低了点,猜中好多次了哈哈~那接下来就是小伙伴自己去happy咯~~~

    佛系编程人
  • 数据分析之NumPy笔记(一)

    前几天群里有个大佬推荐了一门极客时间里关于数据分析的课程,教学方式是图文+音频,是我比较喜欢的教学方式之一,光看评论都能学到很多的知识,比如学习方式,对内容的理...

    佛系编程人
  • 图灵聊天机器人

    佛系编程人
  • Python3实现飞机大战游戏

    本文实例为大家分享了Python3实现飞机大战游戏的具体代码,供大家参考,具体内容如下

    砸漏
  • python codis集群客户端(二) - 基于zookeeper对实例创建与摘除

     在这一篇中我们实现了不通过zk来编写codis集群proxys的api, 如果codis集群暴露zk给你的话,那么就方便了,探活和故障摘除与恢复codis集群...

    用户1225216
  • 如何用 Python 打飞机 ?

    前言:python 除了生孩子 ,啥都会 。包括打飞机 !今天小詹的一位读者就来教你如何用 python 打飞机 !

    小小詹同学
  • Python爬虫入门教程 56-100 python爬虫高级技术之验证码篇2-开放平台OCR技术

    今天你要学习的验证码采用通过第三方AI平台开放的OCR接口实现,OCR文字识别技术目前已经比较成熟了,而且第三方比较多,今天采用的是百度的。

    梦想橡皮擦
  • 继承(第十三章)

    嗯哼哼?其实就相当于就用,继承者相当于子类,pass是什么,空的意思方便大家理解,官方点就是占位符

    天钧
  • Python写自动化之SVN更新

    在远程机器上执行脚本时,为了能够保证脚本的实时性,我们一般会将脚本存放到SVN上,远程机器通过SVN的操作去更新脚本;

    py3study
  • Python写的俄罗斯方块

    简单瞅了下Tkinter,和Canvas配合在一起,还算是简洁的界面开发API。threading.Thread创建新的线程,其多线程机制也算是方便。

    py3study

扫码关注云+社区

领取腾讯云代金券