飞机大战游戏

步骤1 面向对象化改造

将原有的代码基础改造为面向对象编程的方法

原代码
import pygame

pygame.init()
screen=pygame.display.set_mode((400,600))

# 检查退出
while True
     for event in pygame.event.get():
          if event.type == pygame.QUIT:
              pygame.quit()
      # 设置背景
      self.screen.fill((255,255,255))
      # 游戏更新
      pygame.display.update()
      
if __name__ == '__main__':
    # 创建游戏 并开始游戏
    game=MainGame()
    game.show()
更改后
SCREEN_W=400
SCREEN_H=600

class MainGame:
    def __init__(self):
        # 游戏初始化
        pygame.init()
        # 创建屏幕
        self.screen = pygame.display.set_mode((SCREEN_W,SCREEN_H))
 
    # 运行游戏
    def show(self):
        while True:
            # 检查退出
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
            # 设置背景
            self.screen.fill((255,255,255))
            # 游戏更新
            pygame.display.update()
步骤2 增加战机类

在这里插入图片描述

2.1 游戏图操作
操作代码
加载图片img=pygame.image.load()
裁剪img.subsurface(pygame.Rect(8,99,108,126))
透明化img.convert_alpha()
2.2 游戏精灵类

精灵,简单来说是一个会动图片。
两个成员变量
1)self.image=要显示图片的Surface
2)self.rect = 显示Surface的区域,

import pygame
from pygame.locals import *

SCREEN_W=400
SCREEN_H=600

# 战机类(继承于游戏精灵类)
class Player(pygame.sprite.Sprite):

    speed=1 # 移动速度

    def __init__(self,plane_img,init_pos):
    	pygame.sprite.Sprite.__init__(self)
        # 游戏精灵类 要点1:精灵的矩形区域
        self.rect = pygame.Rect(5, 99, 98, 126) # (x,y,w,h)
        # 游戏精灵类 要点2:精灵的显示图像
        self.image = plane_img.subsurface(self.rect).convert_alpha() # 裁剪 之后透明化处理

        # 初始化位置
        self.rect.topleft=init_pos # 左上角等于初始坐标

    # 继承游戏精灵类之后 移动只用修改rect的位置
    def moveUp(self):
        self.rect.top  -= self.speed
    def moveDown(self):
        self.rect.top  += self.speed
    def moveLeft(self):
        self.rect.left -= self.speed
    def moveRight(self):
        self.rect.left += self.speed

    # 显示战机
    def showPlane(self,scr):
        scr.blit(self.image,self.rect)


# 主游戏

class MainGame:
    def __init__(self):
        # 游戏初始化
        pygame.init()
        # 创建屏幕
        self.screen = pygame.display.set_mode((SCREEN_W,SCREEN_H))
        # 设置标题
        pygame.display.set_caption("飞机大战")
        # 获得图片资源
        plane_img = pygame.image.load('resources/image/shoot.png')
        # 创建战机
        self.player = Player(plane_img,(200,500))

    # 运行游戏
    def show(self):
        while True:
            # 检查退出
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
            # 设置背景
            self.screen.fill((255,255,255))
            # 显示战机
            self.player.showPlane(self.screen)
            # 检查按键并操作战机
            self.checkPress()
            # 游戏更新
            pygame.display.update()
    # 检测按键并操作战机
    def checkPress(self):
        key_pressed = pygame.key.get_pressed()
        if key_pressed[K_UP]:
            self.player.moveUp()
        if key_pressed[K_DOWN]:
            self.player.moveDown()
        if key_pressed[K_LEFT]:
            self.player.moveLeft()
        if key_pressed[K_RIGHT]:
            self.player.moveRight()

if __name__ == '__main__':
    # 创建游戏 并开始游戏
    game=MainGame()
    game.show()
2.3 战机状态变化(喷气效果)

可以改变战机的多种形态

