Python中pygame游戲模塊的用法詳解
Python中的pygame游戲模塊的使用
Pygame 是一組用來開發(fā)游戲軟件的 Python 程序模塊,Pygame 在 SDL(Simple DirectMedia Layer) 的基礎(chǔ)上開發(fā)而成。它提供了諸多操作模塊,比如圖像模塊(image)、聲音模塊(mixer)、輸入/輸出(鼠標、鍵盤、顯示屏)模塊,擅長開發(fā) 2D 游戲,Python 也提供了開發(fā) 3D 游戲的軟件包,比如 Pyglet、Panda3D、PyOgre 等。Pygame 是一個高可移植性的模塊可以支持多個操作系統(tǒng)。用它來開發(fā)小游戲非常適合。官網(wǎng)https://www.pygame.org/news
pygame模塊的安裝
若使用pygame模塊(python的2D游戲開發(fā)庫),這是第三方(擴展)模塊,若未預先裝,需要在CMD中,使用 pip install pygame 先裝入,可能需要花點時間。
查看是否電腦上是否有pygame,在CMD中,使用pip list命令,參見下圖

若沒有 pygame,需要在CMD中,使用 pip install pygame 命令安裝,參見下圖:

驗證是否成功安裝
法一、在CMD中,使用python -m pygame.examples.aliens命令驗證,參見下圖:

法二、進入Python的交互界面,輸入以下命令驗證是否成功安裝,參見下圖:

不報錯,則說明安裝成功。
pygame快速入門
Pygame的坐標原點(0,0)點位于左上角,X軸自左向右,Y軸自上向下,單位為像素,參見下圖:

在游戲中,所有可見的元素都是以矩形區(qū)域來描述位置的;
pygame專門提供了一個類Rect 用于 描述矩形區(qū)域,格式:
Rect(x,y,width,height)
Pygame的Rect對象,表示的區(qū)域必須位于一個 Surface 對象之上,比如游戲的主窗口(screen)。上述方法由四個關(guān)鍵參數(shù)值構(gòu)成,分別是 left、top、width、height
pygame. Rect(left, top, width, height)

display 用于創(chuàng)建、管理游戲窗口
pygame.display.set_mode() #初始化游戲顯示窗口
pygame.dispaly.update() #刷新屏幕內(nèi)容顯示,稍后使用
為了做到游戲程序啟動后,不會立即退出,通常會在游戲程序中使用一個游戲循環(huán)。
pygame開發(fā)游戲的大體框架結(jié)構(gòu)如下:
import pygame
# 初始化pygame
pygame.init()
# 創(chuàng)建游戲的窗口 350 * 573(寬,高);注意:此窗口的大小是依據(jù)游戲的背景圖片而設(shè)定的
screen=pygame.display.set_mode((350,600))
# 游戲循環(huán)
while True:
pass
示例代碼如下:
# 導入所需的模塊
import pygame
import sys
# 導入所有pygame.locals里的變量(比如下面大寫的QUIT變量)
from pygame.locals import *
# 初始化pygame
pygame.init()
# 設(shè)置窗口的大小,單位為像素
screen = pygame.display.set_mode((450, 300))
# 設(shè)置窗口標題
pygame.display.set_caption('Hello World')
# 程序主循環(huán)
while True:
# 獲取事件
for event in pygame.event.get():
# 判斷事件是否為退出事件
if event.type == QUIT:
# 退出pygame
pygame.quit()
# 退出系統(tǒng)
sys.exit()
# 繪制屏幕內(nèi)容
pygame.display.update()
運行之,顯示如下:

Pygame設(shè)置窗口圖標和設(shè)置窗口背景圖片
#設(shè)置窗口圖標,下面兩句
icon = pygame.image.load("./images/xyicon.png") # 加載圖像數(shù)據(jù)
pygame.display.set_icon(icon) #設(shè)置圖標
#設(shè)置窗口背景圖片,下面三兩句
bg = pygame.image.load("./images/background.png") # 加載圖像數(shù)據(jù)
screen.blit(bg,(0,0)) #繪制圖像 blit(圖像,位置);
pygame.display.update() #更新屏幕顯示
在前面示例代碼,設(shè)置窗口標題之后,添加設(shè)置窗口圖標和設(shè)置窗口背景圖片:

運行之,如下圖所示:

