大家好,本文將圍繞python制作小游戲50行代碼小鳥(niǎo)管道展開(kāi)說(shuō)明,python制作小游戲都用什么軟件是一個(gè)很多人都想弄明白的事情,想搞清楚python制作小游戲400行代碼需要先了解以下幾個(gè)事情。
Python非常受歡迎的一個(gè)原因是它的應(yīng)用領(lǐng)域非常廣泛,其中就包括游戲開(kāi)發(fā)。而是用Python進(jìn)行游戲開(kāi)發(fā)的首選模塊就是PyGame如何用python畫(huà)不同大小的滿(mǎn)天星。
1. 初識(shí)Pygame
- PyGame是跨平臺(tái)Python模塊,專(zhuān)為電子游戲設(shè)計(jì),包含圖像、聲音等,創(chuàng)建在SDL(Simple DirectMedia Layer)基礎(chǔ)上,允許實(shí)時(shí)電子游戲研發(fā)而不會(huì)被低級(jí)語(yǔ)言,如C語(yǔ)言或是更低級(jí)的匯編語(yǔ)言束縛?;谶@樣一個(gè)設(shè)想,所有需要的游戲功能和理念(主要是圖像方面)都完全簡(jiǎn)化為游戲邏輯本身,所有的資源結(jié)構(gòu)都可以由高級(jí)語(yǔ)言(如Python)提供。
1. 安裝Pygame
- PyGame的官方網(wǎng)址是www.pygame.org。在該網(wǎng)址中可以查看PyGame的相關(guān)文檔。PyGame的安裝命令很簡(jiǎn)單:
pip install pygame
- 檢查模塊是否安裝成功:
import pygame
pygame.ver
- 運(yùn)行結(jié)果如下:
2. Pygame常用模塊
- Pygame做游戲開(kāi)發(fā)的優(yōu)勢(shì)在于不需要過(guò)多地考慮底層相關(guān)的內(nèi)容,可以把工作中心放在游戲邏輯上。例如,PyGame中集成了很多和底層相關(guān)的模塊,如訪(fǎng)問(wèn)顯示設(shè)備、管理事件、使用字體等。
- Pygame常用模塊如下:
模塊名 | 功能 |
---|---|
pygame.cdrom | 訪(fǎng)問(wèn)光驅(qū)。 |
pygame.cursors | 加載光標(biāo)。 |
pygame.display | 訪(fǎng)問(wèn)顯示設(shè)備。 |
pygame.draw | 繪制形狀、線(xiàn)和點(diǎn)。 |
pygame.event | 管理事件。 |
pygame.font | 使用字體。 |
pygame.image | 加載和存儲(chǔ)圖片。 |
pygame.joystick | 使用游戲手柄或類(lèi)似的東西。 |
pygame.key | 讀取鍵盤(pán)按鍵。 |
pygame.mixer | 聲音。 |
pygame.mouse | 鼠標(biāo)。 |
pygame.movie | 播放視頻。 |
pygame.music | 播放音樂(lè)。 |
pygame.overlay | 訪(fǎng)問(wèn)高級(jí)視頻疊加。 |
pygame.rect | 管理矩形區(qū)域。 |
pygame.sndarray | 操作聲音數(shù)據(jù)。 |
pygame.sprite | 操作移動(dòng)圖像。 |
pygame.surface | 管理圖像和屏幕。 |
pygame.surfarray | 管理點(diǎn)陣圖像數(shù)據(jù)。 |
pygame.time | 管理時(shí)間和幀信息。 |
pygame.transform | 縮放和移動(dòng)圖像。 |
- 使用Pygame的display模塊和event模塊創(chuàng)建一個(gè)PyGame窗口,代碼如下:
# -*- coding: utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 320, 240 # 設(shè)置窗口尺寸
screen = pygame.display.set_mode(size) # 顯示窗口
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get(): # 遍歷所有事件
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
pygame.quit() # 退出pygame
- 運(yùn)行結(jié)果如下:
2. 制作一個(gè)跳躍的小球游戲(Pygame基本使用)
- 創(chuàng)建一個(gè)游戲窗口,然后在窗口內(nèi)創(chuàng)建一個(gè)小球。以一定速度移動(dòng)小球,當(dāng)小球碰到游戲窗口的邊緣時(shí),小球彈回,繼續(xù)移動(dòng)。
(1)創(chuàng)建一個(gè)游戲窗口,寬高設(shè)置640*480:
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width,height=640,480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
- 上述代碼中,首先導(dǎo)入pygame模塊,然后調(diào)用init()方法初始化pygame模塊。接下來(lái)設(shè)置窗口的寬和高,最后使用display模塊顯示窗體。
- display模塊的常用方法:
方法名 | 功能 |
---|---|
pygame.display.init | 初始化display模塊。 |
pygame.display.quit | 結(jié)束display模塊。 |
pygame.display.get_init | 如果display模塊已經(jīng)被初始化,則返回True。 |
pygame.display.set_mode | 初始化一個(gè)準(zhǔn)備顯示的界面。 |
pygame.display.get_surface | 獲取當(dāng)前的Surface對(duì)象。 |
pygame.display.flip | 更新整個(gè)待顯示的Surface對(duì)象到屏幕上。 |
pygame.display.update | 更新部分內(nèi)容顯示到屏幕上,如果沒(méi)有參數(shù)則與flip功能相同。 |
(2)運(yùn)行上述代碼,會(huì)出現(xiàn)一個(gè)一閃而過(guò)的黑色窗口,這是因?yàn)槌绦驁?zhí)行完成后會(huì)自動(dòng)關(guān)閉。如果讓窗口一直顯示,需要使用while True讓程序一直執(zhí)行,此外,還需要設(shè)置關(guān)閉按鈕。代碼具體如下: |
# -*-coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
pygame.quit() # 退出pygame
- 上述代碼中,添加了輪詢(xún)事件檢測(cè)。pygame.event.get()能夠獲取事件隊(duì)列,使用for…in遍歷事件,然后根據(jù)type屬性判斷事件類(lèi)型。這里的事件處理方式與GUI類(lèi)似,如event.type等于pygame.GUIT表示檢測(cè)到關(guān)閉pygame窗口事件,pygame.KEYDOWN表示鍵盤(pán)按下事件,pygame.MOUSEBUTTONDOWN表示鼠標(biāo)按下事件等。
(3)在窗口中添加小球。我們先準(zhǔn)備好一張ball.png圖片,然后加載該圖片,最后將圖片顯示在窗口中:
# #######################1. 窗口一閃而過(guò)
# import sys # 導(dǎo)入sys模塊
# import pygame # 導(dǎo)入pygame模塊
#
# pygame.init() # 初始化pygame
# size = width,height=640,480 # 設(shè)置窗口
# screen = pygame.display.set_mode(size) # 顯示窗口
# ##############################2. 窗口持續(xù)
# # -*-coding:utf-8 -*-
# import sys # 導(dǎo)入sys模塊
# import pygame # 導(dǎo)入pygame模塊
#
# pygame.init() # 初始化pygame
# size = width, height = 640, 480 # 設(shè)置窗口
# screen = pygame.display.set_mode(size) # 顯示窗口
#
# # 執(zhí)行死循環(huán),確保窗口一直顯示
# while True:
# # 檢查事件
# for event in pygame.event.get():
# if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
# sys.exit()
# pygame.quit() # 退出pygame
# ######################3. 添加ball的窗口
# -*-coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果點(diǎn)擊關(guān)閉窗口,則退出
sys.exit()
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 上述代碼使用image模塊的load()方法加載圖片,返回值ball是一個(gè)Surface對(duì)象。Surface是用來(lái)代表圖片的pygame對(duì)象,可以對(duì)一個(gè)Surface對(duì)象進(jìn)行涂畫(huà)、變形、復(fù)制等各種操作。事實(shí)上,屏幕也只是一個(gè)surface,pygame.display.set_mode就返回一個(gè)屏幕Surface對(duì)象。如果將ball這個(gè)Surface對(duì)象畫(huà)到screen.Surface對(duì)象,需要使用blit()方法,最后使用display模塊的flip方法更新整個(gè)待顯示的Surface對(duì)象到屏幕上。
- 運(yùn)行結(jié)果如下:
- Surface對(duì)象的常用方法如下:
方法名 | 功能 |
---|---|
pygame.Surface.blit | 將一個(gè)圖像畫(huà)到另一個(gè)圖像上。 |
pygame.Surface.convert | 轉(zhuǎn)換圖像的像素格式。 |
pygame.Surface.convert_alpha | 轉(zhuǎn)換圖像的像素格式,包含alpha通道的轉(zhuǎn)換。 |
pygame.Surface.fill | 使用顏色填充Surface |
pygame.Surface.get_rect | 獲取Surface的矩形區(qū)域。 |
(4)下面該讓小球動(dòng)起來(lái)了。ball.get_rect()方法返回值ballrect()方法返回值ballrect是一個(gè)Rect對(duì)象,該對(duì)象有一個(gè)move()方法可用于移動(dòng)矩形。move(x,y)函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)是X軸移動(dòng)的距離,第二個(gè)參數(shù)是Y軸移動(dòng)的距離。窗體左上角坐標(biāo)為(0,0),例如move(100,50)。
- 為實(shí)現(xiàn)小球不停地移動(dòng),將move()函數(shù)添加到while循環(huán)內(nèi):
# -*- coding:utf-8-*-
import sys
import pygame
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
speed = [5, 5] # 設(shè)置移動(dòng)的X軸、Y軸距離
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
ballrect = ballrect.move(speed) # 移動(dòng)小球
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 運(yùn)行上述代碼,小球在屏幕中一閃而過(guò),此時(shí),小球并沒(méi)有真正消失,而是移動(dòng)到窗體外了,此時(shí)需要添加碰撞檢測(cè)的功能。當(dāng)小球與窗體的任一邊緣發(fā)生碰撞,則改變小球的移動(dòng)方向:
# -*- coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置窗口背景顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
speed = [1, 1] # 設(shè)置移動(dòng)的X軸、Y軸距離
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
ballrect = ballrect.move(speed) # 移動(dòng)小球
# 碰到左右邊緣
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
# 碰到上下邊緣
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 上述代碼中,添加了碰撞檢測(cè)功能。如果球碰到左右邊緣,則更改X軸數(shù)據(jù)為負(fù)數(shù);如果碰到上下邊緣,則改Y軸數(shù)據(jù)為負(fù)數(shù)。
- 運(yùn)行結(jié)果如下:
(6)運(yùn)行上述代碼發(fā)現(xiàn)好像有多個(gè)小球在飛快移動(dòng),這是因?yàn)檫\(yùn)行上述代碼的時(shí)間非常短,導(dǎo)致肉眼錯(cuò)覺(jué),因此需要添加一個(gè)“時(shí)鐘”來(lái)控制程序運(yùn)行時(shí)間。用pygame的time模塊控制。使用pygame時(shí)鐘前,必須先創(chuàng)建一個(gè)Clock對(duì)象的一個(gè)實(shí)例,然后在while循環(huán)中設(shè)置多長(zhǎng)時(shí)間運(yùn)行一次。代碼如下:
# -*- coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
speed = [5, 5] # 設(shè)置移動(dòng)的X軸、Y軸距離
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
ballrect = ballrect.move(speed) # 移動(dòng)小球
# 碰到左右邊緣
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
# 碰到上下邊緣
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 至此,就完成了跳躍的小球游戲。
- 運(yùn)行效果如下:
3. 開(kāi)發(fā)Flappy Bird游戲
- 游戲的素材可以從該網(wǎng)站上找自己喜歡的:https://www.aigei.com/s?tab=file&type=2d&q=flappy+bird&page=3#resContainer
- 也可以使用我下載的:
1. 游戲簡(jiǎn)介
- Flappy Bird是一款鳥(niǎo)類(lèi)飛行游戲,由越南河內(nèi)獨(dú)立游戲開(kāi)發(fā)者阮哈東(DongNguyen)開(kāi)發(fā)。在Flappy Bird這款游戲中,玩家只需要用一根手指來(lái)操控,單擊觸摸手機(jī)屏幕,小鳥(niǎo)就會(huì)往上飛,不斷地單擊就會(huì)不斷地往高處飛。放松手指,則會(huì)快速下降。所以玩家要控制小鳥(niǎo)一直向前飛行,然后注意躲避途中高低不平的管子。如果小鳥(niǎo)碰到了障礙物,游戲就會(huì)結(jié)束。每當(dāng)小鳥(niǎo)飛過(guò)一組管道,玩家就會(huì)獲得一分。
2. 游戲分析
- 在Flappy Bird中,主要有兩個(gè)對(duì)象:小鳥(niǎo)和管道??梢詣?chuàng)建Bird類(lèi)和Pineline類(lèi)來(lái)分別表示這兩個(gè)對(duì)象。小鳥(niǎo)可以通過(guò)上下移動(dòng)來(lái)躲避管道,所以在Bird類(lèi)中創(chuàng)建一個(gè)birdUpdate()方法,實(shí)現(xiàn)小鳥(niǎo)的上下移動(dòng)。為了體現(xiàn)小鳥(niǎo)向前飛行的特征,可以讓管道一直向左側(cè)移動(dòng),這樣在窗口中就好像小鳥(niǎo)在向前飛行。所以,在Pineline類(lèi)中也創(chuàng)建了一個(gè)updatePipline()方法,實(shí)現(xiàn)管道的向左移動(dòng)。此外,還創(chuàng)建了3個(gè)函數(shù):createMap()函數(shù)用于繪制地圖;checkDead()函數(shù)用于判斷小鳥(niǎo)的生命狀態(tài);getResult()函數(shù)用于獲取最終分?jǐn)?shù)。最后在主邏輯中實(shí)例化類(lèi)并調(diào)用相關(guān)方法,實(shí)現(xiàn)相應(yīng)功能。
3. 搭建主框架
- 通過(guò)前面分析,我們可以搭建起Flappy Bird游戲的主框架。Flappy Bird游戲有兩個(gè)對(duì)象:小鳥(niǎo)和管道。先來(lái)創(chuàng)建這兩個(gè)類(lèi),類(lèi)中的具體方法可以先使用pass語(yǔ)句替代。然后創(chuàng)建一個(gè)繪制地圖的函數(shù)createMap()。最后,在主邏輯中繪制背景圖片。關(guān)鍵代碼如下:
import pygame
import sys
import random
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
pass
def birdUpdate(self):
pass
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
pass
def updatePipeline(self):
"""水平移動(dòng)"""
pass
def createMap(screen, background):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
size = width, height = 400, 720 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background) # 繪制地圖
pygame.quit() # 退出
- 運(yùn)行結(jié)果如下:
4. 創(chuàng)建小鳥(niǎo)類(lèi)
- 下面創(chuàng)建小鳥(niǎo)類(lèi)。該類(lèi)需要初始化很多參數(shù),所以定義一個(gè)__init__()方法,用來(lái)初始化各種參數(shù),包括鳥(niǎo)飛行的幾種狀態(tài)、飛行的速度、跳躍的高度等。然后定義birdUpdate()方法,該方法用于實(shí)現(xiàn)小鳥(niǎo)的跳躍和墜落。接下來(lái),在主邏輯的輪詢(xún)事件中添加鍵盤(pán)按下事件或鼠標(biāo)單擊事件,如按下鼠標(biāo),使小鳥(niǎo)上升等。最后,在createMap()方法中顯示小鳥(niǎo)的圖像。
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
pass
def updatePipeline(self):
"""水平移動(dòng)"""
pass
def createMap(screen, background):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
size = width, height = 400, 720 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background) # 繪制地圖
pygame.quit() # 退出
- 上述代碼在Bird類(lèi)中設(shè)置了birdStatus屬性,該屬性是一個(gè)鳥(niǎo)類(lèi)圖片的列表,列表中顯示鳥(niǎo)類(lèi)的3種飛行狀態(tài),根據(jù)小鳥(niǎo)的不同狀態(tài)加載相應(yīng)的圖片。在birdUpdate()方法中,為了達(dá)到較好的動(dòng)畫(huà)效果,使用jumpSpeed和gravity兩個(gè)屬性逐漸變化。運(yùn)行上述代碼,在窗體內(nèi)創(chuàng)建一只鳥(niǎo),默認(rèn)情況下小鳥(niǎo)會(huì)一直下降。當(dāng)單擊一下鼠標(biāo)或按一下鍵盤(pán),小鳥(niǎo)會(huì)跳躍一下,高度上升。運(yùn)行效果如下圖:
5. 創(chuàng)建管道類(lèi)
- 創(chuàng)建完鳥(niǎo)類(lèi)之后,我們來(lái)創(chuàng)建管道類(lèi)。同樣,在_init_()方法中初始化各種參數(shù),包括設(shè)置管道的坐標(biāo),加載上下管道圖片等。然后在updatePipline()方法中,定義管道向左移動(dòng)的速度,并且當(dāng)管道移出屏幕時(shí)重新繪制下一組管道。最后,在createMap()函數(shù)中顯示管道。關(guān)鍵代碼如下:
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.wallx = 400 # 管道所在X軸坐標(biāo)
self.pineUp = pygame.image.load("assets/top.png") # 加載上管道圖片
self.pineDown = pygame.image.load("assets/bottom.png") # 加載下管道圖片
def updatePipeline(self):
"""管道水平移動(dòng)方法"""
self.wallx -= 5 # 管道X軸坐標(biāo)遞減,即管道向左移動(dòng)
# 當(dāng)管道運(yùn)行到一定位置,即小鳥(niǎo)飛越管道,分?jǐn)?shù)加1,并且管道重置
if self.wallx < -80:
self.wallx = 400
def createMap(screen, background):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示管道
screen.blit(Pipeline.pineUp, (Pipeline.wallx, -300)) # 上管道坐標(biāo)位置(X,Y)
screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500)) # 下管道坐標(biāo)位置(X,Y)
Pipeline.updatePipeline() # 管道移動(dòng)
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
size = width, height = 400, 720 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background) # 繪制地圖
pygame.quit() # 退出
- 上述代碼中,在createMap()函數(shù)中,設(shè)置先顯示管道,再顯示小鳥(niǎo)。這樣做的目的是,當(dāng)小鳥(niǎo)與管道圖像重合的時(shí)候,小鳥(niǎo)的圖像顯示在上層,而管道的圖像顯示在底層。運(yùn)行結(jié)果如下:
6. 計(jì)算得分
- 當(dāng)小鳥(niǎo)飛過(guò)管道時(shí),玩家得分加1.這里對(duì)于飛過(guò)管道的邏輯做了簡(jiǎn)化處理:當(dāng)管道移動(dòng)到窗體左側(cè)一定距離后,默認(rèn)小鳥(niǎo)飛過(guò)管道,使分?jǐn)?shù)加1,并顯示在屏幕上。在updatePipeline()方法中實(shí)現(xiàn)該功能。代碼如下:
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.wallx = 400 # 管道所在X軸坐標(biāo)
self.pineUp = pygame.image.load("assets/top.png") # 加載上管道圖片
self.pineDown = pygame.image.load("assets/bottom.png") # 加載下管道圖片
def updatePipeline(self):
"""管道水平移動(dòng)方法"""
self.wallx -= 5 # 管道X軸坐標(biāo)遞減,即管道向左移動(dòng)
# 當(dāng)管道運(yùn)行到一定位置,即小鳥(niǎo)飛越管道,分?jǐn)?shù)加1,并且管道重置
if self.wallx < -80:
global score
score += 1
self.wallx = 400
def createMap(screen, background, font):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示管道
screen.blit(Pipeline.pineUp, (Pipeline.wallx, -100)) # 上管道坐標(biāo)位置(X,Y)
screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500)) # 下管道坐標(biāo)位置(X,Y)
Pipeline.updatePipeline() # 管道移動(dòng)
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
# 顯示分?jǐn)?shù)
screen.blit(font.render("score: " + str(score), -1, (255, 255, 255)), (230, 20)) # 設(shè)置顏色及坐標(biāo)位置
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
pygame.font.init() # 初始化字體
font = pygame.font.SysFont(None, 50) # 設(shè)置默認(rèn)字體和大小
size = width, height = 400, 680 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
score = 0 # 初始化分?jǐn)?shù)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background, font) # 繪制地圖
pygame.quit() # 退出
- 運(yùn)行效果如下:
7. 碰撞檢測(cè)
- 當(dāng)小鳥(niǎo)與管道相碰撞時(shí),小鳥(niǎo)顏色變?yōu)榛疑?,游戲結(jié)束,并且顯示總分?jǐn)?shù)。在checkDead()函數(shù)中通過(guò)pygame.Rect()可以分別獲取小鳥(niǎo)的矩形區(qū)域?qū)ο蠛凸艿赖木匦螀^(qū)域?qū)ο螅搶?duì)象有一個(gè)colliderect()方法可以判斷倆各個(gè)矩形區(qū)域是否相碰撞。如果相碰撞,設(shè)置Bird.dead屬性為T(mén)rue。此外,當(dāng)小鳥(niǎo)飛出窗體時(shí),也設(shè)置Bird.dead屬性為T(mén)rue。最后,用兩行文字顯示總成績(jī)。關(guān)鍵代碼如下:
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.wallx = 400 # 管道所在X軸坐標(biāo)
self.pineUp = pygame.image.load("assets/top.png") # 加載上管道圖片
self.pineDown = pygame.image.load("assets/bottom.png") # 加載下管道圖片
def updatePipeline(self):
"""管道水平移動(dòng)方法"""
self.wallx -= 5 # 管道X軸坐標(biāo)遞減,即管道向左移動(dòng)
# 當(dāng)管道運(yùn)行到一定位置,即小鳥(niǎo)飛越管道,分?jǐn)?shù)加1,并且管道重置
if self.wallx < -80:
global score
score += 1
self.wallx = 400
def createMap(screen, background, font):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示管道
screen.blit(Pipeline.pineUp, (Pipeline.wallx, -100)) # 上管道坐標(biāo)位置(X,Y)
screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500)) # 下管道坐標(biāo)位置(X,Y)
Pipeline.updatePipeline() # 管道移動(dòng)
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
# 顯示分?jǐn)?shù)
screen.blit(font.render("score: " + str(score), -1, (255, 255, 255)), (230, 20)) # 設(shè)置顏色及坐標(biāo)位置
pygame.display.update() # 更新顯示
def checkDead():
# 上方管子的矩形位置
upRect = pygame.Rect(Pipeline.wallx, -100,Pipeline.pineUp.get_width() - 10, Pipeline.pineUp.get_height())
# 下方管子的矩形位置
downRect = pygame.Rect(Pipeline.wallx, 500, Pipeline.pineDown.get_width() - 10, Pipeline.pineDown.get_height())
# 檢測(cè)小鳥(niǎo)與上下方管子是否碰撞
if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
Bird.dead = True
return True
else:
return False
def getResult():
final_text1 = "Game over"
final_text2 = "Your final score is: " + str(score)
ft1_font = pygame.font.SysFont("Arial", 70) # 設(shè)置第一行文字字體
ft1_surf = ft1_font.render(final_text1, 1, (242, 3, 36)) # 設(shè)置第一行文字的顏色
ft2_font = pygame.font.SysFont("Arial", 50) # 設(shè)置第二行文字字體
ft2_surf = ft2_font.render(final_text2, 1, (253, 177, 6)) # 設(shè)置第二行文字顏色
# 設(shè)置第一行文字顯示位置
screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])
# 設(shè)置第二行文字顯示位置
screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 200])
pygame.display.flip() # 更新整個(gè)待顯示的Surface對(duì)象到屏幕上
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
pygame.font.init() # 初始化字體
font = pygame.font.SysFont(None, 50) # 設(shè)置默認(rèn)字體和大小
size = width, height = 400, 680 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
score = 0 # 初始化分?jǐn)?shù)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
if checkDead(): # 檢測(cè)小鳥(niǎo)生命狀態(tài)
getResult() # 如果小鳥(niǎo)死亡,游戲結(jié)束,顯示游戲總分?jǐn)?shù)
else:
createMap(screen, background, font) # 繪制地圖
pygame.quit() # 退出
- 上述代碼的checkDead()方法中,upRect.colliderect(Bird.birdRect)用于檢測(cè)小鳥(niǎo)的矩形區(qū)域是否與上管道的矩形區(qū)域相撞,colliderect()函數(shù)的參數(shù)是另一個(gè)矩形區(qū)域?qū)ο?。碰撞后小鳥(niǎo)死亡的情況如下圖:
- 本實(shí)例已經(jīng)實(shí)現(xiàn)了Flappy Bird的基本功能,但還有很多需要完善的地方,如設(shè)置游戲的難度,包括設(shè)置管道的高度、小鳥(niǎo)的飛行速度等。
4. 小結(jié)
- 主要講解了如何使用Pygame開(kāi)發(fā)游戲。首先通過(guò)一個(gè)跳躍的小球游戲來(lái)了解Pygame的基本使用方法,然后利用Python逐步開(kāi)發(fā)一個(gè)知名游戲Flappy Bird。通過(guò)本章的學(xué)習(xí),可以掌握Pygame的基礎(chǔ)知識(shí),并使用Python面向?qū)ο蟮乃季S方式開(kāi)發(fā)一個(gè)Python小游戲,進(jìn)一步體會(huì)Python編程的樂(lè)趣。
最后,感謝每一個(gè)認(rèn)真閱讀我文章的人,禮尚往來(lái)總是要有的,下面資料雖然不是什么很值錢(qián)的東西,如果你用得到的話(huà)可以直接拿走:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-763868.html
- ① Python所有方向的學(xué)習(xí)路線(xiàn)圖,清楚各個(gè)方向要學(xué)什么東西
- ② 600多節(jié)Python課程視頻,涵蓋必備基礎(chǔ)、爬蟲(chóng)和數(shù)據(jù)分析
- ③ 100多個(gè)Python實(shí)戰(zhàn)案例,含50個(gè)超大型項(xiàng)目詳解,學(xué)習(xí)不再是只會(huì)理論
- ④ 20款主流手游迫解 爬蟲(chóng)手游逆行迫解教程包
- ⑤ 爬蟲(chóng)與反爬蟲(chóng)攻防教程包,含15個(gè)大型網(wǎng)站迫解
- ⑥ 爬蟲(chóng)APP逆向?qū)崙?zhàn)教程包,含45項(xiàng)絕密技術(shù)詳解
- ⑦ 超300本Python電子好書(shū),從入門(mén)到高階應(yīng)有盡有
- ⑧ 華為出品獨(dú)家Python漫畫(huà)教程,手機(jī)也能學(xué)習(xí)
- ⑨ 歷年互聯(lián)網(wǎng)企業(yè)Python面試真題,復(fù)習(xí)時(shí)非常方便
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-763868.html
Python非常受歡迎的一個(gè)原因是它的應(yīng)用領(lǐng)域非常廣泛,其中就包括游戲開(kāi)發(fā)。而是用Python進(jìn)行游戲開(kāi)發(fā)的首選模塊就是PyGame如何用python畫(huà)不同大小的滿(mǎn)天星。
1. 初識(shí)Pygame
- PyGame是跨平臺(tái)Python模塊,專(zhuān)為電子游戲設(shè)計(jì),包含圖像、聲音等,創(chuàng)建在SDL(Simple DirectMedia Layer)基礎(chǔ)上,允許實(shí)時(shí)電子游戲研發(fā)而不會(huì)被低級(jí)語(yǔ)言,如C語(yǔ)言或是更低級(jí)的匯編語(yǔ)言束縛。基于這樣一個(gè)設(shè)想,所有需要的游戲功能和理念(主要是圖像方面)都完全簡(jiǎn)化為游戲邏輯本身,所有的資源結(jié)構(gòu)都可以由高級(jí)語(yǔ)言(如Python)提供。
1. 安裝Pygame
- PyGame的官方網(wǎng)址是www.pygame.org。在該網(wǎng)址中可以查看PyGame的相關(guān)文檔。PyGame的安裝命令很簡(jiǎn)單:
pip install pygame
- 檢查模塊是否安裝成功:
import pygame
pygame.ver
- 運(yùn)行結(jié)果如下:
2. Pygame常用模塊
- Pygame做游戲開(kāi)發(fā)的優(yōu)勢(shì)在于不需要過(guò)多地考慮底層相關(guān)的內(nèi)容,可以把工作中心放在游戲邏輯上。例如,PyGame中集成了很多和底層相關(guān)的模塊,如訪(fǎng)問(wèn)顯示設(shè)備、管理事件、使用字體等。
- Pygame常用模塊如下:
模塊名 | 功能 |
---|---|
pygame.cdrom | 訪(fǎng)問(wèn)光驅(qū)。 |
pygame.cursors | 加載光標(biāo)。 |
pygame.display | 訪(fǎng)問(wèn)顯示設(shè)備。 |
pygame.draw | 繪制形狀、線(xiàn)和點(diǎn)。 |
pygame.event | 管理事件。 |
pygame.font | 使用字體。 |
pygame.image | 加載和存儲(chǔ)圖片。 |
pygame.joystick | 使用游戲手柄或類(lèi)似的東西。 |
pygame.key | 讀取鍵盤(pán)按鍵。 |
pygame.mixer | 聲音。 |
pygame.mouse | 鼠標(biāo)。 |
pygame.movie | 播放視頻。 |
pygame.music | 播放音樂(lè)。 |
pygame.overlay | 訪(fǎng)問(wèn)高級(jí)視頻疊加。 |
pygame.rect | 管理矩形區(qū)域。 |
pygame.sndarray | 操作聲音數(shù)據(jù)。 |
pygame.sprite | 操作移動(dòng)圖像。 |
pygame.surface | 管理圖像和屏幕。 |
pygame.surfarray | 管理點(diǎn)陣圖像數(shù)據(jù)。 |
pygame.time | 管理時(shí)間和幀信息。 |
pygame.transform | 縮放和移動(dòng)圖像。 |
- 使用Pygame的display模塊和event模塊創(chuàng)建一個(gè)PyGame窗口,代碼如下:
# -*- coding: utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 320, 240 # 設(shè)置窗口尺寸
screen = pygame.display.set_mode(size) # 顯示窗口
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get(): # 遍歷所有事件
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
pygame.quit() # 退出pygame
- 運(yùn)行結(jié)果如下:
2. 制作一個(gè)跳躍的小球游戲(Pygame基本使用)
- 創(chuàng)建一個(gè)游戲窗口,然后在窗口內(nèi)創(chuàng)建一個(gè)小球。以一定速度移動(dòng)小球,當(dāng)小球碰到游戲窗口的邊緣時(shí),小球彈回,繼續(xù)移動(dòng)。
(1)創(chuàng)建一個(gè)游戲窗口,寬高設(shè)置640*480:
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width,height=640,480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
- 上述代碼中,首先導(dǎo)入pygame模塊,然后調(diào)用init()方法初始化pygame模塊。接下來(lái)設(shè)置窗口的寬和高,最后使用display模塊顯示窗體。
- display模塊的常用方法:
方法名 | 功能 |
---|---|
pygame.display.init | 初始化display模塊。 |
pygame.display.quit | 結(jié)束display模塊。 |
pygame.display.get_init | 如果display模塊已經(jīng)被初始化,則返回True。 |
pygame.display.set_mode | 初始化一個(gè)準(zhǔn)備顯示的界面。 |
pygame.display.get_surface | 獲取當(dāng)前的Surface對(duì)象。 |
pygame.display.flip | 更新整個(gè)待顯示的Surface對(duì)象到屏幕上。 |
pygame.display.update | 更新部分內(nèi)容顯示到屏幕上,如果沒(méi)有參數(shù)則與flip功能相同。 |
(2)運(yùn)行上述代碼,會(huì)出現(xiàn)一個(gè)一閃而過(guò)的黑色窗口,這是因?yàn)槌绦驁?zhí)行完成后會(huì)自動(dòng)關(guān)閉。如果讓窗口一直顯示,需要使用while True讓程序一直執(zhí)行,此外,還需要設(shè)置關(guān)閉按鈕。代碼具體如下: |
# -*-coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
pygame.quit() # 退出pygame
- 上述代碼中,添加了輪詢(xún)事件檢測(cè)。pygame.event.get()能夠獲取事件隊(duì)列,使用for…in遍歷事件,然后根據(jù)type屬性判斷事件類(lèi)型。這里的事件處理方式與GUI類(lèi)似,如event.type等于pygame.GUIT表示檢測(cè)到關(guān)閉pygame窗口事件,pygame.KEYDOWN表示鍵盤(pán)按下事件,pygame.MOUSEBUTTONDOWN表示鼠標(biāo)按下事件等。
(3)在窗口中添加小球。我們先準(zhǔn)備好一張ball.png圖片,然后加載該圖片,最后將圖片顯示在窗口中:
# #######################1. 窗口一閃而過(guò)
# import sys # 導(dǎo)入sys模塊
# import pygame # 導(dǎo)入pygame模塊
#
# pygame.init() # 初始化pygame
# size = width,height=640,480 # 設(shè)置窗口
# screen = pygame.display.set_mode(size) # 顯示窗口
# ##############################2. 窗口持續(xù)
# # -*-coding:utf-8 -*-
# import sys # 導(dǎo)入sys模塊
# import pygame # 導(dǎo)入pygame模塊
#
# pygame.init() # 初始化pygame
# size = width, height = 640, 480 # 設(shè)置窗口
# screen = pygame.display.set_mode(size) # 顯示窗口
#
# # 執(zhí)行死循環(huán),確保窗口一直顯示
# while True:
# # 檢查事件
# for event in pygame.event.get():
# if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
# sys.exit()
# pygame.quit() # 退出pygame
# ######################3. 添加ball的窗口
# -*-coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果點(diǎn)擊關(guān)閉窗口,則退出
sys.exit()
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 上述代碼使用image模塊的load()方法加載圖片,返回值ball是一個(gè)Surface對(duì)象。Surface是用來(lái)代表圖片的pygame對(duì)象,可以對(duì)一個(gè)Surface對(duì)象進(jìn)行涂畫(huà)、變形、復(fù)制等各種操作。事實(shí)上,屏幕也只是一個(gè)surface,pygame.display.set_mode就返回一個(gè)屏幕Surface對(duì)象。如果將ball這個(gè)Surface對(duì)象畫(huà)到screen.Surface對(duì)象,需要使用blit()方法,最后使用display模塊的flip方法更新整個(gè)待顯示的Surface對(duì)象到屏幕上。
- 運(yùn)行結(jié)果如下:
- Surface對(duì)象的常用方法如下:
方法名 | 功能 |
---|---|
pygame.Surface.blit | 將一個(gè)圖像畫(huà)到另一個(gè)圖像上。 |
pygame.Surface.convert | 轉(zhuǎn)換圖像的像素格式。 |
pygame.Surface.convert_alpha | 轉(zhuǎn)換圖像的像素格式,包含alpha通道的轉(zhuǎn)換。 |
pygame.Surface.fill | 使用顏色填充Surface |
pygame.Surface.get_rect | 獲取Surface的矩形區(qū)域。 |
(4)下面該讓小球動(dòng)起來(lái)了。ball.get_rect()方法返回值ballrect()方法返回值ballrect是一個(gè)Rect對(duì)象,該對(duì)象有一個(gè)move()方法可用于移動(dòng)矩形。move(x,y)函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)是X軸移動(dòng)的距離,第二個(gè)參數(shù)是Y軸移動(dòng)的距離。窗體左上角坐標(biāo)為(0,0),例如move(100,50)。
- 為實(shí)現(xiàn)小球不停地移動(dòng),將move()函數(shù)添加到while循環(huán)內(nèi):
# -*- coding:utf-8-*-
import sys
import pygame
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
speed = [5, 5] # 設(shè)置移動(dòng)的X軸、Y軸距離
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
ballrect = ballrect.move(speed) # 移動(dòng)小球
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 運(yùn)行上述代碼,小球在屏幕中一閃而過(guò),此時(shí),小球并沒(méi)有真正消失,而是移動(dòng)到窗體外了,此時(shí)需要添加碰撞檢測(cè)的功能。當(dāng)小球與窗體的任一邊緣發(fā)生碰撞,則改變小球的移動(dòng)方向:
# -*- coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置窗口背景顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
speed = [1, 1] # 設(shè)置移動(dòng)的X軸、Y軸距離
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
ballrect = ballrect.move(speed) # 移動(dòng)小球
# 碰到左右邊緣
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
# 碰到上下邊緣
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 上述代碼中,添加了碰撞檢測(cè)功能。如果球碰到左右邊緣,則更改X軸數(shù)據(jù)為負(fù)數(shù);如果碰到上下邊緣,則改Y軸數(shù)據(jù)為負(fù)數(shù)。
- 運(yùn)行結(jié)果如下:
(6)運(yùn)行上述代碼發(fā)現(xiàn)好像有多個(gè)小球在飛快移動(dòng),這是因?yàn)檫\(yùn)行上述代碼的時(shí)間非常短,導(dǎo)致肉眼錯(cuò)覺(jué),因此需要添加一個(gè)“時(shí)鐘”來(lái)控制程序運(yùn)行時(shí)間。用pygame的time模塊控制。使用pygame時(shí)鐘前,必須先創(chuàng)建一個(gè)Clock對(duì)象的一個(gè)實(shí)例,然后在while循環(huán)中設(shè)置多長(zhǎng)時(shí)間運(yùn)行一次。代碼如下:
# -*- coding:utf-8 -*-
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
pygame.init() # 初始化pygame
size = width, height = 640, 480 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
color = (0, 0, 0) # 設(shè)置顏色
ball = pygame.image.load("ball.png") # 加載圖片
ballrect = ball.get_rect() # 獲取矩形區(qū)域
speed = [5, 5] # 設(shè)置移動(dòng)的X軸、Y軸距離
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
# 執(zhí)行死循環(huán),確保窗口一直顯示
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 檢查事件
for event in pygame.event.get():
if event.type == pygame.QUIT: # 如果單擊關(guān)閉窗口,則退出
sys.exit()
ballrect = ballrect.move(speed) # 移動(dòng)小球
# 碰到左右邊緣
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
# 碰到上下邊緣
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
screen.fill(color) # 填充顏色
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
screen.blit(ball, ballrect) # 將圖片畫(huà)到窗口上
pygame.display.flip() # 更新全部顯示
pygame.quit() # 退出pygame
- 至此,就完成了跳躍的小球游戲。
- 運(yùn)行效果如下:
3. 開(kāi)發(fā)Flappy Bird游戲
- 游戲的素材可以從該網(wǎng)站上找自己喜歡的:https://www.aigei.com/s?tab=file&type=2d&q=flappy+bird&page=3#resContainer
- 也可以使用我下載的:
1. 游戲簡(jiǎn)介
- Flappy Bird是一款鳥(niǎo)類(lèi)飛行游戲,由越南河內(nèi)獨(dú)立游戲開(kāi)發(fā)者阮哈東(DongNguyen)開(kāi)發(fā)。在Flappy Bird這款游戲中,玩家只需要用一根手指來(lái)操控,單擊觸摸手機(jī)屏幕,小鳥(niǎo)就會(huì)往上飛,不斷地單擊就會(huì)不斷地往高處飛。放松手指,則會(huì)快速下降。所以玩家要控制小鳥(niǎo)一直向前飛行,然后注意躲避途中高低不平的管子。如果小鳥(niǎo)碰到了障礙物,游戲就會(huì)結(jié)束。每當(dāng)小鳥(niǎo)飛過(guò)一組管道,玩家就會(huì)獲得一分。
2. 游戲分析
- 在Flappy Bird中,主要有兩個(gè)對(duì)象:小鳥(niǎo)和管道??梢詣?chuàng)建Bird類(lèi)和Pineline類(lèi)來(lái)分別表示這兩個(gè)對(duì)象。小鳥(niǎo)可以通過(guò)上下移動(dòng)來(lái)躲避管道,所以在Bird類(lèi)中創(chuàng)建一個(gè)birdUpdate()方法,實(shí)現(xiàn)小鳥(niǎo)的上下移動(dòng)。為了體現(xiàn)小鳥(niǎo)向前飛行的特征,可以讓管道一直向左側(cè)移動(dòng),這樣在窗口中就好像小鳥(niǎo)在向前飛行。所以,在Pineline類(lèi)中也創(chuàng)建了一個(gè)updatePipline()方法,實(shí)現(xiàn)管道的向左移動(dòng)。此外,還創(chuàng)建了3個(gè)函數(shù):createMap()函數(shù)用于繪制地圖;checkDead()函數(shù)用于判斷小鳥(niǎo)的生命狀態(tài);getResult()函數(shù)用于獲取最終分?jǐn)?shù)。最后在主邏輯中實(shí)例化類(lèi)并調(diào)用相關(guān)方法,實(shí)現(xiàn)相應(yīng)功能。
3. 搭建主框架
- 通過(guò)前面分析,我們可以搭建起Flappy Bird游戲的主框架。Flappy Bird游戲有兩個(gè)對(duì)象:小鳥(niǎo)和管道。先來(lái)創(chuàng)建這兩個(gè)類(lèi),類(lèi)中的具體方法可以先使用pass語(yǔ)句替代。然后創(chuàng)建一個(gè)繪制地圖的函數(shù)createMap()。最后,在主邏輯中繪制背景圖片。關(guān)鍵代碼如下:
import pygame
import sys
import random
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
pass
def birdUpdate(self):
pass
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
pass
def updatePipeline(self):
"""水平移動(dòng)"""
pass
def createMap(screen, background):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
size = width, height = 400, 720 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background) # 繪制地圖
pygame.quit() # 退出
- 運(yùn)行結(jié)果如下:
4. 創(chuàng)建小鳥(niǎo)類(lèi)
- 下面創(chuàng)建小鳥(niǎo)類(lèi)。該類(lèi)需要初始化很多參數(shù),所以定義一個(gè)__init__()方法,用來(lái)初始化各種參數(shù),包括鳥(niǎo)飛行的幾種狀態(tài)、飛行的速度、跳躍的高度等。然后定義birdUpdate()方法,該方法用于實(shí)現(xiàn)小鳥(niǎo)的跳躍和墜落。接下來(lái),在主邏輯的輪詢(xún)事件中添加鍵盤(pán)按下事件或鼠標(biāo)單擊事件,如按下鼠標(biāo),使小鳥(niǎo)上升等。最后,在createMap()方法中顯示小鳥(niǎo)的圖像。
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
pass
def updatePipeline(self):
"""水平移動(dòng)"""
pass
def createMap(screen, background):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
size = width, height = 400, 720 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background) # 繪制地圖
pygame.quit() # 退出
- 上述代碼在Bird類(lèi)中設(shè)置了birdStatus屬性,該屬性是一個(gè)鳥(niǎo)類(lèi)圖片的列表,列表中顯示鳥(niǎo)類(lèi)的3種飛行狀態(tài),根據(jù)小鳥(niǎo)的不同狀態(tài)加載相應(yīng)的圖片。在birdUpdate()方法中,為了達(dá)到較好的動(dòng)畫(huà)效果,使用jumpSpeed和gravity兩個(gè)屬性逐漸變化。運(yùn)行上述代碼,在窗體內(nèi)創(chuàng)建一只鳥(niǎo),默認(rèn)情況下小鳥(niǎo)會(huì)一直下降。當(dāng)單擊一下鼠標(biāo)或按一下鍵盤(pán),小鳥(niǎo)會(huì)跳躍一下,高度上升。運(yùn)行效果如下圖:
5. 創(chuàng)建管道類(lèi)
- 創(chuàng)建完鳥(niǎo)類(lèi)之后,我們來(lái)創(chuàng)建管道類(lèi)。同樣,在_init_()方法中初始化各種參數(shù),包括設(shè)置管道的坐標(biāo),加載上下管道圖片等。然后在updatePipline()方法中,定義管道向左移動(dòng)的速度,并且當(dāng)管道移出屏幕時(shí)重新繪制下一組管道。最后,在createMap()函數(shù)中顯示管道。關(guān)鍵代碼如下:
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.wallx = 400 # 管道所在X軸坐標(biāo)
self.pineUp = pygame.image.load("assets/top.png") # 加載上管道圖片
self.pineDown = pygame.image.load("assets/bottom.png") # 加載下管道圖片
def updatePipeline(self):
"""管道水平移動(dòng)方法"""
self.wallx -= 5 # 管道X軸坐標(biāo)遞減,即管道向左移動(dòng)
# 當(dāng)管道運(yùn)行到一定位置,即小鳥(niǎo)飛越管道,分?jǐn)?shù)加1,并且管道重置
if self.wallx < -80:
self.wallx = 400
def createMap(screen, background):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示管道
screen.blit(Pipeline.pineUp, (Pipeline.wallx, -300)) # 上管道坐標(biāo)位置(X,Y)
screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500)) # 下管道坐標(biāo)位置(X,Y)
Pipeline.updatePipeline() # 管道移動(dòng)
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
size = width, height = 400, 720 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background) # 繪制地圖
pygame.quit() # 退出
- 上述代碼中,在createMap()函數(shù)中,設(shè)置先顯示管道,再顯示小鳥(niǎo)。這樣做的目的是,當(dāng)小鳥(niǎo)與管道圖像重合的時(shí)候,小鳥(niǎo)的圖像顯示在上層,而管道的圖像顯示在底層。運(yùn)行結(jié)果如下:
6. 計(jì)算得分
- 當(dāng)小鳥(niǎo)飛過(guò)管道時(shí),玩家得分加1.這里對(duì)于飛過(guò)管道的邏輯做了簡(jiǎn)化處理:當(dāng)管道移動(dòng)到窗體左側(cè)一定距離后,默認(rèn)小鳥(niǎo)飛過(guò)管道,使分?jǐn)?shù)加1,并顯示在屏幕上。在updatePipeline()方法中實(shí)現(xiàn)該功能。代碼如下:
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.wallx = 400 # 管道所在X軸坐標(biāo)
self.pineUp = pygame.image.load("assets/top.png") # 加載上管道圖片
self.pineDown = pygame.image.load("assets/bottom.png") # 加載下管道圖片
def updatePipeline(self):
"""管道水平移動(dòng)方法"""
self.wallx -= 5 # 管道X軸坐標(biāo)遞減,即管道向左移動(dòng)
# 當(dāng)管道運(yùn)行到一定位置,即小鳥(niǎo)飛越管道,分?jǐn)?shù)加1,并且管道重置
if self.wallx < -80:
global score
score += 1
self.wallx = 400
def createMap(screen, background, font):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示管道
screen.blit(Pipeline.pineUp, (Pipeline.wallx, -100)) # 上管道坐標(biāo)位置(X,Y)
screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500)) # 下管道坐標(biāo)位置(X,Y)
Pipeline.updatePipeline() # 管道移動(dòng)
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
# 顯示分?jǐn)?shù)
screen.blit(font.render("score: " + str(score), -1, (255, 255, 255)), (230, 20)) # 設(shè)置顏色及坐標(biāo)位置
pygame.display.update() # 更新顯示
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
pygame.font.init() # 初始化字體
font = pygame.font.SysFont(None, 50) # 設(shè)置默認(rèn)字體和大小
size = width, height = 400, 680 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
score = 0 # 初始化分?jǐn)?shù)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
createMap(screen, background, font) # 繪制地圖
pygame.quit() # 退出
- 運(yùn)行效果如下:
7. 碰撞檢測(cè)
- 當(dāng)小鳥(niǎo)與管道相碰撞時(shí),小鳥(niǎo)顏色變?yōu)榛疑?,游戲結(jié)束,并且顯示總分?jǐn)?shù)。在checkDead()函數(shù)中通過(guò)pygame.Rect()可以分別獲取小鳥(niǎo)的矩形區(qū)域?qū)ο蠛凸艿赖木匦螀^(qū)域?qū)ο螅搶?duì)象有一個(gè)colliderect()方法可以判斷倆各個(gè)矩形區(qū)域是否相碰撞。如果相碰撞,設(shè)置Bird.dead屬性為T(mén)rue。此外,當(dāng)小鳥(niǎo)飛出窗體時(shí),也設(shè)置Bird.dead屬性為T(mén)rue。最后,用兩行文字顯示總成績(jī)。關(guān)鍵代碼如下:
import pygame
import sys
import random
# 素材參考地址:https://www.aigei.com/s?q=flappy+bird&type=2d
class Bird(object):
"""定義一個(gè)鳥(niǎo)類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.birdRect = pygame.Rect(65, 50, 50, 50) # 鳥(niǎo)的矩形
# 定義鳥(niǎo)的3種狀態(tài)列表
self.birdStatus = [pygame.image.load("assets/1.png"),
pygame.image.load("assets/2.png"),
pygame.image.load("assets/dead.png")]
self.status = 0 # 默認(rèn)飛行狀態(tài)
self.birdX = 120 # 鳥(niǎo)所在X軸坐標(biāo)
self.birdY = 350 # 鳥(niǎo)所在Y軸坐標(biāo),即上下飛行高度
self.jump = False # 默認(rèn)情況小鳥(niǎo)自動(dòng)降落
self.jumpSpeed = 10 # 跳躍高度
self.gravity = 5 # 重力
self.dead = False # 默認(rèn)小鳥(niǎo)生命狀態(tài)為活著
def birdUpdate(self):
if self.jump:
# 小鳥(niǎo)跳躍
self.jumpSpeed -= 1 # 速度遞減,上升越來(lái)越慢
self.birdY -= self.jumpSpeed # 鳥(niǎo)Y軸坐標(biāo)減小,小鳥(niǎo)上升
else:
# 小鳥(niǎo)墜落
self.gravity += 0.2 # 重力遞增,下降越來(lái)越快
self.birdY += self.gravity # 鳥(niǎo)Y軸坐標(biāo)增加,小鳥(niǎo)下降
self.birdRect[1] = self.birdY # 更改Y軸位置
class Pipeline(object):
"""定義一個(gè)管道類(lèi)"""
def __init__(self):
"""定義初始化方法"""
self.wallx = 400 # 管道所在X軸坐標(biāo)
self.pineUp = pygame.image.load("assets/top.png") # 加載上管道圖片
self.pineDown = pygame.image.load("assets/bottom.png") # 加載下管道圖片
def updatePipeline(self):
"""管道水平移動(dòng)方法"""
self.wallx -= 5 # 管道X軸坐標(biāo)遞減,即管道向左移動(dòng)
# 當(dāng)管道運(yùn)行到一定位置,即小鳥(niǎo)飛越管道,分?jǐn)?shù)加1,并且管道重置
if self.wallx < -80:
global score
score += 1
self.wallx = 400
def createMap(screen, background, font):
"""定義創(chuàng)建地圖的方法"""
screen.fill((255, 255, 255)) # 填充顏色
screen.blit(background, (0, 0)) # 填入到背景
# 顯示管道
screen.blit(Pipeline.pineUp, (Pipeline.wallx, -100)) # 上管道坐標(biāo)位置(X,Y)
screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500)) # 下管道坐標(biāo)位置(X,Y)
Pipeline.updatePipeline() # 管道移動(dòng)
# 顯示小鳥(niǎo)
if Bird.dead: # 撞管道狀態(tài)
Bird.status = 2
elif Bird.jump: # 起飛狀態(tài)
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY)) # 設(shè)置小鳥(niǎo)的坐標(biāo)
Bird.birdUpdate() # 鳥(niǎo)移動(dòng)
# 顯示分?jǐn)?shù)
screen.blit(font.render("score: " + str(score), -1, (255, 255, 255)), (230, 20)) # 設(shè)置顏色及坐標(biāo)位置
pygame.display.update() # 更新顯示
def checkDead():
# 上方管子的矩形位置
upRect = pygame.Rect(Pipeline.wallx, -100,Pipeline.pineUp.get_width() - 10, Pipeline.pineUp.get_height())
# 下方管子的矩形位置
downRect = pygame.Rect(Pipeline.wallx, 500, Pipeline.pineDown.get_width() - 10, Pipeline.pineDown.get_height())
# 檢測(cè)小鳥(niǎo)與上下方管子是否碰撞
if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
Bird.dead = True
return True
else:
return False
def getResult():
final_text1 = "Game over"
final_text2 = "Your final score is: " + str(score)
ft1_font = pygame.font.SysFont("Arial", 70) # 設(shè)置第一行文字字體
ft1_surf = ft1_font.render(final_text1, 1, (242, 3, 36)) # 設(shè)置第一行文字的顏色
ft2_font = pygame.font.SysFont("Arial", 50) # 設(shè)置第二行文字字體
ft2_surf = ft2_font.render(final_text2, 1, (253, 177, 6)) # 設(shè)置第二行文字顏色
# 設(shè)置第一行文字顯示位置
screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])
# 設(shè)置第二行文字顯示位置
screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 200])
pygame.display.flip() # 更新整個(gè)待顯示的Surface對(duì)象到屏幕上
if __name__ == "__main__":
"""主程序"""
pygame.init() # 初始化pygame
pygame.font.init() # 初始化字體
font = pygame.font.SysFont(None, 50) # 設(shè)置默認(rèn)字體和大小
size = width, height = 400, 680 # 設(shè)置窗口
screen = pygame.display.set_mode(size) # 顯示窗口
clock = pygame.time.Clock() # 設(shè)置時(shí)鐘
Pipeline = Pipeline() # 實(shí)例化管道類(lèi)
Bird = Bird() # 實(shí)例化鳥(niǎo)類(lèi)
score = 0 # 初始化分?jǐn)?shù)
while True:
clock.tick(60) # 每秒執(zhí)行60次
# 輪詢(xún)事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True # 跳躍
Bird.gravity = 5 # 重力
Bird.jumpSpeed = 10 # 跳躍速度
background = pygame.image.load("assets/background.png") # 加載背景圖片
if checkDead(): # 檢測(cè)小鳥(niǎo)生命狀態(tài)
getResult() # 如果小鳥(niǎo)死亡,游戲結(jié)束,顯示游戲總分?jǐn)?shù)
else:
createMap(screen, background, font) # 繪制地圖
pygame.quit() # 退出
- 上述代碼的checkDead()方法中,upRect.colliderect(Bird.birdRect)用于檢測(cè)小鳥(niǎo)的矩形區(qū)域是否與上管道的矩形區(qū)域相撞,colliderect()函數(shù)的參數(shù)是另一個(gè)矩形區(qū)域?qū)ο蟆E鲎埠笮▲B(niǎo)死亡的情況如下圖:
- 本實(shí)例已經(jīng)實(shí)現(xiàn)了Flappy Bird的基本功能,但還有很多需要完善的地方,如設(shè)置游戲的難度,包括設(shè)置管道的高度、小鳥(niǎo)的飛行速度等。
4. 小結(jié)
- 主要講解了如何使用Pygame開(kāi)發(fā)游戲。首先通過(guò)一個(gè)跳躍的小球游戲來(lái)了解Pygame的基本使用方法,然后利用Python逐步開(kāi)發(fā)一個(gè)知名游戲Flappy Bird。通過(guò)本章的學(xué)習(xí),可以掌握Pygame的基礎(chǔ)知識(shí),并使用Python面向?qū)ο蟮乃季S方式開(kāi)發(fā)一個(gè)Python小游戲,進(jìn)一步體會(huì)Python編程的樂(lè)趣。
最后,感謝每一個(gè)認(rèn)真閱讀我文章的人,禮尚往來(lái)總是要有的,下面資料雖然不是什么很值錢(qián)的東西,如果你用得到的話(huà)可以直接拿走:
- ① Python所有方向的學(xué)習(xí)路線(xiàn)圖,清楚各個(gè)方向要學(xué)什么東西
- ② 600多節(jié)Python課程視頻,涵蓋必備基礎(chǔ)、爬蟲(chóng)和數(shù)據(jù)分析
- ③ 100多個(gè)Python實(shí)戰(zhàn)案例,含50個(gè)超大型項(xiàng)目詳解,學(xué)習(xí)不再是只會(huì)理論
- ④ 20款主流手游迫解 爬蟲(chóng)手游逆行迫解教程包
- ⑤ 爬蟲(chóng)與反爬蟲(chóng)攻防教程包,含15個(gè)大型網(wǎng)站迫解
- ⑥ 爬蟲(chóng)APP逆向?qū)崙?zhàn)教程包,含45項(xiàng)絕密技術(shù)詳解
- ⑦ 超300本Python電子好書(shū),從入門(mén)到高階應(yīng)有盡有
- ⑧ 華為出品獨(dú)家Python漫畫(huà)教程,手機(jī)也能學(xué)習(xí)
- ⑨ 歷年互聯(lián)網(wǎng)企業(yè)Python面試真題,復(fù)習(xí)時(shí)非常方便
到了這里,關(guān)于python制作小游戲50行代碼,用python制作小游戲代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!