運作效果
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90ERNJTUE9kMBRVT3V1MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4kDN0AzMxMjMwMzNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
代碼
# 先導入系統子產品
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()
打包成exe文章連結
記一次pygame小程式打包成exe
圖檔素材位址
連結: https://pan.baidu.com/s/1mMeJfSqEjSgMATxU6SXfZg
提取碼: 9cge