Pygame播放音頻
有兩個方法:
☆播放特效聲音:
pygame.mixer.Sound(filename)
該方法返回一個Sound對象,調(diào)用它的.play( )方法,即可播放較短的音頻文件(如游戲中的槍炮聲等);
☆播放背景音樂:
pygame.mixer.music.load(filename)
該方法用來加載背景音樂,之后調(diào)用pygame.mixer.music.play( )方法就可以播放背景音樂(在同一個時刻只允許加載一個背景音樂)
# 加載并播放一個特效音頻文件)
sound = pygame.mixer.Sound('./music/alter.mp3')
sound.play()
# 加載背景音樂文件
pygame.mixer.music.load('./music/bgmusic.mp3')
# 播放背景音樂,第一個參數(shù)為播放的次數(shù)(-1表示無限循環(huán)),第二個參數(shù)是設(shè)置播放的起點(單位為秒)
pygame.mixer.music.play(-1, 0.0)
可以在適當?shù)牡胤?,作為測試在背景圖片之后插入播放音頻代碼段,當然音頻文件需要準備好。
Pygame繪制圖形
Pygame繪制圖形的常用的方法:
☆ pygame.draw.line(Surface, color, start_pos, end_pos, width)此方法用于繪制一條線段
☆ pygame.draw.aaline(Surface, color, start_pos, end_pos, blend)此方法用于繪制一條抗鋸齒的線
☆ pygame.draw.lines(Surface, color, closed, pointlist, width)此方法用于繪制一條折線
☆ pygame.draw.rect(Surface, color, Rect)此方法用于繪制一個矩形
☆ pygame.draw.rect(Surface, color, Rect, width)此方法用于繪制一個矩形框
☆ pygame.draw.ellipse(Surface, color, Rect)此方法用于繪制一個橢圓
☆ pygame.draw.ellipse(Surface, color, Rect, width)此方法用于繪制一個橢圓框
☆ pygame.draw.polygon(Surface, color, pointlist, width)此方法用于繪制一個多邊形
☆ pygame.draw.arc(Surface, color, Rect, start_angle, stop_angle, width)此方法用于繪制一條弧線
☆ pygame.draw.circle(Surface, color, Rect, radius)此方法用于繪制一個圓
示例代碼
# 導入需要的模塊
import pygame, sys
from pygame.locals import *
from math import pi
# 初始化pygame
pygame.init()
# 設(shè)置窗口的大小,單位為像素
screen = pygame.display.set_mode((400,300))
# 設(shè)置窗口標題
pygame.display.set_caption('Drawing')
# 定義顏色
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
# 設(shè)置背景顏色
screen.fill(WHITE)
# 繪制一條線
pygame.draw.line(screen, GREEN, [10, 10], [50,30], 5)
# 繪制一條抗鋸齒的線
pygame.draw.aaline(screen, GREEN, [10, 50],[50, 80],True)
# 繪制一條折線
pygame.draw.lines(screen, BLACK, False,[[10, 80], [50, 90], [200, 80], [220, 30]], 5)
# 繪制一個空心矩形
pygame.draw.rect(screen, BLACK, [75, 10, 50, 20], 2)
# 繪制一個矩形
pygame.draw.rect(screen, BLACK, [150, 10, 50, 20])
# 繪制一個空心橢圓
pygame.draw.ellipse(screen, RED, [225, 10, 50, 20], 2)
# 繪制一個橢圓
pygame.draw.ellipse(screen, RED, [300, 10, 50, 20])
# 繪制多邊形
pygame.draw.polygon(screen, BLACK, [[100, 100], [0, 200], [200, 200]], 5)
# 繪制多條弧線
pygame.draw.arc(screen, BLACK,[210, 75, 150, 125], 0, pi/2, 2)
pygame.draw.arc(screen, GREEN,[210, 75, 150, 125], pi/2, pi, 2)
pygame.draw.arc(screen, BLUE, [210, 75, 150, 125], pi,3*pi/2, 2)
pygame.draw.arc(screen, RED, [210, 75, 150, 125], 3*pi/2, 2*pi, 2)
# 繪制一個圓
pygame.draw.circle(screen, BLUE, [60, 250], 40)
# 程序主循環(huán)
while True:
# 獲取事件
for event in pygame.event.get():
# 判斷事件是否為退出事件
if event.type == QUIT:
# 退出pygame
pygame.quit()
# 退出系統(tǒng)
sys.exit()
# 繪制屏幕內(nèi)容
pygame.display.update()
運行之,顯示如下:

