python游戲開發之色彩與繪圖
pygame色彩機制
-
使用pygame.Color類表示色彩
Color類使用RGB或者RGBA(A代表透明度,可選)色彩模式。
可以使用色彩名字:
色彩的RGB或RBGA值:Color(190, 190, 190, 255)
色彩的名字:Color("grey")
RGB即紅綠藍三原色,范圍從0~255之間。
A為α通道,參考值為0~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 可以使得所有的參數歸一化一個0~1之間的浮點數 -
修改小球的背景顏色
需求:通過小球運動的位置不同,分別改變其背景中R,G,B三原色的值。
import sys, pygame
pygame.init()
size = width, height = (600, 400)
speed = [1, 1]
bgcolor = pygame.Color("black")
fps = 300
still = False
icon = pygame.image.load("滑稽球1.jpg")
pygame.display.set_icon(icon)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("壁球小游戲鼠標版")
ball = pygame.image.load("滑稽球1.jpg")
ballrect = ball.get_rect()
fclock = pygame.time.Clock()
def RGBChannel(a):
return 0 if a<0 else(255 if a>255 else(int(a)))
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]))
elif event.key == pygame.K_ESCAPE:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
still = True
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
still = False
ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0] == 1:
ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.right > width and ballrect.right + speed[0] > ballrect.right:
# 因為對於鼠標的控制而言,我們是設置的鼠標位置為矩形框的左上角,所以只考慮右下方突破邊界的情況
speed[0] = -speed[0]
elif ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
if ballrect.bottom > height and ballrect.bottom + speed[1] > ballrect.bottom:
speed[1] = -speed[1]
if pygame.display.get_active():
if not still:
ballrect = ballrect.move(speed[0], speed[1])
bgcolor.r = RGBChannel(ballrect.left/width*255)
bgcolor.g = RGBChannel(ballrect.top/height*255)
bgcolor.b = RGBChannel(min(speed[0], speed[1])/max(speed[0], speed[1], 1))
screen.fill(bgcolor)
screen.blit(ball, ballrect)
pygame.display.update()
fclock.tick(fps)
pygame的圖形繪制機制
所有圖形繪制之后,歐pygame都會使用一個rect類(矩形類)來表示一個范圍。
pygame.rect
表示一個矩形范圍,因而有四個基本的參數值:(left, top)矩形左上角的坐標,width,height寬度與高度,通過這四個值唯一確定矩形的位置。
同樣rect類也提供了一些方法例如:rect.move(),rect.copy()等等
pygame.draw
pygame 通過pygame.draw來繪制不同的圖形,包括矩形、圓形、橢圓等等。
- pygame.draw.rect(surface, color, rect, width=0)
surface 表示的是繪制在什么區域,一般而言就是當前的屏幕screen
color表示矩形的顏色
rect表示矩形的區域,通過一個四元素的元組確定即左上角坐標與寬、高
width表示的是矩形的線條寬度,默認為0即矩形全部為color顏色,如果不為0,那么就會繪制一個空心區域
import sys, pygame
pygame.init()
size = width, height = (600, 400)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("pygame圖形繪制")
gold = 255, 251, 0
red = pygame.Color("red")
rect1 = pygame.draw.rect(screen, gold, (100, 100, 200, 100), 5)
rect2 = pygame.draw.rect(screen, red, (210, 210, 200, 100))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
pygame.display.update()
以上是在pygame中繪制矩形的示例代碼。
2. pygame.draw.polygon(surface, color, pointlist, width=0)
多邊形需要給一個pointlist即一個頂點坐標的列表。
-
pygame.draw.circle(surface, color, pos, radicus, width=0)
圓形通過一個圓心坐標和半徑來繪制。 -
pygame.draw.ellipse(surface, color, rect, width=0)
橢圓形的定義方式是通過一個外切矩形來確定。
rect表示一個矩形區域 -
pygame.draw.arch(surface, color, rect, start_angle, stop_angle, width=0)
這里繪制的是一個橢圓形的部分。
同樣通過一個外切矩形來確定唯一的橢圓。
start_angle來表示起始角度;
stop_angle來表示終止角度;仍然使用的是笛卡爾坐標系。 -
pygame.draw.line(surface, color, start_pos, end_pos, width=1)
start_pos表示的是起始坐標;
end_pos 表示的是終點坐標;
默認的線條寬度是1。 -
pygame.draw.lines(suraface, color, closed, pointlist, width=1)
closed 如果為True會把起始和終止點連接使得多線形成閉合圖形。 -
pygame.draw.aaline(surface, color, start_pos, end_pos, blend=1)
直線繪制需要跨越像素,放大一定程度必然會出現鋸齒。
pygame提供了繪制無鋸齒線的方法,注意這里的“無鋸齒”只是盡可能地減少鋸齒的出現,而不可能真的全面消除鋸齒的存在。
blend:不為0時,與線條所在背景顏色混合。 -
pygame.draw.aalines(surface, color, pointlist, blend=1)
繪制無鋸齒多線。
pygame文字繪制機制
通過使用pygame.freetype來把文字繪制到屏幕上。
無論是中文還是其他語言,文字都是通過點陣圖的方式繪制到屏幕上面。
freetype是增強方法,必須要額外進行import pygame.freetype才能使用。
系統字體
對於windows系統,通常把字體存儲在C:\windows\fonts目錄下。
字體通常是*.ttc或者*.ttf格式的文件。
使用字體
首先需要創建一個字體對象。
pygame.freetype.Font來創建字體對象;
pygame.freetype.render()/render_to()來輸出字體。
- pygame.freetype.Font(File, size=0)
File表示字體文件存儲的位置,建議使用絕對路徑
size表示的字體的大小。 - Font.render_to(surf, dest, text, fgcolor = None, bgcolor = None, rotation, size)
返回的是一個rect 類型。
surf:繪制字體的平面
dest:繪制字體的在屏幕的位置
text:字體的內容,字符串
fgcolor:字體顏色
bgcolor: 背景顏色
rotation:逆時針旋轉的角度
size:字體的大小,如果不另外設置會使用之前的Font的大小。
import sys, pygame
import pygame.freetype
pygame.init()
size = width, height = (600, 400)
screen = pygame.display.set_mode(size)
f1 = pygame.freetype.Font("C://windows//Fonts//msyh.ttc", 36)
rect = f1.render_to(screen, (200, 160), "世界和平", )
- Font.render(text, fgcolor=None, bgcolor=None, rotation, size)
相比於render_to()它少了前兩個參數。
它會返回一個rect對象與一個surf對象,來表示把文字繪制到一個新的屏幕上。
pygame繪圖機制的精髓
- surface類
表示的是繪圖平面,繪圖層、圖層;
表示的是圖形或文字圖像最終繪制的位置。
圖層是可以和主圖層的並列存在的,但是只有主圖層的圖像會被顯示在屏幕上。 - rect類
表示一個矩形區域,但是它只對應一個主圖層上的區域。
它是表示主圖層上某一個區域的位置信息或指針;
可以指定某個圖層繪制在特定區域上。 - 主圖層
由pygame.display.set_mode()生成的surface對象就是主圖層。
如果希望把其他圖層的東西繪制到主圖層上就要使用blit方法,例如:
screen.blit(ball, ballrect)
這就是把小球的圖像ball的圖層將其繪制到ballrect的區域上。
壁球小游戲文字型
需求:把壁球替換為一段文字,可以進行移動;
關鍵要素:文字的繪制與刷新。
可以使用render_to()方法或者render()方法來繪制文字。
import sys, pygame
import pygame.freetype
pygame.init()
size = width, height = 600, 400
speed = [1, 1]
Black = 0, 0, 0
Gold = 255, 251, 0
pos = [230, 160]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("pygame壁球小游戲文字型")
fps = 300
fclock = pygame.time.Clock()
f1 = pygame.freetype.Font("C://windows//Fonts//msyh.ttc", 36)
f1rect = f1.render_to(screen, pos, "世界和平", fgcolor=Gold, size=50)
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] - 1 if speed[0] > 0 else 0
elif event.key == pygame.K_RIGHT:
speed[0] = speed[0] + 1
elif event.key == pygame.K_UP:
speed[1] = speed[1] + 1
elif event.key == pygame.K_DOWN:
speed[1] = speed[1] - 1 if speed[1] > 0 else 0
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(Black)
f1rect = f1.render_to(screen, pos, "世界和平", fgcolor=Gold, size=50)
pygame.display.update()
fclock.tick(fps)
以上內容來自北京理工大學嵩天老師及其團隊的《Python游戲開發入門》課程第四周的內容。
非常感謝嵩天老師及其團隊給我們帶來這樣優質的課程。