# 战机类(继承于游戏精灵类) 增加喷气效果后的战机类
class Player(pygame.sprite.Sprite):

    speed=1 # 移动速度
    temp=0  # 控制显示图片的变量

    def __init__(self,plane_img,init_pos):
    	pygame.sprite.Sprite.__init__(self)
        # 游戏精灵类 要点1:精灵的矩形区域 区域集合
        player_rects = []
        player_rects.append(pygame.Rect(5, 99, 98, 126))      # 战机喷气
        player_rects.append(pygame.Rect(170, 360, 98, 126))
        # 游戏精灵类 要点2:精灵的显示图像列表
        self.images = []  # 用来存储玩家对象精灵图片的列表
        for i in range(len(player_rects)):
            self.images.append(plane_img.subsurface(player_rects[i]).convert_alpha())
        self.rect = player_rects[0]

        # 初始化位置
        self.rect.topleft=init_pos # 左上角等于初始坐标
        
    def moveUp(self):
        self.rect.top  -= self.speed
    def moveDown(self):
        self.rect.top  += self.speed
    def moveLeft(self):
        self.rect.left -= self.speed
    def moveRight(self):
        self.rect.left += self.speed
    
    # 显示战机
    def showPlane(self,scr):
        self.temp += 1
        if self.temp >= 2:
            self.temp = 0
        scr.blit(self.images[self.temp],self.rect)
2.4 战机运动范围限制
class Player(pygame.sprite.Sprite):

    speed=1 # 移动速度
    temp=0  # 控制显示图片的变量

    def __init__(self,plane_img,init_pos):
        # 游戏精灵类 要点1:精灵的矩形区域 区域集合
        player_rects = []
        player_rects.append(pygame.Rect(5, 99, 98, 126))      # 战机喷气
        player_rects.append(pygame.Rect(170, 360, 98, 126))
        # 游戏精灵类 要点2:精灵的显示图像列表
        self.images = []  # 用来存储玩家对象精灵图片的列表
        for i in range(len(player_rects)):
            self.images.append(plane_img.subsurface(player_rects[i]).convert_alpha())
        self.rect = player_rects[0]

        # 初始化位置
        self.rect.topleft=init_pos # 左上角等于初始坐标

    # 继承游戏精灵类之后 移动只用修改rect的位置
    def moveUp(self):
        if self.rect.top <= 0:
            self.rect.top = 0
        else:
            self.rect.top -= self.speed

    def moveDown(self):
        if self.rect.top >= SCREEN_H - self.rect.height:
            self.rect.top = SCREEN_H - self.rect.height
        else:
            self.rect.top += self.speed

    def moveLeft(self):
        if self.rect.left <= 0:
            self.rect.left = 0
        else:
            self.rect.left -= self.speed

    def moveRight(self):
        if self.rect.left >= SCREEN_W - self.rect.width:
            self.rect.left = SCREEN_W - self.rect.width
        else:
            self.rect.left += self.speed

    # 显示战机
    def showPlane(self,scr):
        self.temp += 1
        if self.temp >= 2:
            self.temp = 0
        scr.blit(self.images[self.temp],self.rect)

步骤3 增加子弹类

在这里插入图片描述

import pygame
from pygame.locals import *

SCREEN_W = 400
SCREEN_H = 600