Pygame繪制文字
Pygame不僅可以在屏幕上繪制形狀,還可以將文本繪制到屏幕上。Pygame 提供了一些非常簡單易用的函數(shù),可以創(chuàng)建字體和文本。字體(font)是字體類型的一種描述,表示按照統(tǒng)一風格繪制的一整套的字母、數(shù)字、符號和字符,例如 宋體 和 Times New Roman 都是字體。
☆font.SysFont()函數(shù)來創(chuàng)建一個 Font 對象,這個函數(shù)有兩個參數(shù),第 1 個參數(shù)是字體名稱,第 2 個參數(shù)是字體大小(以像素點為單位)
☆font.render()函數(shù)的參數(shù):第 1 個參數(shù)是要繪制的文本的字符串;第 2 個參數(shù)指定是否想要抗鋸齒的一個 Boolean 值,如果是 True,文本看上去更加平滑一些;第 3 個參數(shù)是用來渲染文本的顏色,這個例子中使用的是白色。
☆blit() 函數(shù),將像素從一個 Surface 復制到另一個 Surface 之上。常用兩個參數(shù):第一個參數(shù)是某矩形圖像(Surface實例),第二個參數(shù)用于指定繪制的位置。
示例代碼
import pygame
import sys
from pygame.locals import *
pygame.init()
wS=pygame.display.set_mode((400,300)) #創(chuàng)建畫布名稱wS
WHITE=(255,255,255)
myString="Hello World!"
font = pygame.font.SysFont("Times New Roman", 48) #來創(chuàng)建 Font對象
text = font.render(myString, True, WHITE)
wS.blit(text, (100,150)) #將text復制到指定位置(100,150)
# 程序主循環(huán)
while True:
# 獲取事件
for event in pygame.event.get():
# 判斷事件是否為退出事件
if event.type == QUIT:
# 退出pygame
pygame.quit()
# 退出系統(tǒng)
sys.exit()
# 繪制屏幕內(nèi)容
pygame.display.update()
運行之,顯示如下:

