python-pygame學習筆記

易哥哦發表於2020-09-27

理解Pygame

• Python最經典的2D遊戲開發第三方庫,也支援3D遊戲開發
• Pygame適合用於遊戲邏輯驗證、遊戲入門及系統演示驗證
• Pygame是一種遊戲開發引擎,基本邏輯具有參考價值
• Pygame有些"過時",但永遠"不過時"
• 使用Pygame可以開發出優秀的遊戲!
在這裡插入圖片描述

sys庫

• sys是Python的標準庫
• sys提供Python執行時環境變數的操控
• sys.exit()用於退出結束遊戲並退出
在這裡插入圖片描述

pygame.init()

對Pygame內部各功能模組進行初始化建立及
變數設定,預設呼叫
在這裡插入圖片描述

pygame.display.set_mode(size)

初始化顯示視窗,第一個引數size是一個二
值元組,分別表示視窗的寬度和高度
在這裡插入圖片描述

pygame.display.set_caption(title)

設定顯示視窗的標題內容,引數title是一個字串型別
在這裡插入圖片描述

while True:

無限迴圈,直到Python執行時退出結束

在這裡插入圖片描述

pygame.event.get()

從Pygame的事件佇列中取出事件,並從佇列
中刪除該事件,例如:鍵盤按下是一個事件。
在這裡插入圖片描述

event.type pygame.QUIT

獲得事件型別,並逐類響應;pygame.QUIT
是Pygame中定義的退出事件常量
在這裡插入圖片描述

pygame.display.update()

對顯示視窗進行更新,預設視窗全部重繪
在這裡插入圖片描述
moveBall1.py(壁球小遊戲)

import pygame,sys
pygame.init()
size=width,height=600,400
screen=pygame.display.set_mode(size)
pygame.display.set_caption("小球碰撞")
color=60,63,65
screen.fill(color)
ball=pygame.image.load("pic/ball.png")
ball_rect=ball.get_rect()
speed=[1,1]
while True:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            sys.exit()
    ball_rect=ball_rect.move(speed[0],speed[1])
    if ball_rect.left<=0 or ball_rect.right>=width:
        speed[0]= -speed[0]
    if ball_rect.top<=0 or ball_rect.bottom>=height:
        speed[1] = -speed[1]

    screen.fill(color)
    screen.blit(ball,ball_rect)
    pygame.display.update()

pygame.time.Clock()

建立一個Clock物件,用於操作時間
在這裡插入圖片描述

clock.tick(framerate)

控制幀速度,即視窗重新整理速度,例如:
clock.tick(100)表示每秒鐘100次幀重新整理
視訊中每次展示的靜態影像稱為幀
在這裡插入圖片描述
moveBall2.py

import pygame,sys
pygame.init()
size = width, height = 600, 400
speed = [1,1]
BLACK = 0, 0, 0
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Pygame壁球")
ball = pygame.image.load("PYG02‐ball.gif")
ballrect = ball.get_rect()
fps = 300
fclock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0])1)*int(speed[0]/abs(speed[0]))
elif event.key == pygame.K_RIGHT:
speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0]1
elif event.key == pygame.K_UP:
speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1]1
elif event.key == pygame.K_DOWN:
speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1])1)*int(speed[1]/abs(speed[1]))
ballrect = ballrect.move(speed)
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(BLACK)
screen.blit(ball, ballrect)
pygame.display.update()
fclock.tick(fps)

Pygame事件處理機制

Pygame事件處理機制簡介

事件處理需求
• 響應使用者鍵盤、滑鼠等外設操作
• 響應螢幕尺寸和模式變化
• 響應遊戲情節的特定觸發條件
• 產生一些觸發條件
Pygame事件佇列在這裡插入圖片描述
Pygame事件
pygame.event.EventType
• 事件本質上是一種封裝後的資料型別(物件)
• EventType是Pygame的一個類,表示事件型別
• 事件型別只有屬性,沒有方法
• 使用者可自定義新的事件型別
Pygame事件處理函式
鍵盤事件及型別的使用
滑鼠事件及型別的使用
壁球小遊戲(滑鼠型)
事件型別及屬性
在這裡插入圖片描述
事件處理的重要函式
在這裡插入圖片描述

鍵盤事件及型別的使用

鍵盤事件及屬性
在這裡插入圖片描述
按鍵的常量名稱
event.key在這裡插入圖片描述
按鍵的修飾符
在這裡插入圖片描述

滑鼠事件及型別的使用

滑鼠事件及屬性
在這裡插入圖片描述
e.event.MOUSEMOTION 滑鼠移動事件
• event.pos 滑鼠當前座標值(x,y),相對於視窗左上角
• event.rel 滑鼠相對運動距離(X,Y),相對於上次事件
• event.buttons 滑鼠按鈕狀態(a,b,c),對應於滑鼠的三個鍵

