设为首页 收藏本站
查看: 901|回复: 0

[经验分享] 【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。

[复制链接]

尚未签到

发表于 2015-11-30 14:41:31 | 显示全部楼层 |阅读模式
  本系列博客介绍以python+pygame库进行小游戏的开发。有写的不对之处还望各位海涵。
  
  在上一篇博客中,我们学习了pygame事件与设备轮询。http://www.cnblogs.com/msxh/p/4979380.html
  这次我们来一起了解一下如何在pygame中加载位图,以及pygame中一些常用的数学函数。
  
  
  一、pygame中常用的数学函数
  首先介绍两个角度和弧度转换的函数:
  math.degress()和math.radians(),用法很简单,只要将数值传进去然后接收返回值就可以了。
  math.cos(angle),math.sin(angle),这里的angle使用的是弧度表示的,因此需要先使用math.radians(),将角度转换为弧度然后再传参。
  
  如果要获取当前时间,我们需要使用datetime模块。
  首先从datetime导入date和time:



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,看名字就知道是什么了。
  
  二、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()
DSC0000.png
  
  额,其实我想用一个绕着地球飞的超人小程序,来讲解一下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))
DSC0001.png
  但是超人图像看起来好大啊,画面比例有点不协调,还需要把超人缩小一点。
  这里使用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之间的角度。
DSC0002.png
  运行看一下,超人可以绕着地球旋转了,但是看起来比较僵硬,最好让他自己也能旋转,指向他移动的方向,以便让画面柔和一些。
  这里我们需要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
  运行一下,现在超人可以非常满意的绕着地球旋转了,效果看起来还是不错的。
DSC0003.png
  
  下个博客我们将一起开发一个小游戏,巩固之前学到的知识。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145468-1-1.html 上篇帖子: Python:IOError: image file is truncated 的解决办法 下篇帖子: Python的正则表达式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表