# 先导入系统模块
import sys
# 随机模块
import random
# 再导入第三方模块
import pygame
import pygame.locals
# 背景图片路径
IMG_BACKGROUND = "res/img_bg_level_1.jpg"
# 敌机图片路径 元组
IMG_ENEMYPLANE = ("res/img-plane_1.png", "res/img-plane_2.png", "res/img-plane_3.png", "res/img-plane_4.png",
"res/img-plane_5.png", "res/img-plane_6.png", "res/img-plane_7.png")
# 玩家飞机图片路径
IMG_PLAYER_PLANE = "res/hero2.png"
# 子弹图片
IMG_BULLET = "res/bullet_13.png"
class Model(object):
"""提供基础模型"""
# 窗口对象
window = None
def __init__(self, img_path, x, y):
# 图片对象
self.img = pygame.image.load(img_path)
# x坐标
self.x = x
# y坐标
self.y = y
def display(self):
# 将要显示的对象添加到窗体中, 并指定其坐标
Model.window.blit(self.img, (self.x, self.y))
class Game(object):
"""游戏整体控制"""
# 窗口宽度
WINDOW_WIDTH = 512
# 窗口高度
WINDOW_HEIGHT = 768
# 窗体标题
WINDOW_TITLE = "Plane Battle v1.0"
# 小图标路径
APP_ICON = "res/app.ico"
def __init__(self):
# 窗体对象
self.window = None
# 背景对象
self.background = None
# 敌机对象
self.enemy_planes = list()
# 玩家对象
self.player_plane = None
def run(self):
"""运行入口, 整体游戏控制"""
# 框架初始化
self.frame_init()
# 模型初始化
self.model_init()
# 构造反复执行的机制, 刷新窗体、使窗体保持在屏幕上
while True:
# 背景移动
self.background.move()
# 显示背景
self.background.display()
for enemy_plane in self.enemy_planes:
# 敌机下降
enemy_plane.move()
# 显示敌机(加载贴图)
enemy_plane.display()
# 显示玩家
self.player_plane.display()
# 把敌机列表传给玩家飞机, 好进行子弹与敌机的碰撞检测
self.player_plane.collision_checking(self.enemy_planes)
# 刷新窗体
pygame.display.update()
# 事件监听
self.event_init()
def frame_init(self):
"""窗体初始化"""
# 设置窗体对象
self.window = pygame.display.set_mode((Game.WINDOW_WIDTH, Game.WINDOW_HEIGHT))
# 将窗口对象传给Model类属性
Model.window = self.window
# 左上小图标对象
app_img = pygame.image.load(Game.APP_ICON)
# 设置窗体图标
pygame.display.set_icon(app_img)
# 设置窗体标题文本
pygame.display.set_caption(Game.WINDOW_TITLE)
def model_init(self):
"""初始化窗体中的对象"""
# 背景对象
self.background = Background(IMG_BACKGROUND, 0, 0)
for _ in IMG_ENEMYPLANE:
# 加入多加敌机到 敌机列表中
self.enemy_planes.append(EnemyPlane())
# 玩家对象
self.player_plane = PlayerPlane(IMG_PLAYER_PLANE, PlayerPlane.PLAYERPLANE_X, PlayerPlane.PLAYERPLANE_Y)
def event_init(self):
"""事件监听"""
# 获取事件列表中的每一个事件
for event in pygame.event.get():
# 判断事件类别是否为退出事件
if event.type == pygame.locals.QUIT:
# 退出程序
sys.exit()
# 当事件类别是鼠标移动动作时
if event.type == pygame.locals.MOUSEMOTION:
# 获取鼠标坐标位置
position = pygame.mouse.get_pos()
# 根据鼠标的位置设置玩家飞机的位置
self.player_plane.x = position[0] - PlayerPlane.PLAYERPLANE_WIDTH / 2
self.player_plane.y = position[1] - PlayerPlane.PLAYERPLANE_HEIGHT / 2 + 5
# 获取鼠标是否按下的状态
mouse_state = pygame.mouse.get_pressed()
# 判断是否按下鼠标左键
if mouse_state[0] == 1:
# 获取鼠标坐标位置
position = pygame.mouse.get_pos()
# 初始化子弹位置
self.player_plane.bullets.append(
Bullet(IMG_BULLET, position[0] - Bullet.BULLET_WIDTH / 2,
position[1] - Bullet.BULLET_HEIGHT - 30))
# 当玩家按下鼠标左键时, 才开始游戏
self.player_plane.start_game = True
class Background(Model):
"""背景"""
def display(self):
"""装载上下两张图片到窗体中"""
# 将要显示的对象添加到窗体中, 并指定其坐标
Model.window.blit(self.img, (self.x, self.y))
Model.window.blit(self.img, (self.x, self.y - Game.WINDOW_HEIGHT))
def move(self):
"""背景移动"""
# 当纵轴的值小于等于屏幕高度时:
if self.y <= Game.WINDOW_HEIGHT:
# 移动图片
self.y += 1
else:
# 图片归位
self.y = 0
class PlayerPlane(Model):
"""玩家飞机"""
# 玩家飞机的宽度
PLAYERPLANE_WIDTH = 120
# 玩家飞机的高度
PLAYERPLANE_HEIGHT = 78
# 玩家飞机的初始位置
PLAYERPLANE_X = 200
PLAYERPLANE_Y = 500
def __init__(self, img, x, y):
super().__init__(img, x, y)
# 子弹列表对象
self.bullets = list()
# 需要删除的子弹列表
self.remove_bullets = list()
# 玩家是否开始游戏标志
self.start_game = False
def collision_checking(self, enemy_list):
"""子弹的显示, 还有子弹与敌机的碰撞检测"""
for bullet in self.bullets:
# 子弹移动
bullet.move()
# 子弹显示
bullet.display()
# 当子弹飞出屏幕时:
if bullet.y < -Bullet.BULLET_HEIGHT:
# 将这个子弹添加到待删除子弹的列表
self.remove_bullets.append(bullet)
# 子弹没有飞出屏幕
else:
# 子弹矩形
bullet_rect = pygame.locals.Rect(bullet.x, bullet.y, Bullet.BULLET_WIDTH, Bullet.BULLET_HEIGHT)
for enemy in enemy_list:
# 敌机矩形
enemy_rect = pygame.locals.Rect(enemy.x, enemy.y, EnemyPlane.ENEMYPLANE_WIDTH, EnemyPlane.ENEMYPLANE_HEIGHT)
# 两个矩形碰撞检测
if pygame.Rect.colliderect(bullet_rect, enemy_rect):
# 子弹碰撞敌机后, 敌机归位到屏幕上方
enemy.enemy_plane_init()
# 子弹加入删除列表
self.remove_bullets.append(bullet)
# 一颗子弹只能撞击 一架敌机, 退出for循环
break
# 玩家飞机矩形
player_rect = pygame.locals.Rect(self.x, self.y, PlayerPlane.PLAYERPLANE_WIDTH,
PlayerPlane.PLAYERPLANE_HEIGHT)
for enemy in enemy_list:
# 敌机矩形
enemy_rect = pygame.locals.Rect(enemy.x, enemy.y, EnemyPlane.ENEMYPLANE_WIDTH,
EnemyPlane.ENEMYPLANE_HEIGHT)
# 玩家飞机与敌机碰撞检测
if pygame.Rect.colliderect(player_rect, enemy_rect):
# 一开始游戏时, 玩家按下鼠标左键, 才能判断玩家飞机与敌机碰撞检测, 再退出游戏
if self.start_game:
# 退出程序
sys.exit()
# 根据 待删除子弹的列表 删除子弹列表中的对象
for bullet in self.remove_bullets:
self.bullets.remove(bullet)
else:
# 删除完后, 需要将 待删除列表清空
self.remove_bullets.clear()
class Bullet(Model):
"""子弹"""
# 子弹的宽度
BULLET_WIDTH = 20
# 子弹的高度
BULLET_HEIGHT = 29
# 子弹间的移动速度
BULLET_SPEED = 8
def move(self):
"""子弹移动"""
self.y -= Bullet.BULLET_SPEED
class EnemyPlane(Model):
"""敌机"""
# 敌机的宽度
ENEMYPLANE_WIDTH = 100
# 敌机的高度
ENEMYPLANE_HEIGHT = 68
# 敌机移动速度
ENEMYPLANE_SPEED = 4
def __init__(self):
self.enemy_plane_init()
def enemy_plane_init(self):
"""初始化敌机"""
# 敌机归到窗口上方
self.y = 0 - EnemyPlane.ENEMYPLANE_HEIGHT
# 敌机横坐标随机出现
self.x = random.randint(0, Game.WINDOW_WIDTH - EnemyPlane.ENEMYPLANE_WIDTH)
# 贴图随机
self.img = pygame.image.load(IMG_ENEMYPLANE[random.randint(0, 6)])
def move(self):
# 当敌机没有下降出屏幕高度时
if self.y <= Game.WINDOW_HEIGHT:
# 移动敌机
self.y += EnemyPlane.ENEMYPLANE_SPEED
else:
self.enemy_plane_init()
if __name__ == '__main__':
Game().run()
记一次pygame小程序打包成exe
链接: https://pan.baidu.com/s/1mMeJfSqEjSgMATxU6SXfZg
提取码: 9cge