实战项目:飞机大战

实战项目:飞机大战

项目目标:

实现基本的飞机大战python

项目描述:

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


项目实现环境:

  • 编辑器:vscode编辑器微信

  • 操纵系统:win10dom

  • 编辑语言:python3.7编辑器

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

  • pygame:第三方模块,用于编写游戏ide

  • random:python自带的模块,在指定的数字范围内随机产生相应结果动画

项目需求:

  • 绘制游戏背景图并实现背景图滚动ui

  • 绘制敌机并实现出现的时间随机spa

  • 绘制英雄飞机,并实现上下左右移动.net

  • 实现英雄飞机自动发射子弹

  • 实现英雄飞机与敌机、子弹与敌机的碰撞检测

项目准备:建立文件

  • 建立专门调用功能实现飞机大战的主文件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表明定时事件的编号,经过后面+一、+二、+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()

总结

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

欢迎添加微信(sy520518)跟我联系

本文分享自微信公众号 - 佛系编程人(py520llj)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索