本系列博客介绍以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:

  1. from datetime import datetime, date, time

使用datetime.today()函数可以获取当前的日期和事件:

  1. today = datetime.today()

today变量里面包含了很多信息,如果我们直接将其打印出来:

  1. print today
  2. 2015-11-24 17:00:23.162000

这样很不方便我们使用,所以需要对其进行进一步的拆分:

  1. today.date()
  2. datetime.date(2015, 11, 24)
  3.  
  4. today.time()
  5. datetime.time(17, 0, 23, 162000)

如果只需要当前时间而不需要当前日期的话,可以直接使用datetime.today().time()函数:

  1. Time = datetime.today().time()

Time有很多属性,Time.hour Time.minute Time.second  Time.microsecond,看名字就知道是什么了。

二、pygame中加载位图、绘制位图

通常,游戏中需要加载大量的位图,pygame中自带了一些类和函数可以帮助我们轻松的搞定位图加载和绘制。

  1. 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等多种图片格式)。

现在让我们来加载一个位图试试:

  1. space = pygame.image.load("space.png").convert_alpha()

convert_alpha()方法会使用透明的方法绘制前景对象,因此在加载一个有alpha通道的素材时(比如PNG TGA),需要使用convert_alpha()方法,当然普通的图片也是可以使用这个方法的,用了也不会有什么副作用。

2.绘制位图

Surface对象有一个名为blit()的方法,它可以绘制位图

  1. 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中的位图。星空已经加载上了,下面加载并绘制一个地球。

为了让地球可以在夜空的中间绘制,还得多写几段代码。

  1. planet = pygame.image.load("earth.png").convert_alpha()
    #获取位图的宽和高
  2. width,height = planet.get_size()
    #在屏幕的中间绘制地球
  3. screen.blit(planet, (400-width/2,300-height/2))

get_size()可以获取位图的宽度和高度,然后利用他们就可以在确定在屏幕的中间绘制地球了。

最后该绘制我们的超人了。添加代码:

  1. superman = pygame.image.load("superman.png").convert_alpha()
  2. screen.blit(superman,(30,30))

但是超人图像看起来好大啊,画面比例有点不协调,还需要把超人缩小一点。

这里使用pygame.transform 这个模块可以满足我们的需求,这个模块包含了比如缩放,翻转等一些非常有用的函数。

pygame.transform.scale()这是一个快速的缩放函数,可以快速缩放一个图像,但是如果你试过以后就会发现他并不是那么的理想,像素看起来会很密集,有点怪怪的。