pygame.event.MOUSEBUTTONUP 滑鼠鍵釋放事件
• event.pos 滑鼠當前座標值(x,y),相對於視窗左上角
• event.button 滑鼠按下鍵編號n 取值 0/1/2,分別對應三個鍵

pygame.event.MOUSEBUTTONDOWN 滑鼠鍵按下事件
• event.pos 滑鼠當前座標值(x,y),相對於視窗左上角
• event.button 滑鼠按下鍵編號n 取值為整數,左鍵為1,右鍵為3,裝置相關

import pygame,sys
pygame.init()
size=width,height=600,400
screen=pygame.display.set_mode(size)
pygame.display.set_caption("pygame事件處理")
while True:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            sys.exit()
        elif event.type==pygame.KEYDOWN:
            if event.unicode=="":
                print("[KEYDOWN]:","#",event.key,event.mod)
            else:
                print("[KEYDOWN]:",event.unicode,event.key,event.mod)
        elif event.type==pygame.MOUSEMOTION:
             print("[MOUSEMOTTON]",event.pos,event.rel,event.buttons)
        elif event.type==pygame.MOUSEBUTTONUP:
            print("[MOUSEBUTTONUP]",event.pos,event.button)
        elif event.type==pygame.MOUSEBUTTONDOWN:
            print("[MOUSEBUTTONDOWN",event.pos,event.button)
    pygame.display.update()

對小球彈跳進行優化

import pygame, sys

pygame.init()
vInfo = pygame.display.Info()
# 設定螢幕顯示為全屏
# size=width,height=vInfo.current_w,vInfo.current_h
# screen=pygame.display.set_mode(size,pygame.FULLSCREEN)
size = width, height = 600, 400
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
# 設定螢幕可改變
pygame.display.set_caption("小球碰撞")
color = 60, 63, 65
screen.fill(color)
ball = pygame.image.load("pic/ball.png")
ball_rect = ball.get_rect();
icon = pygame.image.load("pic/dragon.png")
pygame.display.set_icon(icon)

speed = [1, 1]
fps = 300
fClock = pygame.time.Clock()
still = False

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else ((abs(speed[1]) - 1) * int(abs(speed[1]) / speed[1]))
            elif event.key == pygame.K_ESCAPE:
                sys.exit()
        elif event.type == pygame.VIDEORESIZE:  # 當螢幕進行拉縮時
            size = width, height = event.size[0], event.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                still = True
        elif event.type == pygame.MOUSEBUTTONUP:
            still = False
            if event.button == 1:
                ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
        elif event.type == pygame.MOUSEMOTION:
            if event.buttons[0] == 1:
                ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
    if pygame.display.get_active() and not still:  # 當螢幕活躍時(未縮小為最小化)
        ball_rect = ball_rect.move(speed[0], speed[1])
    if (ball_rect.left < 0 or ball_rect.right > width):
        speed[0] = -speed[0]
        if ball_rect.right > width and ball_rect.right + speed[0] > ball_rect.right:
            speed[0] = -speed[0]
    if (ball_rect.top < 0 or ball_rect.bottom >height):
        speed[1] = -speed[1]
        if ball_rect.bottom > height and ball_rect.bottom + speed[1] >ball_rect.bottom:
            speed[1] = -speed[1]
        if ball_rect.top<0 and ball_rect.top+speed[1]<ball_rect.top:
            speed[1] = -speed[1]
    screen.fill(color)
    screen.blit(ball, ball_rect)
    pygame.display.update()
    fClock.tick(fps)

Pygame事件處理函式

事件處理的重要函式
在這裡插入圖片描述
pygame.event.get()
在這裡插入圖片描述
pygame.event.poll()
在這裡插入圖片描述
pygame.event.clear()
在這裡插入圖片描述
Pygame事件佇列
在這裡插入圖片描述
pygame.event.set_blocked(type or typelist)
•控制哪些型別事件不允許被儲存到事件佇列中

pygame.event.set_allowed(type or typelist)
•控制哪些型別事件允許被儲存到事件佇列中

pygame.event.get_blocked(type)
•測試某個事件型別是否被事件佇列所禁止
•如果事件型別被禁止,則返回True,否則返回False

pygame.event.post(Event)
•產生一個事件,並將其放入事件佇列
•一般用於放置使用者自定義事件(pygame.USEREVENT)
•也可以用於放置系統定義事件(如滑鼠或鍵盤等),給定引數

pygame.event.Event(type, dict)
•建立一個給定型別的事件
•其中,事件的屬性和值採用字典型別複製,屬性名採用字串形式
•如果建立已有事件,屬性需要一致

