使用python中的pygame实现飞机大战(一)


前言

目的:更好理解python中的pygame,梳理python代码逻辑


文章目录

  • 使用python中的pygame实现飞机大战(一)
  • 前言
  • 一、游戏准备
  • 二、游戏实现
  • 1.游戏框架搭建
  • 1.窗口与游戏状态实现
  • 2.界面退出
  • 3.界面暂停
  • 2.精灵与精灵组
  • 3.指示器面板
  • 三、总结



一、游戏准备

游戏流程简单,这里不再赘述。安装pygame模块,新增虚拟环境,用来专门搞游戏这类方向的学习。
新建项目飞机大战,准备好需要的音乐图片等。分别创建核心模块game.py,游戏模块moudle.py,配乐music.py,提示信息tips.py文件

二、游戏实现

1.游戏框架搭建

1.窗口与游戏状态实现

代码如下(窗口与游戏状态实现):

import pygame
from 飞机大战.module import *
from 飞机大战.music import *
from 飞机大战.tips import  *
class Game(object):

    def __init__(self):
        # 游戏窗口初始化
        screen = pygame.Rect(0, 0, 480, 700)  # 游戏窗口
        self.mainwindow = pygame.display.set_mode(screen.size)
        pygame.display.set_caption("飞机大战")
        #游戏精灵

        #游戏状态
        self.pause = False
        self.over = False

    def reset(self):#游戏重置
        self.pause = False
        self.over = False
if __name__ == '__main__':
    game = Game()
    print(game.pause,game.over)
    game.over = True
    print(game.pause,game.over)

看一下基本的执行情况:

python *.py Pythonpygame 飞机大战代码_游戏

2.界面退出

代码如下(ESC与窗口右上角的叉叉):