Pygame實現(xiàn)動畫
Pygame實現(xiàn)動畫
由于人類眼睛的特殊生理結(jié)構(gòu),當所看畫面的幀率高于24的時候,就會認為是連貫的。
幀率(Frame rate)是用于測量顯示幀數(shù)的量度,所謂的測量單位為每秒顯示幀數(shù)(Frames per Second,簡稱:FPS)。
在原有坐標系的基礎(chǔ)上添加偏移量,再重新繪制,依次一張一張的循環(huán)繪制下去,就會得到我們想要的物體移動的效果。
Pygame實現(xiàn)動畫主要用到的方法:
☆ pygame.image.load(filename) 加載一張圖片
☆pygame.Surface.blit(source, dest, area=None, special_flags = 0) 將圖片繪制到屏幕相應(yīng)坐標上(后面兩個參數(shù)默認,可以不傳)
☆pygame.time.Clock() 獲得pygame的時鐘
☆pygame.time.Clock.tick(FPS) 設(shè)置pygame時鐘的間隔時間
示例代碼如下:
# 導入需要的模塊
import pygame, sys
from pygame.locals import *
# 初始化pygame
pygame.init()
# 設(shè)置幀率(屏幕每秒刷新的次數(shù))
FPS = 30
# 獲得pygame的時鐘
fpsClock = pygame.time.Clock()
# 設(shè)置窗口大小
screen = pygame.display.set_mode((500, 400), 0, 32)
# 設(shè)置標題
pygame.display.set_caption('Animation')
# 定義顏色
WHITE = (255, 255, 255)
# 加載一張圖片
img = pygame.image.load('./images/bird.png')
# 初始化圖片的位置
imgx = 10
imgy = 10
# 初始化圖片的移動方向
direction = 'right'
# 程序主循環(huán)
while True:
# 每次都要重新繪制背景白色
screen.fill(WHITE)
# 判斷移動的方向,并對相應(yīng)的坐標做加減
if direction == 'right':
imgx += 5
if imgx == 380:
direction = 'down'
elif direction == 'down':
imgy += 5
if imgy == 300:
direction = 'left'
elif direction == 'left':
imgx -= 5
if imgx == 10:
direction = 'up'
elif direction == 'up':
imgy -= 5
if imgy == 10:
direction = 'right'
# 該方法將用于圖片繪制到相應(yīng)的坐標中
screen.blit(img, (imgx, imgy))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# 刷新屏幕
pygame.display.update()
# 設(shè)置pygame時鐘的間隔時間
fpsClock.tick(FPS)Pygame事件簡介
pygame事件可以處理游戲中的各種事情,事件是一個概念,比如點擊鼠標左鍵,按下一個鍵盤的按鍵,關(guān)閉窗口等等都是一個事件,pygame提供了一個函數(shù)來獲取游戲的事件,并把他們存放在一個隊列中,程序通過讀取整個事件隊列,來獲取當前發(fā)生的時間,并作出響應(yīng)。
Pygame常用的事件如下表:
事件 | 產(chǎn)生途徑 | 參數(shù) |
QUIT | 用戶按下關(guān)閉按鈕 | none |
ACTIVEEVENT | Pygame被激活或者隱藏 | gain, state |
KEYDOWN | 鍵盤被按下 | unicode, key, mod |
KEYUP | 鍵盤被放開 | key, mod |
MOUSEMOTION | 鼠標移動 | pos, rel, buttons |
MOUSEBUTTONDOWN | 鼠標按下 | pos, button |
MOUSEBUTTONUP | 鼠標放開 | pos, button |
VIDEORESIZE | Pygame窗口縮放 | size, w, h |
示例代碼:
# 導入需要的模塊
import pygame, sys
from pygame.locals import *
# 定義顏色
WHITE = (255, 255, 255)
# 初始化pygame
pygame.init()
# 設(shè)置窗口的大小,單位為像素
screen = pygame.display.set_mode((500,400), 0, 32)
# 設(shè)置窗口的標題
pygame.display.set_caption('Event')
# 設(shè)置背景
screen.fill(WHITE)
# 程序主循環(huán)
while True:
# 獲取事件
for event in pygame.event.get():
# 判斷事件是否為退出事件
if event.type == QUIT:
# 退出pygame
pygame.quit()
# 退出系統(tǒng)
sys.exit()
# 獲得鼠標按下的位置
if event.type ==MOUSEBUTTONDOWN:
print("鼠標按下:",event.pos)
# 獲得鼠標抬起的位置
if event.type ==MOUSEBUTTONUP:
print("鼠標抬起:",event.pos)
# 獲得鍵盤方向鍵按下的事件
if event.type == KEYDOWN:
if(event.key==K_UP or event.key==K_w):
print("上")
if(event.key==K_DOWN or event.key==K_s):
print("下")
if(event.key==K_LEFT or event.key==K_a):
print("左")
if(event.key==K_RIGHT or event.key==K_d):
print("右")
# 按下鍵盤的Esc鍵退出
if(event.key==K_ESCAPE):
# 退出pygame
pygame.quit()
# 退出系統(tǒng)
sys.exit()
# 繪制屏幕內(nèi)容
pygame.display.update()
效果圖如下:

綜合例子
下面給出綜合例子
1、畫一個小房子,房前有樹,樹頂上有太陽
先給出效果圖:

源碼如下:
import pygame
import sys
# 初始化pygame
pygame.init()
# 設(shè)置窗口尺寸
width, height = 861, 594
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('畫圖')
# 定義顏色
WHITE = (255, 255, 255)
ORANGE = (255, 165, 0)
BROWN = (165, 42, 42)
GREEN = (0, 128, 0)
RED = (255, 0, 0)
GRAY = (128, 128, 128)
# 繪制背景
screen.fill(WHITE)
# 畫房子
pygame.draw.polygon(screen, GRAY, [(150, 300), (350, 300), (250, 200)]) # 房子的屋頂
pygame.draw.polygon(screen, ORANGE, [(150, 400), (350, 400), (350, 300), (150, 300)]) # 房子的底部
# 畫房子的門和窗戶
pygame.draw.rect(screen, WHITE, (180, 350, 30, 30)) # 窗戶1
pygame.draw.rect(screen, WHITE, (230, 350, 40, 50)) # 門
pygame.draw.rect(screen, WHITE, (290, 350, 30, 30)) # 窗戶2
# 畫樹1
pygame.draw.rect(screen, BROWN, (400, 300, 20, 100)) # 樹干
pygame.draw.circle(screen, GREEN, (410, 250), 50) # 樹冠
# 畫樹2
pygame.draw.rect(screen, BROWN, (560, 300, 40, 150)) # 繪制樹干
# 繪制樹冠
pygame.draw.circle(screen, GREEN, (550, 250), 50)
pygame.draw.circle(screen, GREEN, (620, 250), 50)
pygame.draw.circle(screen, GREEN, (590, 220), 50)
pygame.draw.circle(screen, GREEN, (560, 280), 50)
pygame.draw.circle(screen, GREEN, (610, 280), 50)
# 畫太陽
pygame.draw.circle(screen, RED, (650, 50), 25) # 太陽
# 刷新屏幕
pygame.display.flip()
# 保持窗口打開
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()2、用方向鍵控制小貓移動示例
需要兩個素材文件:小貓圖片 cat.png 和背景圖片bg1.jpg,為簡便將它們 和源碼程序文件,放在同一文件夾中。