import pygame, sys

pygame.init()
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("pygame事件處理")
fps = 12
fclok = pygame.time.Clock()
num = 10
while True:
    uevent = pygame.event.Event(pygame.KEYDOWN, {"unicode": 123, "key": pygame.K_SPACE, "mod": pygame.KMOD_ALT})
    pygame.event.post(uevent)
    num = num + 1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.unicode == "":
                print("[KEYDOWN{}]".format(num), "#", event.key, event.mod)
            else:
                print("[KEYDOW{}]".format(num), event.unicode, event.key, event.mod)
        pygame.display.update()
        fclok.tick(fps)

Pygame色彩與繪圖機制
色彩表達

Color類用於表達色彩,使用RGB或RGBA色彩模式,A可選
Color類可以用色彩名字、RGBA值、HTML色彩格式等方式定義
pygame.Color
Color(name) 例如:Color(“grey”)
Color(r,g,b,a) 例如:Color(190, 190, 190, 255)
Color(rgbvalue) 例如:Color("#BEBEBEFF")
• RGB色彩模式之外增加了第四維度:alpha通道
• alpha通道表示不透明度,取值0-255,預設255
• alpha通道值越大,不透明度越高,255表示不透明

pygame.Color類

pygame.Color.r 獲得Color類的紅色值r
pygame.Color.g 獲得Color類的綠色值g
pygame.Color.b 獲得Color類的藍色值b
pygame.Color.a 獲得Color類的不透明度值a
pygame.Color.normalize 將RGBA各通道值歸一到0-1之間
壁球小遊戲(色彩型)
在這裡插入圖片描述

import pygame, sys
def RGBChanel(a):
    return (0 if a<0 else (255 if a>255 else int(a)))
pygame.init()
vInfo = pygame.display.Info()
# 設定螢幕顯示為全屏
# size=width,height=vInfo.current_w,vInfo.current_h
# screen=pygame.display.set_mode(size,pygame.FULLSCREEN)
size = width, height = 600, 400
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
# 設定螢幕可改變
pygame.display.set_caption("小球碰撞")
color = 60, 63, 65
screen.fill(color)
ball = pygame.image.load("pic/ball.png")
ball_rect = ball.get_rect();
icon = pygame.image.load("pic/dragon.png")
pygame.display.set_icon(icon)

speed = [1, 1]
fps = 300
fClock = pygame.time.Clock()
still = False
bgcolor=pygame.Color("black")
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else ((abs(speed[1]) - 1) * int(abs(speed[1]) / speed[1]))
            elif event.key == pygame.K_ESCAPE:
                sys.exit()
        elif event.type == pygame.VIDEORESIZE:  # 當螢幕進行拉縮時
            size = width, height = event.size[0], event.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                still = True
        elif event.type == pygame.MOUSEBUTTONUP:
            still = False
            if event.button == 1:
                ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
        elif event.type == pygame.MOUSEMOTION:
            if event.buttons[0] == 1:
                ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
    if pygame.display.get_active() and not still:  # 當螢幕活躍時(未縮小為最小化)
        ball_rect = ball_rect.move(speed[0], speed[1])
    if (ball_rect.left < 0 or ball_rect.right > width):
        speed[0] = -speed[0]
        if ball_rect.right > width and ball_rect.right + speed[0] > ball_rect.right:
            speed[0] = -speed[0]
    if (ball_rect.top < 0 or ball_rect.bottom >height):
        speed[1] = -speed[1]
        if ball_rect.bottom > height and ball_rect.bottom + speed[1] > ball_rect.bottom:
            speed[1] = -speed[1]
    bgcolor.r=RGBChanel(ball_rect.left*255/width)
    bgcolor.g=RGBChanel(ball_rect.top*255/width)
    bgcolor.b=RGBChanel(min(speed[0],speed[1])*255/max(speed[0],speed[1],1))
    screen.fill(bgcolor)
    screen.blit(ball, ball_rect)
    pygame.display.update()
    fClock.tick(fps)

圖形繪製

向螢幕上繪製一些簡單的圖形,如直線、圓形、橢圓等。任何一個圖形繪製後,會返回一個矩形Rect類表示該形狀
在這裡插入圖片描述

Rect類

表達一個矩形區域的類,用於儲存座標和長度資訊。Pygame利用Rect類來操作圖形/影像等元素
在這裡插入圖片描述
Rect類提供瞭如下屬性,返回一個數值或一個代表座標的元組
在這裡插入圖片描述
Rect類提供瞭如下方法,用來操作Rect類
在這裡插入圖片描述

圖形繪製

pygame.draw
在這裡插入圖片描述

