使用python中的pygame实现飞机大战(一)
前言
目的:更好理解python中的pygame,梳理python代码逻辑
一、游戏准备
游戏流程简单,这里不再赘述。安装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)
看一下基本的执行情况:
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()
窗口效果:
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()
结果实验:
2.精灵与精灵组
正常加载图片太过于繁琐,需要加载图片,确定矩阵位置,对多个组不好管理。为了保证在开发游戏时,能够方便地实现大量图像的绘制工作。pygame的sprite模块专门提供了两个类:精灵Sprite和精灵组Group,类图如下:
未使用精灵,代码如下:
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
添加背景精灵,两张图片拼接,展示整个背景,代码如下:
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
添加按钮精灵,标签精灵,面板指示器代码如下:
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)
暂时效果:
三、总结
暂时先到这里面板指示器这里,等有时间继续。