源碼如下:
import sys
import pygame
from pygame.locals import *
def control_ball(event):
speed = [x,y] =[0,0]# 設(shè)置相對位移
speed_offset = 1 #小球的速度
# 如果事件的類型是 鍵盤輸入,就根據(jù)方向鍵來求出速度的方向(默認是從左往右為1,從上往下為1)
if event.type == KEYDOWN:
if event.key == pygame.K_LEFT:
speed[0] -= speed_offset
event.key
if event.key == pygame.K_RIGHT:
speed[0] = speed_offset
event.key
if event.key == pygame.K_UP:
speed[1] -= speed_offset
event.key
if event.key == pygame.K_DOWN:
speed[1] = speed_offset
event.key
#如果沒有方向鍵的輸入,則速度為0,小球不動
if event.type in (pygame.K_UP, pygame.K_LEFT, pygame.K_RIGHT, pygame.K_DOWN):
speed = [0,0]
return speed
#定義函數(shù)
def play_ball():
pygame.init()#初始化
window_size = Rect(0,0,600,440)#設(shè)置窗口的大小
screen = pygame.display.set_mode(window_size.size)#設(shè)置窗口模式
pygame.display.set_caption('hello cat')#設(shè)置窗口標題
ball_image = pygame.image.load('cat.png')#載入小球圖片
back_image = pygame.image.load('bg1.jpg')#載入背景圖片
ball_rect = ball_image.get_rect()# 獲取小球圖片所在的區(qū)域
while True:
#退出事件的處理
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
control_speed = control_ball(event)#獲取到小球的方向
ball_rect = ball_rect.move(control_speed).clamp(window_size)#小球按照方向移動,并且不會移出窗口。
screen.blit(back_image,(0,0))#設(shè)置窗口背景,位于(0,0)處,窗口左上角。
screen.blit(ball_image, ball_rect)#把小球繪制到背景surface上。
pygame.display.flip()#更新窗口內(nèi)容
#調(diào)用函數(shù)
play_ball()
3、拼圖游戲
兩種實現(xiàn):點擊交換式和拖動交換式
★拼圖游戲之點擊交換式
加載一張圖片分塊打亂,用戶用鼠標單擊兩塊圖片則兩塊圖片交換位置,拼圖完成后提示成功。確保圖像文件存在并與代碼中指定的路徑相匹配——我這里圖片名是player.png,和源碼文件放在同一文件夾中。