# 时间:2021/1/1 21:15
# 核心模块
import pygame
from 飞机大战.module import *
from 飞机大战.music import *
from 飞机大战.tips import  *
class Game(object):

    def __init__(self):
        # 游戏窗口初始化
        screen = pygame.Rect(0, 0, 480, 700)  # 游戏窗口
        self.mainwindow = pygame.display.set_mode(screen.size)
        pygame.display.set_caption("飞机大战")
        #游戏精灵

        #游戏状态
        self.pause = False
        self.over = False

    def reset(self):#游戏重置
        self.pause = False
        self.over = False

    def run(self):
        clock = pygame.time.Clock()
        while True:
            if self.event_handler(): #键盘事件监听
                return

            clock.tick(60)# 刷新率

    def event_handler(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:#窗口叉叉退出
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: #ESC退出
                return True


if __name__ == '__main__':
    game = Game()
    game.run()

窗口效果:

python *.py Pythonpygame 飞机大战代码_飞机大战_02


3.界面暂停

代码如下(空格暂停与重新载入游戏):

# 时间:2021/1/1 21:15
# 核心模块
import pygame
from 飞机大战.module import *
from 飞机大战.music import *
from 飞机大战.tips import  *
class Game(object):

    def __init__(self):
        # 游戏窗口初始化
        screen = pygame.Rect(0, 0, 480, 700)  # 游戏窗口
        self.mainwindow = pygame.display.set_mode(screen.size)
        pygame.display.set_caption("飞机大战")
        #游戏精灵

        #游戏状态
        self.pause = False
        self.over = False

    def reset(self):#游戏重置
        self.pause = False
        self.over = False

    def run(self):
        clock = pygame.time.Clock()
        if self.pause == False:
            print("游戏开始")
        while True:
            if self.event_handler(): #键盘事件监听
                return
            if self.pause == True:
                print("游戏暂停")
            elif self.over == True:
                print("游戏结束")
            else:
                print("游戏继续")
            pygame.display.update() #刷新界面
            clock.tick(60)# 刷新率

    def event_handler(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:#窗口叉叉退出
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: #ESC退出
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: #空格暂停与游戏重新开始
                if not self.pause:
                    self.pause = not self.pause
                else:
                    self.reset()
        # return False


if __name__ == '__main__':
    game = Game()
    game.run()

结果实验:

python *.py Pythonpygame 飞机大战代码_python_03


2.精灵与精灵组

正常加载图片太过于繁琐,需要加载图片,确定矩阵位置,对多个组不好管理。为了保证在开发游戏时,能够方便地实现大量图像的绘制工作。pygame的sprite模块专门提供了两个类:精灵Sprite和精灵组Group,类图如下:

python *.py Pythonpygame 飞机大战代码_pygame_04

未使用精灵,代码如下:

def creatimage(self):
        #加载背景、战机图像
        self.backgroundimage = pygame.image.load("./static/images/background.png")
        self.backgroundreact = self.backgroundimage.get_rect()
        self.zhanjiimage = pygame.image.load("./static/images/me1.png")
        self.zhanjireact = self.zhanjiimage.get_rect()
        #战机对齐背景中间
        self.zhanjireact.center =  self.backgroundreact.center

python *.py Pythonpygame 飞机大战代码_pygame_05

添加背景精灵,两张图片拼接,展示整个背景,代码如下:

class Background(GameSprite):
    def __init__(self,outside,*group):
        super(Background, self).__init__("background.png",1,*group)

        if outside:
            self.rect.y = -self.rect.h

    def update(self, *args, **kwargs):
        super(Background, self).update(*args)
        # 背景拼接
        if self.rect.y > self.rect.h:
            self.rect.y = -self.rect.y

python *.py Pythonpygame 飞机大战代码_python_06


添加按钮精灵,标签精灵,面板指示器代码如下:

class Label(py.sprite.Sprite):
    """标签精灵类"""
    font_path = './static/font/MarkerFelt.ttc'

    def __init__(self,text,size,color,*groups):
        super(Label, self).__init__(*groups)

        # 字体
        py.init()
        self.font = py.font.Font(self.font_path,size)
        self.color = color
        self.image = self.font.render(text,True,self.color)
        self.rect = self.image.get_rect()

    def set_text(self,text):
        """设置文字"""
        self.image = self.font.render(text, True, self.color)
        self.rect = self.image.get_rect()

 class Button(GameSprite):

    def __init__(self,image_names,*groups):
        #image_names是元组,0暂停,1继续
        super(Button, self).__init__(image_names[0],0,*groups)
        self.images = [py.image.load(self.path + image) for image in image_names]

    def switch(self,is_pause):
        self.image = self.images[1 if is_pause else 0]

3.指示器面板

代码如下:

"""面板指示器标签"""
import pygame as py
from 飞机大战.module import *
from 飞机大战.game import *
class Panel(object):

    margin = 10 #间距
    white = (255,255,255)
    gray = (64,64,64)
    screen = py.Rect(0, 0, 480, 700)

    def __init__(self,display_group):
        self.score = 0 #得分
        self.lives = 6 #命数
        self.level = 1 #关卡
        self.best_score = 0 #最佳分数

        # 按钮
        self.status_sprite = Button(("pause.png","resume.png"),display_group)
        self.status_sprite.rect.topleft = (self.margin,self.margin)
        self.bomb_sprite = GameSprite("bomb.png", 0, display_group)  # 生命精灵
        self.bomb_sprite.rect.bottomleft = (self.margin,self.screen.bottom-self.margin )
        self.lives_sprite = GameSprite("life.png", 0, display_group)  # 子弹精灵
        self.lives_sprite.rect.right = self.screen.right-6*self.margin
        self.lives_sprite.rect.bottom = self.screen.bottom-self.margin
        # bullet_sprite.rect.bottomleft = screen.bottomleft
        # lives_sprite.rect.bottomright = screen.bottomright
        # 图像精灵

        # 标签
        self.best_label = Label('Best score:%d'%self.best_score,36,self.white,display_group)
        self.best_label.rect.center = self.screen.center

        self.status_label = Label('Game pause',48,self.white,display_group)
        self.status_label.rect.midbottom = (self.best_label.rect.centerx,
                                            self.best_label.rect.y-2*self.margin)
        self.score_label = Label('Current score:%d'%self.score, 21, self.gray,display_group)
        self.score_label.rect.right = self.screen.right - 2 * self.margin
        self.score_label.rect.top = self.screen.top + 2*self.margin

        self.bomb_label = Label('X 3', 32, self.gray,display_group)
        self.bomb_label.rect.midleft = (self.bomb_sprite.rect.right + self.margin,
                                         self.bomb_sprite.rect.centery)
        self.lives_label = Label('X %d'%self.lives,32,self.gray,display_group)
        self.lives_label.rect.midright = (self.screen.right-self.margin,
                                         self.bomb_sprite.rect.centery)

        # 提示标签
        self.tips_label = Label('Press space to continue',22,self.white,display_group)
        self.tips_label.rect.midtop = (self.best_label.rect.centerx,
                                       self.best_label.rect.bottom + 8*self.margin)

暂时效果:

python *.py Pythonpygame 飞机大战代码_pygame_07


三、总结

暂时先到这里面板指示器这里,等有时间继续。