# 战机类(继承于游戏精灵类)
class Player(pygame.sprite.Sprite):

    speed=1 # 移动速度
    temp=0  # 控制显示图片的变量

    def __init__(self,plane_img,init_pos):
        pygame.sprite.Sprite.__init__(self)
        # 游戏精灵类 要点1:精灵的矩形区域 区域集合
        player_rects = []
        player_rects.append(pygame.Rect(5, 99, 98, 126))      # 战机喷气
        player_rects.append(pygame.Rect(170, 360, 98, 126))
        # 游戏精灵类 要点2:精灵的显示图像列表
        self.images = []  # 用来存储玩家对象精灵图片的列表
        for i in range(len(player_rects)):
            self.images.append(plane_img.subsurface(player_rects[i]).convert_alpha())
        self.rect = player_rects[0]

        # 创建子弹列表
        self.bullets = pygame.sprite.Group()
        bullet_rect = pygame.Rect(1004, 987, 9, 21)
        self.bullet_image = plane_img.subsurface(bullet_rect)

        # 初始化位置
        self.rect.topleft=init_pos # 左上角等于初始坐标

    # 继承游戏精灵类之后 移动只用修改rect的位置
    def moveUp(self):
        if self.rect.top <= 0:
            self.rect.top = 0
        else:
            self.rect.top -= self.speed

    def moveDown(self):
        if self.rect.top >= SCREEN_H - self.rect.height:
            self.rect.top = SCREEN_H - self.rect.height
        else:
            self.rect.top += self.speed

    def moveLeft(self):
        if self.rect.left <= 0:
            self.rect.left = 0
        else:
            self.rect.left -= self.speed

    def moveRight(self):
        if self.rect.left >= SCREEN_W - self.rect.width:
            self.rect.left = SCREEN_W - self.rect.width
        else:
            self.rect.left += self.speed

    # 显示战机
    def showPlane(self,scr):
        self.temp += 1
        if self.temp >= 2:
            self.temp = 0
        scr.blit(self.images[self.temp],self.rect)

    # 发射炮弹
    def shoot(self):
        bullet = Bullet(self.bullet_image, self.rect.midtop)
        self.bullets.add(bullet) #增加一颗子弹

    # 炮弹移动
    def moveBullet(self):
        for bullet in self.bullets:
            bullet.move()
            # 子弹出界
            if bullet.rect.bottom < 0:
                self.bullets.remove(bullet)
    # 绘制炮弹
    def drawBullets(self, scr):
        self.bullets.draw(scr)

