Pygame開發(fā)游戲詳細(xì)流程記錄
一、Pygame 核心架構(gòu)
游戲主循環(huán)
├── 事件處理 (Event Handling)
├── 游戲邏輯更新 (Game Logic)
├── 渲染繪制 (Rendering)
└── 幀率控制 (FPS Control)
二、完整開發(fā)流程詳解
1.基礎(chǔ)框架搭建
import pygame
import sys
class Game:
def __init__(self):
"""初始化游戲"""
pygame.init()
# 1. 創(chuàng)建游戲窗口
self.screen_width = 800
self.screen_height = 600
self.screen = pygame.display.set_mode(
(self.screen_width, self.screen_height)
)
pygame.display.set_caption("我的游戲")
# 2. 初始化游戲時(shí)鐘(控制幀率)
self.clock = pygame.time.Clock()
self.FPS = 60
# 3. 游戲狀態(tài)
self.running = True
self.game_over = False
# 4. 顏色定義(RGB)
self.BLACK = (0, 0, 0)
self.WHITE = (255, 255, 255)
self.RED = (255, 0, 0)
self.GREEN = (0, 255, 0)
self.BLUE = (0, 0, 255)
# 5. 初始化游戲資源
self.load_resources()
def load_resources(self):
"""加載游戲資源"""
# 字體
self.font_small = pygame.font.SysFont(None, 36)
self.font_large = pygame.font.SysFont(None, 72)
# 加載圖片
try:
self.player_image = pygame.image.load("player.png").convert_alpha()
except:
# 如果圖片不存在,創(chuàng)建一個(gè)矩形代替
self.player_image = pygame.Surface((50, 50))
self.player_image.fill(self.BLUE)
# 加載音效
try:
self.jump_sound = pygame.mixer.Sound("jump.wav")
except:
self.jump_sound = None
# 背景音樂
pygame.mixer.music.load("bgm.mp3")
pygame.mixer.music.play(-1) # -1表示循環(huán)播放
2.主游戲循環(huán)
def run(self):
"""主游戲循環(huán)"""
while self.running:
# 1. 處理事件
self.handle_events()
# 2. 更新游戲狀態(tài)(只有游戲沒結(jié)束時(shí)才更新)
if not self.game_over:
self.update()
# 3. 繪制畫面
self.render()
# 4. 控制幀率
self.clock.tick(self.FPS)
# 游戲結(jié)束,退出
self.quit()
def handle_events(self):
"""事件處理"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
# 鍵盤按下事件
elif event.type == pygame.KEYDOWN:
self.on_key_down(event.key)
# 鍵盤釋放事件
elif event.type == pygame.KEYUP:
self.on_key_up(event.key)
# 鼠標(biāo)事件
elif event.type == pygame.MOUSEBUTTONDOWN:
self.on_mouse_click(event.pos, event.button)
3.精靈系統(tǒng)(Sprite System)
class Player(pygame.sprite.Sprite):
"""玩家角色類"""
def __init__(self, x, y):
super().__init__()
# 創(chuàng)建圖像和矩形
self.image = pygame.Surface((50, 50))
self.image.fill((0, 0, 255))
# 加載動(dòng)畫幀
self.frames = []
self.load_animation_frames()
self.current_frame = 0
self.animation_speed = 0.2
self.animation_timer = 0
self.rect = self.image.get_rect()
self.rect.center = (x, y)
# 物理屬性
self.velocity = pygame.Vector2(0, 0)
self.speed = 5
self.jump_power = -15
self.gravity = 0.8
self.on_ground = False
# 游戲?qū)傩?
self.health = 100
self.score = 0
def load_animation_frames(self):
"""加載動(dòng)畫幀"""
for i in range(4):
frame = pygame.Surface((50, 50))
frame.fill((0, 0, 200 + i * 15))
self.frames.append(frame)
def update(self, platforms):
"""更新玩家狀態(tài)"""
# 處理用戶輸入
keys = pygame.key.get_pressed()
# 水平移動(dòng)
self.velocity.x = 0
if keys[pygame.K_LEFT]:
self.velocity.x = -self.speed
if keys[pygame.K_RIGHT]:
self.velocity.x = self.speed
# 跳躍
if keys[pygame.K_SPACE] and self.on_ground:
self.velocity.y = self.jump_power
self.on_ground = False
# 應(yīng)用重力
self.velocity.y += self.gravity
# 水平移動(dòng)
self.rect.x += self.velocity.x
# 水平碰撞檢測
self.check_horizontal_collision(platforms)
# 垂直移動(dòng)
self.rect.y += self.velocity.y
# 垂直碰撞檢測
self.check_vertical_collision(platforms)
# 更新動(dòng)畫
self.update_animation()
# 邊界檢查
self.check_bounds()
def check_horizontal_collision(self, platforms):
for platform in platforms:
if self.rect.colliderect(platform):
if self.velocity.x > 0: # 向右移動(dòng)
self.rect.right = platform.left
elif self.velocity.x < 0: # 向左移動(dòng)
self.rect.left = platform.right
def check_vertical_collision(self, platforms):
self.on_ground = False
for platform in platforms:
if self.rect.colliderect(platform):
if self.velocity.y > 0: # 向下移動(dòng)
self.rect.bottom = platform.top
self.velocity.y = 0
self.on_ground = True
elif self.velocity.y < 0: # 向上移動(dòng)
self.rect.top = platform.bottom
self.velocity.y = 0
def update_animation(self):
"""更新動(dòng)畫幀"""
self.animation_timer += self.animation_speed
if self.animation_timer >= 1:
self.current_frame = (self.current_frame + 1) % len(self.frames)
self.image = self.frames[self.current_frame]
self.animation_timer = 0
def check_bounds(self):
"""檢查邊界"""
if self.rect.top > 600: # 掉落屏幕
self.health = 0
4.游戲場景管理
class GameScene:
"""游戲場景基類"""
def __init__(self, game):
self.game = game
def handle_events(self):
pass
def update(self):
pass
def render(self):
pass
class MainMenuScene(GameScene):
"""主菜單場景"""
def __init__(self, game):
super().__init__(game)
self.buttons = []
self.create_buttons()
def create_buttons(self):
"""創(chuàng)建菜單按鈕"""
button_width, button_height = 200, 50
# 開始游戲按鈕
start_rect = pygame.Rect(
self.game.screen_width // 2 - button_width // 2,
200,
button_width,
button_height
)
self.buttons.append({
'rect': start_rect,
'text': '開始游戲',
'action': self.start_game
})
# 退出游戲按鈕
quit_rect = pygame.Rect(
self.game.screen_width // 2 - button_width // 2,
280,
button_width,
button_height
)
self.buttons.append({
'rect': quit_rect,
'text': '退出游戲',
'action': self.quit_game
})
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.game.running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # 左鍵
self.check_button_click(event.pos)
def check_button_click(self, pos):
"""檢查按鈕點(diǎn)擊"""
for button in self.buttons:
if button['rect'].collidepoint(pos):
button['action']()
def start_game(self):
"""切換到游戲場景"""
self.game.current_scene = GamePlayScene(self.game)
def quit_game(self):
self.game.running = False
def render(self):
# 繪制背景
self.game.screen.fill((30, 30, 70))
# 繪制標(biāo)題
title_font = pygame.font.SysFont(None, 72)
title_text = title_font.render("我的游戲", True, (255, 255, 255))
title_rect = title_text.get_rect(center=(self.game.screen_width//2, 100))
self.game.screen.blit(title_text, title_rect)
# 繪制按鈕
for button in self.buttons:
# 繪制按鈕背景
pygame.draw.rect(self.game.screen, (50, 150, 200), button['rect'])
pygame.draw.rect(self.game.screen, (255, 255, 255), button['rect'], 3)
# 繪制按鈕文字
button_font = pygame.font.SysFont(None, 36)
button_text = button_font.render(button['text'], True, (255, 255, 255))
text_rect = button_text.get_rect(center=button['rect'].center)
self.game.screen.blit(button_text, text_rect)
5.完整游戲示例:平臺(tái)跳躍游戲
import pygame
import sys
import random
class PlatformGame:
def __init__(self):
pygame.init()
# 屏幕設(shè)置
self.WIDTH = 800
self.HEIGHT = 600
self.screen = pygame.display.set_mode((self.WIDTH, self.HEIGHT))
pygame.display.set_caption("平臺(tái)跳躍")
# 顏色
self.SKY_BLUE = (135, 206, 235)
self.GROUND_COLOR = (101, 67, 33)
self.PLATFORM_COLOR = (0, 200, 100)
# 游戲狀態(tài)
self.clock = pygame.time.Clock()
self.FPS = 60
self.running = True
self.score = 0
self.font = pygame.font.SysFont(None, 36)
# 游戲?qū)ο?
self.player = pygame.Rect(100, 300, 30, 30)
self.player_vel_y = 0
self.gravity = 0.8
self.jump_strength = -15
self.on_ground = False
# 平臺(tái)
self.platforms = [
pygame.Rect(0, 500, 800, 100), # 地面
pygame.Rect(200, 400, 200, 20),
pygame.Rect(450, 350, 150, 20),
pygame.Rect(300, 250, 200, 20),
pygame.Rect(100, 200, 150, 20),
pygame.Rect(550, 150, 200, 20),
]
# 金幣
self.coins = []
self.generate_coins()
# 敵人
self.enemies = []
self.spawn_timer = 0
self.spawn_interval = 2000 # 毫秒
def generate_coins(self):
"""生成金幣"""
for platform in self.platforms[1:]: # 除了地面
x = random.randint(platform.left + 10, platform.right - 20)
y = platform.top - 30
self.coins.append(pygame.Rect(x, y, 15, 15))
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and self.on_ground:
self.player_vel_y = self.jump_strength
self.on_ground = False
elif event.key == pygame.K_r: # 重新開始
self.__init__()
def update(self):
# 鍵盤輸入
keys = pygame.key.get_pressed()
# 水平移動(dòng)
player_speed = 5
if keys[pygame.K_LEFT]:
self.player.x -= player_speed
if keys[pygame.K_RIGHT]:
self.player.x += player_speed
# 應(yīng)用重力
self.player_vel_y += self.gravity
self.player.y += self.player_vel_y
# 邊界檢查
if self.player.left < 0:
self.player.left = 0
if self.player.right > self.WIDTH:
self.player.right = self.WIDTH
# 平臺(tái)碰撞檢測
self.on_ground = False
for platform in self.platforms:
if self.player.colliderect(platform):
if self.player_vel_y > 0: # 下落
self.player.bottom = platform.top
self.player_vel_y = 0
self.on_ground = True
elif self.player_vel_y < 0: # 上升
self.player.top = platform.bottom
self.player_vel_y = 0
# 金幣收集
for coin in self.coins[:]:
if self.player.colliderect(coin):
self.coins.remove(coin)
self.score += 10
# 生成敵人
current_time = pygame.time.get_ticks()
if current_time - self.spawn_timer > self.spawn_interval:
self.enemies.append(pygame.Rect(
random.randint(0, self.WIDTH - 30),
-30,
30, 30
))
self.spawn_timer = current_time
# 更新敵人
for enemy in self.enemies[:]:
enemy.y += 3
if enemy.top > self.HEIGHT:
self.enemies.remove(enemy)
# 玩家與敵人碰撞
if self.player.colliderect(enemy):
self.game_over()
def game_over(self):
"""游戲結(jié)束"""
game_over_font = pygame.font.SysFont(None, 72)
game_over_text = game_over_font.render("游戲結(jié)束!", True, (255, 0, 0))
score_text = self.font.render(f"最終得分: {self.score}", True, (255, 255, 255))
restart_text = self.font.render("按 R 重新開始", True, (255, 255, 255))
# 繪制半透明背景
overlay = pygame.Surface((self.WIDTH, self.HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 180))
self.screen.blit(overlay, (0, 0))
# 繪制文字
self.screen.blit(game_over_text,
(self.WIDTH//2 - game_over_text.get_width()//2,
self.HEIGHT//2 - 100))
self.screen.blit(score_text,
(self.WIDTH//2 - score_text.get_width()//2,
self.HEIGHT//2))
self.screen.blit(restart_text,
(self.WIDTH//2 - restart_text.get_width()//2,
self.HEIGHT//2 + 50))
pygame.display.flip()
# 等待玩家按鍵
waiting = True
while waiting:
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
waiting = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
self.__init__()
waiting = False
def render(self):
# 繪制背景
self.screen.fill(self.SKY_BLUE)
# 繪制平臺(tái)
for platform in self.platforms:
pygame.draw.rect(self.screen, self.PLATFORM_COLOR, platform)
# 繪制地面
pygame.draw.rect(self.screen, self.GROUND_COLOR, self.platforms[0])
# 繪制金幣
for coin in self.coins:
pygame.draw.circle(self.screen, (255, 215, 0), coin.center, coin.width//2)
# 繪制敵人
for enemy in self.enemies:
pygame.draw.rect(self.screen, (255, 0, 0), enemy)
# 繪制玩家
pygame.draw.rect(self.screen, (0, 0, 255), self.player)
# 繪制分?jǐn)?shù)
score_text = self.font.render(f"分?jǐn)?shù): {self.score}", True, (255, 255, 255))
self.screen.blit(score_text, (10, 10))
pygame.display.flip()
def run(self):
while self.running:
self.handle_events()
self.update()
self.render()
self.clock.tick(self.FPS)
pygame.quit()
sys.exit()
if __name__ == "__main__":
game = PlatformGame()
game.run()
三、最佳實(shí)踐和優(yōu)化技巧
1.性能優(yōu)化
# 1. 使用雙緩沖
screen = pygame.display.set_mode((width, height), pygame.DOUBLEBUF)
# 2. 圖像轉(zhuǎn)換優(yōu)化
image = pygame.image.load("image.png").convert() # 普通轉(zhuǎn)換
image = pygame.image.load("image.png").convert_alpha() # 帶透明度轉(zhuǎn)換
# 3. 臟矩形更新(只更新變化的部分)
dirty_rects = []
dirty_rects.append(player.rect)
pygame.display.update(dirty_rects)
# 4. 對(duì)象池(減少對(duì)象創(chuàng)建銷毀)
class ObjectPool:
def __init__(self, create_func, max_size=100):
self.pool = []
self.create_func = create_func
self.max_size = max_size
def get(self):
if self.pool:
return self.pool.pop()
return self.create_func()
def recycle(self, obj):
if len(self.pool) < self.max_size:
self.pool.append(obj)
2.狀態(tài)機(jī)管理
class StateMachine:
def __init__(self):
self.states = {}
self.current_state = None
def add_state(self, name, state):
self.states[name] = state
def change_state(self, name):
if self.current_state:
self.current_state.exit()
self.current_state = self.states[name]
self.current_state.enter()
def update(self):
if self.current_state:
self.current_state.update()
def render(self):
if self.current_state:
self.current_state.render()
class GameState:
def enter(self):
pass
def exit(self):
pass
def update(self):
pass
def render(self):
pass
3.粒子系統(tǒng)
class Particle:
def __init__(self, x, y):
self.x = x
self.y = y
self.vx = random.uniform(-2, 2)
self.vy = random.uniform(-5, -2)
self.lifetime = 60
self.color = random.choice([(255, 255, 0), (255, 165, 0)])
def update(self):
self.x += self.vx
self.y += self.vy
self.vy += 0.1
self.lifetime -= 1
def draw(self, screen):
radius = max(1, self.lifetime // 15)
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), radius)
四、調(diào)試技巧
- 顯示幀率
fps_text = font.render(f"FPS: {int(clock.get_fps())}", True, WHITE)
- 顯示調(diào)試信息
def draw_debug_info():
debug_info = [
f"玩家位置: ({player.rect.x}, {player.rect.y})",
f"速度: ({player.velocity.x:.1f}, {player.velocity.y:.1f})",
f"金幣數(shù)量: {len(coins)}",
f"敵人數(shù)量: {len(enemies)}"
]
for i, info in enumerate(debug_info):
text = font.render(info, True, WHITE)
screen.blit(text, (10, 30 + i * 25))
- 碰撞框顯示
pygame.draw.rect(screen, (255, 0, 0), object.rect, 2) # 紅色邊框
五、項(xiàng)目結(jié)構(gòu)建議
my_game/ ├── main.py # 游戲主入口 ├── game.py # 游戲主類 ├── player.py # 玩家類 ├── enemy.py # 敵人類 ├── platform.py # 平臺(tái)類 ├── powerup.py # 道具類 ├── scene/ │ ├── menu_scene.py # 菜單場景 │ ├── game_scene.py # 游戲場景 │ └── game_over_scene.py ├── assets/ │ ├── images/ │ ├── sounds/ │ └── fonts/ ├── config.py # 配置文件 └── utils.py # 工具函數(shù)
按照這個(gè)流程,你可以從簡單到復(fù)雜逐步開發(fā)完整的Pygame游戲。記?。合葘?shí)現(xiàn)核心玩法,再添加特效和優(yōu)化!
總結(jié)
到此這篇關(guān)于Pygame開發(fā)游戲詳細(xì)流程記錄的文章就介紹到這了,更多相關(guān)Pygame開發(fā)游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)杰卡德距離以及環(huán)比算法講解
這篇文章主要為大家介紹了Python實(shí)現(xiàn)杰卡德距離以及環(huán)比算法的示例講解,有需要的朋友可以借鑒參考下2022-02-02
Eclipse和PyDev搭建完美Python開發(fā)環(huán)境教程(Windows篇)
這篇文章主要介紹了Eclipse和PyDev搭建完美Python開發(fā)環(huán)境教程(Windows篇),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下。2016-11-11
解決PyCharm不在run輸出運(yùn)行結(jié)果而不是再Console里輸出的問題
這篇文章主要介紹了解決PyCharm不在run輸出運(yùn)行結(jié)果而不是再Console里輸出的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
解決python字典對(duì)值(值為列表)賦值出現(xiàn)重復(fù)的問題
今天小編就為大家分享一篇解決python字典對(duì)值(值為列表)賦值出現(xiàn)重復(fù)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01
為什么入門大數(shù)據(jù)選擇Python而不是Java?
為什么入門大數(shù)據(jù)選擇Python而不是Java?這篇文章就來談?wù)剬W(xué)習(xí)大數(shù)據(jù)入門語言的選擇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
OpenCV-Python 攝像頭實(shí)時(shí)檢測人臉代碼實(shí)例
這篇文章主要介紹了OpenCV-Python 攝像頭實(shí)時(shí)檢測人臉,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
淺析form標(biāo)簽中的GET和POST提交方式區(qū)別
在HTML中,form表單的作用是收集標(biāo)簽中的內(nèi)容<form>...</form> 中間可以由訪問者添加類似于文本,選擇,或者一些控制模塊等等.然后這些內(nèi)容將會(huì)被送到服務(wù)端2021-09-09
使用Python設(shè)置PDF中圖片的透明度的實(shí)現(xiàn)方法
在PDF文檔的設(shè)計(jì)與內(nèi)容創(chuàng)作過程中,圖像的透明度設(shè)置是一個(gè)重要的操作,尤其是在處理圖文密集型PDF文檔時(shí),本文將介紹如何使用Python添加指定透明度的圖片到PDF文檔或調(diào)整PDF文檔中現(xiàn)有圖片的透明度,需要的朋友可以參考下2024-09-09
Python利用 utf-8-sig 編碼格式解決寫入 csv 文件亂碼問題
這篇文章主要介紹了Python利用 utf-8-sig 編碼格式解決寫入 csv 文件亂碼問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02

