本系列博客介紹以python+pygame庫進行小遊戲的開發。有寫的不對之處還望各位海涵。html
在上一篇博客中,咱們學習了pygame事件與設備輪詢。http://www.cnblogs.com/msxh/p/4979380.htmlpython
此次咱們來一塊兒瞭解一下如何在pygame中加載位圖,以及pygame中一些經常使用的數學函數。小程序
本篇博客中素材連接:傳送門 (時間過久了,後補的資源,超人素材找不到了,用飛船替代了。)dom
1、pygame中經常使用的數學函數函數
首先介紹兩個角度和弧度轉換的函數:學習
math.degress()和math.radians(),用法很簡單,只要將數值傳進去而後接收返回值就能夠了。ui
math.cos(angle),math.sin(angle),這裏的angle使用的是弧度表示的,所以須要先使用math.radians(),將角度轉換爲弧度而後再傳參。spa
若是要獲取當前時間,咱們須要使用datetime模塊。code
首先從datetime導入date和time:orm
from datetime import datetime, date, time
使用datetime.today()函數能夠獲取當前的日期和事件:
today = datetime.today()
today變量裏面包含了不少信息,若是咱們直接將其打印出來:
print today 2015-11-24 17:00:23.162000
這樣很不方便咱們使用,因此須要對其進行進一步的拆分:
today.date() datetime.date(2015, 11, 24) today.time() datetime.time(17, 0, 23, 162000)
若是隻須要當前時間而不須要當前日期的話,能夠直接使用datetime.today().time()函數:
Time = datetime.today().time()
Time有不少屬性,Time.hour Time.minute Time.second Time.microsecond,看名字就知道是什麼了。
2、pygame中加載位圖、繪製位圖
一般,遊戲中須要加載大量的位圖,pygame中自帶了一些類和函數能夠幫助咱們輕鬆的搞定位圖加載和繪製。
screen = pygame.display.set_mode
上面的代碼,咱們在前幾期的博客中已經使用過不少次了,實際上pygame.display.set_mode()這個函數會返回一個Surface對象,他是位圖的一種。
實例中須要的一些素材能夠到這裏下載:http://yunpan.cn/cLI5cDKQU8sYG 訪問密碼 c83a
1.加載位圖
在pygame中可使用pygame.image.load()函數來加載位圖。(支持jpg,png,gif,bmp,pcx,tif,tga等多種圖片格式)。
如今讓咱們來加載一個位圖試試:
space = pygame.image.load("space.png").convert_alpha()
convert_alpha()方法會使用透明的方法繪製前景對象,所以在加載一個有alpha通道的素材時(好比PNG TGA),須要使用convert_alpha()方法,固然普通的圖片也是可使用這個方法的,用了也不會有什麼反作用。
2.繪製位圖
Surface對象有一個名爲blit()的方法,它能夠繪製位圖
screen.blit(space, (0,0))
第一個參數是加載完成的位圖,第二個參數是繪製的起始座標。咱們來看一下完整的程序和效果:
1 import sys, random, math, pygame 2 from pygame.locals import * 3 4 pygame.init() 5 screen = pygame.display.set_mode((800,600)) 6 pygame.display.set_caption("星空") 7 font = pygame.font.Font(None, 18) 8 9 space = pygame.image.load("space.png").convert_alpha() 10 11 while True: 12 for event in pygame.event.get(): 13 if event.type == QUIT: 14 pygame.quit() 15 sys.exit() 16 keys = pygame.key.get_pressed() 17 if keys[K_ESCAPE]: 18 sys.exit() 19 screen.blit(space, (0,0)) 20 21 pygame.display.update()
額,其實我想用一個繞着地球飛的超人小程序,來說解一下pygame中的位圖。星空已經加載上了,下面加載並繪製一個地球。
爲了讓地球能夠在夜空的中間繪製,還得多寫幾段代碼。
planet = pygame.image.load("earth.png").convert_alpha()
#獲取位圖的寬和高 width,height = planet.get_size()
#在屏幕的中間繪製地球 screen.blit(planet, (400-width/2,300-height/2))
get_size()能夠獲取位圖的寬度和高度,而後利用他們就能夠在肯定在屏幕的中間繪製地球了。
最後該繪製咱們的超人了。添加代碼:
superman = pygame.image.load("superman.png").convert_alpha() screen.blit(superman,(30,30))
可是超人圖像看起來好大啊,畫面比例有點不協調,還須要把超人縮小一點。
這裏使用pygame.transform 這個模塊能夠知足咱們的需求,這個模塊包含了好比縮放,翻轉等一些很是有用的函數。
pygame.transform.scale()這是一個快速的縮放函數,能夠快速縮放一個圖像,可是若是你試過之後就會發現他並非那麼的理想,像素看起來會很密集,有點怪怪的。
幸虧它有一個名爲pygame.transform.smoothscale()的變體,這個函數經過複雜的計算產生比較平滑的圖像,固然它的運行耗時大於快速縮放函數。
superman = pygame.transform.smoothscale(superman,(width//2,height//2))
好了,如今咱們該考慮如何讓超人繞着地球旋轉了。
import sys, random, math, pygame from pygame.locals import * class Point(object): def __init__(self, x, y): self.__x = x self.__y = y #X property def getx(self): return self.__x def setx(self, x): self.__x = x x = property(getx, setx) #Y property def gety(self): return self.__y def sety(self, y): self.__y = y y = property(gety, sety) def wrap_angle(angle): return angle % 360 radius = 250 angle = 0.0 pos = Point(0,0) old_pos = Point(0,0) pygame.init() screen = pygame.display.set_mode((800,600)) pygame.display.set_caption("星空") font = pygame.font.Font(None, 18) space = pygame.image.load("space.png").convert_alpha() planet = pygame.image.load("earth.png").convert_alpha() superman = pygame.image.load("superman.png").convert_alpha() width,height = superman.get_size() superman = pygame.transform.smoothscale(superman,(width//2,height//2)) while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() keys = pygame.key.get_pressed() if keys[K_ESCAPE]: sys.exit() screen.blit(space, (0,0)) angle = wrap_angle(angle - 0.1) pos.x = math.sin( math.radians(angle) ) * radius pos.y = math.cos( math.radians(angle) ) * radius #獲取位圖的寬和高 width,height = planet.get_size() #在屏幕的中間繪製地球 screen.blit(planet, (400-width/2,300-height/2)) width,height = superman.get_size() screen.blit(superman,(400+pos.x-width//2,300+pos.y-height//2)) pygame.display.update()
在這裏,定義了一個point類,方便咱們表示圖像的座標,而後分別實現了set 和get方法,很簡單的,看代碼就能夠理解了。
而後又定義了一個wrap_angle(angle)函數。他會返回一個0~360之間的角度。
運行看一下,超人能夠繞着地球旋轉了,可是看起來比較僵硬,最好讓他本身也能旋轉,指向他移動的方向,以便讓畫面柔和一些。
這裏咱們須要math.atan2()這個函數,它用於計算反正切函數,須要傳遞兩個參數:delta_x,delta_y。delta_x,delta_y表示兩個座標x,y之間的距離
工做流程是這樣的:先記錄飛船的最近位置,而後使用當前位置和最近位置調用atan2函數,而後再給atan2函數的返回值加上180.
咱們還須要一個函數是pygame.transform.rotate(),沒錯,它能夠用來旋轉位圖,須要傳兩個參數:圖像,旋轉角度。
1 import sys, random, math, pygame 2 from pygame.locals import * 3 4 class Point(object): 5 def __init__(self, x, y): 6 self.__x = x 7 self.__y = y 8 9 def getx(self): return self.__x 10 def setx(self, x): self.__x = x 11 x = property(getx, setx) 12 13 def gety(self): return self.__y 14 def sety(self, y): self.__y = y 15 y = property(gety, sety) 16 17 def wrap_angle(angle): 18 return angle % 360 19 20 radius = 250 21 angle = 0.0 22 pos = Point(0,0) 23 old_pos = Point(0,0) 24 25 pygame.init() 26 screen = pygame.display.set_mode((800,600)) 27 pygame.display.set_caption("星空") 28 font = pygame.font.Font(None, 18) 29 30 space = pygame.image.load("space.png").convert_alpha() 31 planet = pygame.image.load("earth.png").convert_alpha() 32 superman = pygame.image.load("superman.png").convert_alpha() 33 width,height = superman.get_size() 34 superman = pygame.transform.smoothscale(superman,(width//2,height//2)) 35 36 37 while True: 38 for event in pygame.event.get(): 39 if event.type == QUIT: 40 pygame.quit() 41 sys.exit() 42 keys = pygame.key.get_pressed() 43 if keys[K_ESCAPE]: 44 sys.exit() 45 46 screen.blit(space, (0,0)) 47 48 angle = wrap_angle(angle - 0.1) 49 pos.x = math.sin( math.radians(angle) ) * radius 50 pos.y = math.cos( math.radians(angle) ) * radius 51 52 #獲取位圖的寬和高 53 width,height = planet.get_size() 54 #在屏幕的中間繪製地球 55 screen.blit(planet, (400-width/2,300-height/2)) 56 #旋轉超人 57 delta_x = ( pos.x - old_pos.x ) 58 delta_y = ( pos.y - old_pos.y ) 59 rangle = math.atan2(delta_y, delta_x) 60 rangled = wrap_angle( -math.degrees(rangle) ) 61 superman_rotate = pygame.transform.rotate(superman, rangled) 62 #繪製超人 63 width,height = superman_rotate.get_size() 64 screen.blit(superman_rotate,(400+pos.x-width//2,300+pos.y-height//2)) 65 pygame.display.update() 66 67 old_pos.x = pos.x 68 old_pos.y = pos.y
運行一下,如今超人能夠很是滿意的繞着地球旋轉了,效果看起來仍是不錯的。
下個博客咱們將一塊兒開發一個小遊戲,鞏固以前學到的知識。