源碼如下:
import random
from sys import exit # 使用sys模塊的exit函數(shù)來退出游戲
import pygame
from pygame.locals import * # 導入一些常用的函數(shù)和常量
from tkinter import messagebox #導入messagebox模塊
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
ROW = 0
COL = 0
CELL_WIDTH = 0 #SCREEN_WIDTH / COL
CELL_HEIGHT = 0 #SCREEN_HEIGHT / ROW
firstClickCell = None
# 標記是否游戲成功
successFlag = False
gamePictures='player.png' ##游戲圖片##
pygame.init() # 初始化pygame
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 創(chuàng)建了一個窗口 大小是(寬,高)
pygame.display.set_caption('單擊交換式拼圖') # 設(shè)置窗口標題
scaled_image =pygame.transform.scale(pygame.image.load(gamePictures), (SCREEN_WIDTH//6, SCREEN_HEIGHT//6)) #加載原始圖片縮小
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
myfont = pygame.font.SysFont('KaiTi', 60) #None系統(tǒng)默認字體,楷體:KaiTi
textImage1 = myfont.render("難度級別 1", True , GREEN)
textImage2 = myfont.render("難度級別 2", True , BLUE)
textImage3 = myfont.render("難度級別 3", True , RED)
myfont = pygame.font.SysFont('SimHei', 20) #黑體:SimHei
textImage4 = myfont.render("選取上面難度等級進入游戲;用戶用鼠標單擊", True , WHITE)
textImage5 = myfont.render("兩個已打亂順序的小圖塊則這兩塊交換位置。", True , WHITE)
screen.fill((0,0,0))
screen.blit(scaled_image, (0, 0))
screen.blit(textImage1, (150, 100))
screen.blit(textImage2, (150, 250))
screen.blit(textImage3, (150, 400))
screen.blit(textImage4, (100, 500))
screen.blit(textImage5, (100, 530))
pygame.display.update()
class PartPicture:
# 初始化一個圖片分塊,保存圖像和圖像的位置, id代表原圖第幾塊的位置
def __init__(self, img, x, y, id):
self.img = img
self.x = x
self.y = y
self.id = id
# 判斷是否在圖片內(nèi)
def isOver(self):
w, h = self.img.get_size()
point_x, point_y = pygame.mouse.get_pos() # 返回鼠標當前坐標
in_x = self.x < point_x < self.x + w
in_y = self.y < point_y < self.y + h
return in_x and in_y
# 檢測移動
def isPressed(self, pictureList):
# print('is_pressed')
if self.isOver():
b1, b2, b3 = pygame.mouse.get_pressed()
if b1 == 1:
global firstClickCell
global successFlag
if firstClickCell is None:
firstClickCell = self
print('id為{}的塊被點擊'.format(firstClickCell.getId()))
else:
print('交換{}與{}的坐標'.format(firstClickCell.getId(), self.getId()))
self.pictureSwitch(firstClickCell, self)
if self.isFinish(pictureList):
successFlag = True
print('成功!')
else:
successFlag = False
firstClickCell = None
return True
return False
# 判斷拼圖完成
def isFinish(self, pictureList):
for cell in pictureList:
nowp_x, nowp_y = cell.getXY()
p_x = cell.getId() % COL * CELL_WIDTH
p_y = (cell.getId() // COL) * CELL_HEIGHT
print("id{} nowx{}與nowy{}的坐標 本來的坐標x{}y{}".format(cell.getId(), nowp_x, nowp_y, p_x, p_y))
if nowp_x != p_x or nowp_y != p_y:
return False
return True
def pictureSwitch(self, cell1, cell2):
tempX = cell1.getX()
tempY = cell1.getY()
cell1.setXY(cell2.getX(), cell2.getY())
cell2.setXY(tempX, tempY)
def render(self, screen):
screen.blit(self.img, (self.x, self.y))
# get和set方法
def getX(self):
return self.x;
def getY(self):
return self.y
# 獲取圖片坐標
def getXY(self):
return self.x, self.y
# 修改圖片坐標
def setXY(self,x, y):
self.x = x
self.y = y
# 獲取id
def getId(self):
return self.id
# 圖片分塊
def devide(imgSrc):
# 切割原來的圖片
pictures = []
ScPictures = []
id = 0 # 給每個分塊的圖片設(shè)置下標
for i in range(ROW):
for j in range(COL):
# 提取部分圖片
partOfPicutre = imgSrc.subsurface(j * CELL_WIDTH, i * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT)
# 保存第一組圖片
tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
pictures.append(tempPicture)
# 保存第二組圖片
tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
ScPictures.append(tempPicture)
id += 1
random.shuffle(pictures)
# 開始利用第二組圖片來打亂原來的圖片
for i in range(len(pictures)):
pictures[i].setXY(ScPictures[i].getX(), ScPictures[i].getY())
return pictures # 把打亂的圖片返回
setInit = False
while True:
if setInit:
break
for event in pygame.event.get():
if event.type == QUIT:
exit() # 接收到退出事件后退出程序
elif event.type == MOUSEBUTTONDOWN:
b1, b2, b3 = pygame.mouse.get_pressed()
if b1 == 1:
point_x, point_y = pygame.mouse.get_pos() # 返回鼠標當前坐標
if 100 < point_y < 200:
ROW = 3
COL = 3
setInit = True
elif 250 < point_y < 350:
ROW = 4
COL = 4
setInit = True
elif 350 < point_y < 450:
ROW = 5
COL = 5
setInit = True
CELL_WIDTH = SCREEN_WIDTH / COL
CELL_HEIGHT = SCREEN_HEIGHT / ROW
# 原圖 提高 blit 的速度 convert_alpha相對于convert,保留了圖像的Alpha 通道信息,可以認為是保留了透明的部分,實現(xiàn)了透明轉(zhuǎn)換
imgSrc = pygame.image.load(gamePictures).convert() ##加載游戲圖片
PictureList = devide(imgSrc) #圖片分塊
while True: # 游戲主循環(huán)
for event in pygame.event.get():
if event.type == QUIT:
exit() # 接收到退出事件后退出程序
elif event.type == MOUSEBUTTONDOWN:
for cell in PictureList:
# 檢測按鍵按下,并且交換圖片位置
if cell.isPressed(PictureList):
break
for partPicture in PictureList:
partPicture.render(screen)
if not successFlag:
# # Sta 繪制分割線
for i in range(1, COL):
pygame.draw.lines(screen, GREEN, 0, [(i * SCREEN_WIDTH // COL, 0), (i * SCREEN_WIDTH // COL, SCREEN_HEIGHT)], 1)
for i in range(1, ROW):
pygame.draw.lines(screen, GREEN, 0, [(0, i * SCREEN_HEIGHT // ROW), (SCREEN_WIDTH, i * SCREEN_HEIGHT // ROW)], 1)
# End 繪制分割線
pygame.display.update() # 刷新一下畫面
if successFlag:
messagebox.showinfo("祝賀你!", "成功完成!")
break效果示意圖如下:

★拼圖游戲之拖動交換式
下面給出拼圖游戲的另一種實現(xiàn)
功能:窗體上有兩個按鈕,單擊"open"按鈕加載的游戲圖片,單擊"start"按鈕將加載的游戲圖片分割成9小塊打亂排列。游戲規(guī)則:將一個小塊拖動到另一小塊時,兩小塊圖片將交換位置,當恢復原樣時,提示"success!"。
源碼如下:
import pygame
import random
import sys
import tkinter as tk
from tkinter import filedialog
# 初始化Tkinter
root = tk.Tk()
root.withdraw()
# 初始化游戲
pygame.init()
# 設(shè)置游戲窗口尺寸
WIDTH = 600
HEIGHT = 600
window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("拼圖游戲:拖動交換小塊圖")
# 設(shè)置顏色
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
# 設(shè)置字體
font = pygame.font.Font(None, 36)
# 設(shè)置拼圖塊的尺寸和間隙
BLOCK_SIZE = 200
BLOCK_MARGIN = 5
# 設(shè)置拼圖塊的初始位置
block_positions = [(j * (BLOCK_SIZE + BLOCK_MARGIN), i * (BLOCK_SIZE + BLOCK_MARGIN))
for i in range(3) for j in range(3)]
# 拼圖塊的當前位置
current_positions = block_positions.copy()
# 游戲狀態(tài)
game_started = False
puzzle_completed = False
# 選中的拼圖塊
selected_block = None
selected_block_index = None
# 加載游戲圖片
original_image = None
block_images = []
def load_image():
global original_image, block_images
# 選擇并加載計算機中的圖片
file_path = filedialog.askopenfilename()
if file_path:
try:
original_image = pygame.image.load(file_path)
original_image = pygame.transform.scale(original_image, (BLOCK_SIZE * 3, BLOCK_SIZE * 3))
# 分割原始圖片為拼圖塊
block_images = []
for i in range(3):
for j in range(3):
block_images.append(original_image.subsurface(pygame.Rect(j * BLOCK_SIZE, i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)))
# 重置游戲狀態(tài)
global game_started, puzzle_completed
game_started = False
puzzle_completed = False
except pygame.error:
print("加載圖片失?。?)
sys.exit(1)
# 檢查拼圖是否完成
def check_puzzle_completed():
global puzzle_completed
puzzle_completed = all(current_positions[i] == block_positions[i] for i in range(len(current_positions)))
# "start"按鈕的點擊事件處理
def start_game():
global game_started, puzzle_completed, current_positions
if original_image is not None:
current_positions = block_positions.copy()
random.shuffle(current_positions)
game_started = True
puzzle_completed = False
# 交換拼圖塊位置
def swap_pieces(pos1, pos2):
current_positions[pos1], current_positions[pos2] = current_positions[pos2], current_positions[pos1]
# 獲取拼圖塊索引
def get_block_index(position):
for i, pos in enumerate(current_positions):
if pos == position:
return i
return None
# 游戲主循環(huán)
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if 50 <= event.pos[0] <= 180 and 50 <= event.pos[1] <= 80:
load_image() # 當鼠標在"open"按鈕區(qū)域內(nèi)按下時,調(diào)用load_image()函數(shù)加載圖片
elif game_started and not puzzle_completed:
for i, position in enumerate(current_positions):
block_rect = pygame.Rect((position[0], position[1]), (BLOCK_SIZE, BLOCK_SIZE))
if block_rect.collidepoint(event.pos):
selected_block = position # 記錄選中的拼圖塊的位置
selected_block_index = i # 記錄選中的拼圖塊的索引
break
elif 200 <= event.pos[0] <= 330 and 50 <= event.pos[1] <= 80:
start_game() # 當鼠標在"start"按鈕區(qū)域內(nèi)按下時,調(diào)用start_game()函數(shù)開始游戲
elif event.type == pygame.MOUSEBUTTONUP:
if game_started and not puzzle_completed and selected_block is not None:
for i, position in enumerate(current_positions):
block_rect = pygame.Rect((position[0], position[1]), (BLOCK_SIZE, BLOCK_SIZE))
if block_rect.collidepoint(event.pos) and selected_block != position:
swap_pieces(selected_block_index, i) # 交換選中的拼圖塊與鼠標釋放位置上的拼圖塊的位置
break
selected_block = None
selected_block_index = None
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
if original_image is not None:
random.shuffle(current_positions) # 按下"r"鍵后,隨機洗牌拼圖塊的位置
game_started = True
puzzle_completed = False
elif event.key == pygame.K_q:
running = False # 按下"q"鍵后,退出游戲循環(huán)
window.fill(WHITE) # 填充窗口背景顏色為白色
if original_image is not None:
for i in range(len(current_positions)):
position = current_positions[i]
pygame.draw.rect(window, BLUE, (position[0], position[1], BLOCK_SIZE, BLOCK_SIZE)) # 繪制拼圖塊的矩形邊框
window.blit(block_images[i], position) # 在拼圖塊的位置上繪制對應(yīng)的圖像
pygame.draw.rect(window, BLUE, (50, 50, 130, 30)) # 繪制"open"按鈕的矩形邊框
open_text = font.render("open", True, WHITE) # 創(chuàng)建渲染的"open"文本圖像
window.blit(open_text, (90, 55)) # 在窗口上繪制"open"文本圖像
pygame.draw.rect(window, BLUE, (200, 50, 130, 30)) # 繪制"start"按鈕的矩形邊框
start_text = font.render("start", True, WHITE) # 創(chuàng)建渲染的"start"文本圖像
window.blit(start_text, (235, 55)) # 在窗口上繪制"start"文本圖像
check_puzzle_completed() # 檢查拼圖是否完成
if puzzle_completed:
success_text = font.render("success!", True, WHITE) # 創(chuàng)建渲染的"success!"文本圖像
success_text_rect = success_text.get_rect(center=(WIDTH // 2, HEIGHT // 2)) # 計算"success!"文本圖像的中心位置
window.blit(success_text, success_text_rect) # 在窗口上繪制"success!"文本圖像
pygame.display.flip() # 更新窗口顯示
clock.tick(60) # 控制游戲循環(huán)的幀率為60幀每秒
pygame.quit()在此就不給出效果示意圖了,你可以試試。
總結(jié)
以上就是Python中pygame游戲模塊的用法詳解的詳細內(nèi)容,更多關(guān)于Python pygame游戲模塊的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實現(xiàn)畫箱線圖展示數(shù)據(jù)分布情況
這篇文章主要介紹了Python實現(xiàn)畫箱線圖展示數(shù)據(jù)分布情況,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
Python任務(wù)調(diào)度利器之APScheduler詳解
所謂的任務(wù)調(diào)度是指安排任務(wù)的執(zhí)行計劃,即何時執(zhí)行,怎么執(zhí)行等。這篇文章主要介紹了Python任務(wù)調(diào)度利器之APScheduler詳解,需要的朋友可以參考下2020-04-04
Python實現(xiàn)矩陣相乘的三種方法小結(jié)
今天小編就為大家分享一篇Python實現(xiàn)矩陣相乘的三種方法小結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07
python中websockets與主線程傳遞參數(shù)的實現(xiàn)
本文主要介紹了python中websockets與主線程傳遞參數(shù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-02-02
如何將matlab數(shù)據(jù)導入到Python中使用
這篇文章主要介紹了如何將matlab數(shù)據(jù)導入到Python中使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12

