本系列博客介绍以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
运行一下,如今超人能够很是满意的绕着地球旋转了,效果看起来仍是不错的。
下个博客咱们将一块儿开发一个小游戏,巩固以前学到的知识。