幸好它有一个名为pygame.transform.smoothscale()的变体,这个函数通过复杂的计算产生比较平滑的图像,当然它的运行耗时大于快速缩放函数。

  1. superman = pygame.transform.smoothscale(superman,(width//2,height//2))

好了,现在我们该考虑如何让超人绕着地球旋转了。

  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. #X property
  10. def getx(self): return self.__x
  11. def setx(self, x): self.__x = x
  12. x = property(getx, setx)
  13.  
  14. #Y property
  15. def gety(self): return self.__y
  16. def sety(self, y): self.__y = y
  17. y = property(gety, sety)
  18.  
  19. def wrap_angle(angle):
  20. return angle % 360
  21.  
  22. radius = 250
  23. angle = 0.0
  24. pos = Point(0,0)
  25. old_pos = Point(0,0)
  26.  
  27. pygame.init()
  28. screen = pygame.display.set_mode((800,600))
  29. pygame.display.set_caption("星空")
  30. font = pygame.font.Font(None, 18)
  31.  
  32. space = pygame.image.load("space.png").convert_alpha()
  33. planet = pygame.image.load("earth.png").convert_alpha()
  34. superman = pygame.image.load("superman.png").convert_alpha()
  35. width,height = superman.get_size()
  36. superman = pygame.transform.smoothscale(superman,(width//2,height//2))
  37.  
  38. while True:
  39. for event in pygame.event.get():
  40. if event.type == QUIT:
  41. pygame.quit()
  42. sys.exit()
  43. keys = pygame.key.get_pressed()
  44. if keys[K_ESCAPE]:
  45. sys.exit()
  46.  
  47. screen.blit(space, (0,0))
  48.  
  49. angle = wrap_angle(angle - 0.1)
  50. pos.x = math.sin( math.radians(angle) ) * radius
  51. pos.y = math.cos( math.radians(angle) ) * radius
  52.  
  53. #获取位图的宽和高
  54. width,height = planet.get_size()
  55. #在屏幕的中间绘制地球
  56. screen.blit(planet, (400-width/2,300-height/2))
  57. width,height = superman.get_size()
  58. screen.blit(superman,(400+pos.x-width//2,300+pos.y-height//2))
  59. 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. while True:
  37. for event in pygame.event.get():
  38. if event.type == QUIT:
  39. pygame.quit()
  40. sys.exit()
  41. keys = pygame.key.get_pressed()
  42. if keys[K_ESCAPE]:
  43. sys.exit()
  44.  
  45. screen.blit(space, (0,0))
  46.  
  47. angle = wrap_angle(angle - 0.1)
  48. pos.x = math.sin( math.radians(angle) ) * radius
  49. pos.y = math.cos( math.radians(angle) ) * radius
  50.  
  51. #获取位图的宽和高
  52. width,height = planet.get_size()
  53. #在屏幕的中间绘制地球
  54. screen.blit(planet, (400-width/2,300-height/2))
  55. #旋转超人
  56. delta_x = ( pos.x - old_pos.x )
  57. delta_y = ( pos.y - old_pos.y )
  58. rangle = math.atan2(delta_y, delta_x)
  59. rangled = wrap_angle( -math.degrees(rangle) )
  60. superman_rotate = pygame.transform.rotate(superman, rangled)
  61. #绘制超人
  62. width,height = superman_rotate.get_size()
  63. screen.blit(superman_rotate,(400+pos.x-width//2,300+pos.y-height//2))
  64. pygame.display.update()
  65.  
  66. old_pos.x = pos.x
  67. old_pos.y = pos.y

运行一下,现在超人可以非常满意的绕着地球旋转了,效果看起来还是不错的。

下个博客我们将一起开发一个小游戏,巩固之前学到的知识。

【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。的更多相关文章

  1. 【python游戏编程之旅】第二篇--pygame中的IO、数据

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇中,我们介绍了pygame的入门操作http://www.cnblogs.com/msxh/p/49 ...

  2. 【python游戏编程04--加载位图与常用的数学函数】

    一.pygame中常用的数学函数 首先介绍两个角度和弧度转换的函数 math.degress()和math.radians()用法很简单,只要将数值传进去然后接受返回值就可以 math.cos(ang ...

  3. 【python游戏编程之旅】第九篇---嗷大喵快跑小游戏开发实例

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 前几期博客我们一起学习了,pygame中的冲突检测技术以及一些常用的数据结构. 这次我们来一起做一个简单的酷 ...

  4. 【python游戏编程之旅】第一篇---初识pygame

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础 ...

  5. 【python游戏编程之旅】第五篇---嗷大喵爱吃鱼小游戏开发实例

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 我们一同在前几期的博客中已经学到了很多pygame的基本知识了,现在该做个小游戏实战一下了. 前几期博客链接 ...

  6. 【python游戏编程之旅】第三篇---pygame事件与设备轮询

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇博客中,我们学习了pygame中的IO.数据http://www.cnblogs.com/msxh/ ...

  7. 少儿编程:python趣味编程第二课,如何在pygame中写文字

    python趣味编程第二课:本文仅针对8-16岁的青少年,所以流程是按如何去教好中小学生走的,并不适合成人找工作学习,因为进度也是按照青少年走的 大家好,我是C大叔,上一篇文章已经跟大家介绍了一款开发 ...

  8. 【python游戏编程之旅】第七篇---pygame中的冲突检测技术

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中的Sprite模块和如何加载动画:http://www.cnblogs ...

  9. 【python游戏编程之旅】第六篇---pygame中的Sprite(精灵)模块和加载动画

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 直到现在我们已经学了很多pygame基础知识了,从这篇博客开始我们将会学习pygame中高级部分,更多和精灵 ...

随机推荐

  1. Poj 1061 青蛙的约会(扩展GCD)

    题目链接:http://poj.org/problem?id=1061 解题报告:两只青蛙在地球的同一条纬度线上,选取一个点位坐标轴原点,所以现在他们都在同一个首尾相连的坐标轴上,那么他们现在的位置分 ...

  2. win7安装apache或者php 5.7缺少vcruntime140.dll的问题

    1.确定win7 系统是否是win7 sp1 版本.因为Visual C++ Redistributable for Visual Studio 2015 需要win7的sp1包的支持才能安装成功! ...

  3. The Perfect Stall (incomplete)

    恩,一看就知道是一道二分图最大匹配的题. 感动得发现自己不会做..果然我是太弱了.学校里真是麻烦死,根本没有时间好吗. (NOIP)会不会感动地滚粗啊? 然后稍微看看,恩,匈牙利算法. 真是感动得落泪 ...

  4. HashMap实现原理分析(详解)

    1. HashMap的数据结构 http://blog.csdn.net/gaopu12345/article/details/50831631   ??看一下 数据结构中有数组和链表来实现对数据的存 ...

  5. windows和linux下mysql的重启命令

    在 Windows 下: 开始->运行->cmd启动:net start mysql停止:net stop mysql 无重启,必须先停止再启动!!! 在LINUX 下: 启动:/etc/ ...

  6. Linux系统排查3——I/O篇

    当磁盘无法写入的时候,一般有以下可能: 文件系统只读 磁盘已满 I节点使用完 一. 遇到只读的文件系统 文件系统自动设置成只读可能是系统自我保护的一种机制,因此需要实现弄清究竟是什么原因造成了文件系统 ...

  7. CSS对字体单位的总结

    国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢? PX特点 1. IE无法调整那些使用px作为单位的字体大小: 2. 国外的大部分网站能够调整的 ...

  8. Razor入门

    一.Razor简介Razor不是编程语言,它是一种允许您向网页中嵌入基于服务器的代码的标记语法,也就是可以在html网页中嵌入的写入C#代码,Razor在VS中有自动提示,使用起来会方便一点,如下代码 ...

  9. Hadoop 1.1.2 eclipse plugin 编译 win7 集成

    Windows平台上使用ANT编译Hadoop Eclipse Plugin 一.准备工作:   1.安装JDK 下载页面:http://www.oracle.com/technetwork/java ...

  10. Android概述