import pygame,sys
from math import pi
pygame.init()
size=width,height=600,400
screen=pygame.display.set_mode(size)
pygame.display.set_caption("pygame圖形繪製")
WHITE=pygame.Color('white')
GREEN=pygame.Color('green')
GOLD=(255,251,0)
RED=pygame.Color('red')
elrect=pygame.draw.ellipse(screen,GREEN,(50,50,500,300),3)
c1rect=pygame.draw.circle(screen,GOLD,(200,180),30,5)
c2rect=pygame.draw.circle(screen,GOLD,(400,180),30)
r1rect = pygame.draw.rect(screen, RED, (170,130, 60, 10), 3)
r2rect = pygame.draw.rect(screen, RED, (370,130, 60, 10))
plist = [(295,170), (285,250), (260,280), (340,280), (315,250), (305,170)]
#l1rect = pygame.draw.lines(screen, GOLD, True, plist, 2)
al1rect = pygame.draw.aalines(screen, GOLD, True, plist, 2)
a1rect = pygame.draw.arc(screen, RED, (200,220,200,100), 1.4*pi, 1.9*pi, 3)
while True:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            sys.exit()
        pygame.display.update()






在這裡插入圖片描述

Pygame文字繪製機制

文字繪製

pygame.freetype
向螢幕上繪製特定字型的文字。文字不能直接print() ,而是用畫素根據字型點陣圖繪製
pygame.freetype是繪製文字的增強方法,建議使用必須額外增加import引用,如下:
在這裡插入圖片描述
系統中的字型
在這裡插入圖片描述

文字繪製機制簡介

在這裡插入圖片描述
Font類
在這裡插入圖片描述
Font類的繪製方法(1)
在這裡插入圖片描述
在這裡插入圖片描述

import pygame, sys
import pygame.freetype
import pygame, sys

pygame.init()  # 對Pygame內部各功能模組進行初始化建立及變數設定,預設呼叫
screen = pygame.display.set_mode((600, 400))  # 初始化顯示視窗,第一個引數size是一個二值元組,分別表示視窗的寬度和高度
pygame.display.set_caption("Pygame遊戲繪製")  # 設定顯示視窗標題設定顯示視窗的標題內容,引數title是一個字串型別
GOLD = (255, 251, 0)
f1=pygame.freetype.Font("c://Windows//Fonts//msyh.ttc",36)  # 微軟雅黑
# f1rect=f1.render_to(screen,(200,160),"知行合一",fgcolor=GOLD,size=50)
f1 = pygame.freetype.Font('C://Windows//Fonts//msyh.ttc', 50)  # 微軟雅黑
f1surf, f1rect = f1.render("世界和平", fgcolor=GOLD, size=30)
f1rect.left=200
f1rect.top=160
while True:  # 無限迴圈,直到Python執行時退出結束  # 微軟雅黑
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()  # 用於退出結束遊戲並退出
    screen.blit(f1surf, f1rect)
    pygame.display.update()  # 重新整理窗體

Font類的繪製方法(2)

在這裡插入圖片描述

Pygame繪圖機制原理精髓

理解Pygame的兩個重要型別
在這裡插入圖片描述
主圖層
在這裡插入圖片描述
文字壁球小遊戲

import pygame, sys
import pygame.freetype

pygame.init()
size = width, height = 600, 400
screen = pygame.display.set_mode(size)
pygame.display.set_caption("小球碰撞")
color = 60, 63, 65
screen.fill(color)

speed = [1, 1]
GOLD = (255, 251, 0)
RED = pygame.Color('red')
pos = [230, 100]
text = "世界和平"
f1 = pygame.freetype.Font("C://Windows//Fonts//msyh.ttc", 36)
# f1rect=f1.render_to(screen,pos,text,fgcolor=GOLD,size=60)
f1surf, f1rect = f1.render("世界和平", fgcolor=GOLD, size=50)
fps = 300

fclock = pygame.time.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.VIDEORESIZE:
            width = event.size[0]
            height = event.size[1]
            size = width, height
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)

    if pos[0] <= 0 or pos[0] + f1rect.width >= width:
        speed[0] = -speed[0]
    if pos[1] <= 0 or pos[1] + f1rect.height >= height:
        speed[1] = -speed[1]
    pos[0] = pos[0] + speed[0]
    pos[1] = pos[1] + speed[1]
    screen.fill(color)

    # f1rect=f1.render_to(screen,pos,text,fgcolor=GOLD,size=50)
    f1surf, f1rect = f1.render(text, fgcolor=GOLD, size=50)
    screen.blit(f1surf, (pos[0], pos[1]))
    pygame.display.update()
    fclock.tick(fps)