# 子弹类
class Bullet(pygame.sprite.Sprite):

    speed=2
    def __init__(self, bullet_img, init_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = bullet_img
        self.rect = bullet_img.get_rect()
        self.rect.midbottom = init_pos

    def move(self):
        self.rect.top -= self.speed

# 主游戏

class MainGame:

    def __init__(self):
        # 游戏初始化
        pygame.init()
        # 创建屏幕
        self.screen = pygame.display.set_mode((SCREEN_W,SCREEN_H))
        # 设置标题
        pygame.display.set_caption("飞机大战")
        # 获得图片资源
        plane_img = pygame.image.load('resources/image/shoot.png')
        # 创建战机
        self.player = Player(plane_img,(200,500))


    # 运行游戏
    def show(self):
        shoot_press,freq=0,30#射击计数 与频率控制值
        while True:
            # 检查退出
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
            # 设置背景
            self.screen.fill((255,255,255))
            # 显示战机
            self.player.showPlane(self.screen)
            # 移动与绘画子弹
            self.player.moveBullet()
            self.player.drawBullets(self.screen)
            # 检查按键并操作战机
            shoot_press=self.checkPress(shoot_press,freq)
            # 游戏更新
            pygame.display.update()
    # 检测按键并操作战机
    def checkPress(self,shoot_press,freq=30):
        key_pressed = pygame.key.get_pressed()
        if key_pressed[K_UP]:
            self.player.moveUp()
        if key_pressed[K_DOWN]:
            self.player.moveDown()
        if key_pressed[K_LEFT]:
            self.player.moveLeft()
        if key_pressed[K_RIGHT]:
            self.player.moveRight()
        # 子弹操控 频率控制
        if key_pressed[K_SPACE]:
            if shoot_press % freq == 0:
                self.player.shoot()
            shoot_press += 1
            if shoot_press >= 1000:
                shoot_press = 0
        return shoot_press


if __name__ == '__main__':
    # 创建游戏 并开始游戏
    game=MainGame()
    game.show()
步骤4 添加敌机

在这里插入图片描述

import pygame
from pygame.locals import *
import random

SCREEN_W = 400
SCREEN_H = 600

# 战机类(继承于游戏精灵类)
class Player(pygame.sprite.Sprite):
	...

# 子弹类
class Bullet(pygame.sprite.Sprite):
	...
# 敌机类
class Enemy(pygame.sprite.Sprite):
    speed = 1
    def __init__(self, enemy_img, init_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = enemy_img          # 图像
        self.rect = enemy_img.get_rect()# 矩形区域
        self.rect.topleft = init_pos    # 初始位置

    # 向下移动
    def move(self):
        self.rect.top += self.speed

# 主游戏

class MainGame:

    def __init__(self):
        # 游戏初始化
        pygame.init()
        # 创建屏幕
        self.screen = pygame.display.set_mode((SCREEN_W,SCREEN_H))
        # 设置标题
        pygame.display.set_caption("飞机大战")
        # 获得图片资源
        plane_img = pygame.image.load('resources/image/shoot.png')
        # 创建战机
        self.player = Player(plane_img,(200,500))

        # 获得敌机图片和创建敌机群
        self.enemies = pygame.sprite.Group()
        self.enemy_rect = pygame.Rect(534, 612, 57, 43)
        self.enemy_img = plane_img.subsurface(self.enemy_rect)

    # 运行游戏
    def show(self):
        shoot_press,shoot_freq=0,30#射击计数 与频率控制值
        enemy_count,enemy_creat_freq,enemy_move_freq=0,100,20#敌机循环计数  与频率控制
        while True:
            # 检查退出
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
            # 设置背景
            self.screen.fill((255,255,255))
            # 显示战机
            self.player.showPlane(self.screen)
            # 移动与绘画子弹
            self.player.moveBullet()
            self.player.drawBullets(self.screen)

            # 创建、移动与显示敌机
            enemy_count+=1
            if enemy_count>=1000:
                enemy_count=0

            if enemy_count%enemy_creat_freq==0:
                self.createEnemy()
            if enemy_count%enemy_move_freq ==0:
                self.moveEnemy()
            self.enemies.draw(self.screen)

            # 检查按键并操作战机
            shoot_press=self.checkPress(shoot_press,shoot_freq)
            # 游戏更新
            pygame.display.update()
    # 检测按键并操作战机
    def checkPress(self,shoot_press,freq=30):
        key_pressed = pygame.key.get_pressed()
        if key_pressed[K_UP]:
            self.player.moveUp()
        if key_pressed[K_DOWN]:
            self.player.moveDown()
        if key_pressed[K_LEFT]:
            self.player.moveLeft()
        if key_pressed[K_RIGHT]:
            self.player.moveRight()
        # 子弹操控 频率控制
        if key_pressed[K_SPACE]:
            if shoot_press % freq == 0:
                self.player.shoot()
            shoot_press += 1
            if shoot_press >= 1000:
                shoot_press = 0
        return shoot_press

    # 随机地创建敌机
    def createEnemy(self):
        self.enemy_pos = [random.randint(0, SCREEN_W - self.enemy_rect.width), 0] # 随机位置
        self.enemy = Enemy(self.enemy_img,self.enemy_pos)                         # 创建敌机
        self.enemies.add(self.enemy)                                              # 添加到敌机群

    # 统一地移动敌机
    def moveEnemy(self):
        for enemy in self.enemies:
            enemy.move()
            if enemy.rect.top > SCREEN_H:    # 超过边界移除
                self.enemies.remove(enemy)


if __name__ == '__main__':
    # 创建游戏 并开始游戏
    game=MainGame()
    game.show()
步骤5 击毁判断

在这里插入图片描述

5.1 碰撞检测

pygame 提供了 两个非常方便 的方法可以实现碰撞检测:

  1. pygame.sprite.groupcollide()
    两个精灵组 中 所有的精灵 的碰撞检测

groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
dokill 设置为 True,则发生碰撞的精灵将被自动移除
collided 参数是用于 计算碰撞的回调函数
如果没有指定,则每个精灵必须有一个 rect 属性
返回发生碰撞的 精灵列表

  1. pygame.sprite.spritecollide()
    判断 某个精灵指定精灵组 中的精灵的碰撞

spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
如果将 dokill 设置为 True,则 指定精灵组 中 发生碰撞的精灵将被自动移除
collided 参数是用于 计算碰撞的回调函数
如果没有指定,则每个精灵必须有一个 rect 属性
返回 精灵组 中跟 精灵 发生碰撞的 精灵列表

import pygame
from pygame.locals import *
import random

SCREEN_W = 400
SCREEN_H = 600

# 战机类(继承于游戏精灵类)
class Player(pygame.sprite.Sprite):
...

# 子弹类
class Bullet(pygame.sprite.Sprite):
...

# 敌机类
class Enemy(pygame.sprite.Sprite):
    speed = 1
    def __init__(self, enemy_img, init_pos,enemy_down_imgs):
        pygame.sprite.Sprite.__init__(self)
        self.image = enemy_img          # 图像
        self.rect = enemy_img.get_rect()# 矩形区域
        self.rect.topleft = init_pos    # 初始位置

        # 接收爆炸图像
        self.down_imgs = enemy_down_imgs
        self.down_index = 0

    # 向下移动
    def move(self):
        self.rect.top += self.speed

    # 绘画爆炸图
    def drawImg(self, scr):
        for i in range(len(self.down_imgs)):
            scr.blit(self.down_imgs[self.down_index ], self.rect)
            self.down_index += 1


# 主游戏

class MainGame:

    def __init__(self):
		....

        # 敌机击落图像集合
        self.enemy_down_imgs = []
        self.enemy_down_imgs.append(
            plane_img.subsurface(pygame.Rect(267, 347, 57, 43)))
        self.enemy_down_imgs.append(
            plane_img.subsurface(pygame.Rect(873, 697, 57, 43)))
        self.enemy_down_imgs.append(
            plane_img.subsurface(pygame.Rect(267, 296, 57, 43)))
        self.enemy_down_imgs.append(
            plane_img.subsurface(pygame.Rect(930, 697, 57, 43)))


    # 运行游戏
    def show(self):
        shoot_press,shoot_freq=0,30#射击计数 与频率控制值
        enemy_count,enemy_creat_freq,enemy_move_freq=0,100,20#敌机循环计数  与频率控制
        while True:
            # 检查退出
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
            # 设置背景
            self.screen.fill((255,255,255))
            # 显示战机
            self.player.showPlane(self.screen)
            # 移动与绘画子弹
            self.player.moveBullet()
            self.player.drawBullets(self.screen)

            # 创建、移动与显示敌机
            enemy_count+=1
            if enemy_count>=1000:
                enemy_count=0
            if enemy_count%enemy_creat_freq==0:
                self.createEnemy()
            if enemy_count%enemy_move_freq ==0:
                self.moveEnemy()
            # 判断敌机击落
            self.judgeEnemy()
            self.enemies.draw(self.screen)

            # 检查按键并操作战机
            shoot_press=self.checkPress(shoot_press,shoot_freq)
            # 游戏更新
            pygame.display.update()
    # 检测按键并操作战机
    def checkPress(self,shoot_press,freq=30):
      ...

    # 判断敌机击落
    def judgeEnemy(self):
        # 调用 groupcollide函数 判断两个群组的重合集合
        enemy_dic = pygame.sprite.groupcollide(self.enemies, self.player.bullets, True, True)
        for enemy in enemy_dic:
            enemy.drawImg(self.screen)


    # 随机地创建敌机
    def createEnemy(self):
        self.enemy_pos = [random.randint(0, SCREEN_W - self.enemy_rect.width), 0] # 随机位置
        self.enemy = Enemy(self.enemy_img,self.enemy_pos,self.enemy_down_imgs)    # 创建敌机
        self.enemies.add(self.enemy)                                              # 添加到敌机群

    # 统一地移动敌机
    def moveEnemy(self):
      ...


if __name__ == '__main__':
    # 创建游戏 并开始游戏
    game=MainGame()
    game.show()
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值