博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。
阅读量:6186 次
发布时间:2019-06-21

本文共 6729 字,大约阅读时间需要 22 分钟。

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

 

 额,其实我想用一个绕着地球飞的超人小程序,来讲解一下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, pygamefrom 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 % 360radius = 250angle = 0.0pos = 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.__x10     def setx(self, x): self.__x = x11     x = property(getx, setx)12 13     def gety(self): return self.__y14     def sety(self, y): self.__y = y15     y = property(gety, sety)16 17 def wrap_angle(angle):18     return angle % 36019 20 radius = 25021 angle = 0.022 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) ) * radius50     pos.y = math.cos( math.radians(angle) ) * radius51     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.x68     old_pos.y = pos.y

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

 

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

你可能感兴趣的文章
我的友情链接
查看>>
写点和硬件有关的
查看>>
硬盘/u盘能识别不能打开问题分析
查看>>
Windows服务的手动添加和删除方法
查看>>
AndroidAnnnotations注入框架的工作原理(二)
查看>>
用fail2ban阻止密码尝试***
查看>>
/etc/resolv.conf文件被复写的解决
查看>>
Windows抓127.0.0.1的包
查看>>
Maven 使用profiles 时 值无法替换问题
查看>>
Edraw Office Viewer component教程(三):将MS Word、Excel、PowerPoint嵌入到WPF应用程序中...
查看>>
NIO-Selector类详解
查看>>
开启HTTPS全网加密新时代 亚洲诚信与中科三方签约战略合作
查看>>
运行JAR包 提示没有主清单属性解决办法
查看>>
2018年第三季欧洲DDoS攻击量急剧增加
查看>>
人体运动轨迹的人工智能动画模拟
查看>>
spring,orm 题目
查看>>
Java 回调函数
查看>>
2018/02/13
查看>>
echarts(二)
查看>>
Hibernate映射文件结构
查看>>