随笔 - 97, 文章 - 22, 评论 - 81, 引用 - 0
数据加载中……

Pygame游戏开发 之一

Pygame游戏开发之一

初涉红尘

       本人是个游戏爱好者,同样是个游戏开发爱好者,最近开始学习PygamePygame 跨平台的 Python模块(包括Win32UnixMacAndroid等等),主要包含图像和声音,专为电子游戏设计。所有需要的游戏功能和理念都完全简化为游戏逻辑本身,这样就大大提高了开发效率。

       我学Pygame之前对Python可以说是一无所知,所以大致浏览了一下《Python核心编程》,但是学一门语言不能光靠看书,必须亲身实践。可以说是一边做游戏,一边学习的过程,通过做游戏来更好地理解这门语言。Pygame的文档可以在以下这个链接中找到:http://www.pygame.org/docs/ 基本游戏中需要用到的一些操作它都给你封装好了,非常方便。

       做游戏之前让我们先把环境配好,到Python的官网把Python相关的软件下载下来(http://www.python.org/download),因为它是跨平台的,所以会有很多不同平台的版本,我下了一个Windows版的python-2.5.msi,之后执行该文件安装Python,一般是安装在C:盘下。安装完毕后,进入 开始菜单->Python 2.5->IDLE,就是PythonIDE(集成开发环境)了。然后是安装Pygame模块,到http://www.pygame.org/download.shtml下载对应平台的pygame,安装即可。

       接下来就开始我们的“Pygame游戏制作之旅”,和大多数的游戏制作一样,程序的框架都是大同小异的,一般就是:

初始化 - (图像、声音)

主循环 -

事件处理(鼠标、键盘)

逻辑层

渲染层

释放资源

Pygame的初始化非常方便,首先调用pygame.init(),这个函数为所有导入的pygame模块进行初始化,如果初始化失败,不会引发任何的异常。

Pygame中用于显示的是一个叫Surface的东西,Surface可以理解成一个表面,就像画画的白纸一样,任何东西都可以在上面绘制。每个Surface都有它固定的分辨率(可以理解成白纸的大小,即宽和高)以及像素格式(pixel format)。

调用pygame.Surface可以创建一个图像对象。起初Surface会被清空成全黑,唯一需要的参数是它的大小。其它还有几个默认的参数:

pygame.Surface((width, height), flags=0, depth=0, masks=None): return Surface
pygame.Surface((width, height), flags=0, Surface): return Surface

像素格式可以通过传入位深depth或者一张存在的Surface来决定,flags参数是表面的一组位或标志,可以传入以下参数的任意组合:

HWSURFACE, 在显存中创建图像
SRCALPHA,
像素格式有alpha值,即透明度

Surface可以有许多额外的属性,像alpha层,关键色,源矩形裁剪等。这些功能主要影响Surface是如何粘贴到其它表面的。这里的粘贴不是一般意义上的粘贴,因为它不止是原图拷贝,有可能是进行像素的与运算、或运算等等,我们称这种操作为blit(位块传输),blit会尽可能使用硬件加速,如果实在不行,它们会使用具有很好优化手段的软件传输方法。

Pygame中支持三种类型的透明处理:关键色(colorkeys),表面alpha(surface alphas),像素alpha(pixel alphas)。表面alpha能够和关键色混合使用,但是如果用了像素alpha,就不能和其它两种进行混合使用了。关键色使得某一种颜色成为透明,任何和这个颜色一样的像素将不会被绘制出来。表面alpha是一个单一的值,它决定了整张图片的透明度。这个值为255表示不透明,0则表示完全透明。

像素alpha储存了所有像素的alpha值,也就是透明度。在表面上的像素访问是允许的,但是对于一个游戏来说,这个速度实在是太慢了-_-|||(不是一般的慢啊试过你就知道了)。像素的访问和修改可以通过get_at() set_at()函数,但是如果需要批量操作,这种方法是不可取的,实在要做,可以利用pygame.surfarray 模块,它将Surface看做是很大的高维数组,操作起来相当快。任何函数如果要直接访问一个Surface的某个像素数据的话需要将这个Surface锁定,锁定和解锁可以调用lock()unlock()方法。

Surface有一定了解之后,我们就可以来看display了,pygame.displayPygame中用于屏幕显示的模块,一旦创建了一个display,你就可以把它当成是常规的Surface来使用了。Pygame在进行显示的时候是采用双缓冲机制的,其实它内部有两个Surface,每次要绘制时是在后备缓冲上进行绘制,当所有东西都绘制完毕后需要手动调用pygame.display.flip()函数,这个函数的作用就是将后备缓冲和前台缓冲进行一次交换,如此一来,先前绘制的东西也就自然而然得显示到屏幕上来了(也可以调用pygame.display.update(),它是对前一个翻页函数的优化,可以传入一些矩形,只在传入的矩形进行更新操作)。我们利用以下函数对屏幕的Surface进行初始化:

pygame.display.set_mode(resolution=(0,0), flags=0, depth=0) : return Surface

resolution表示需要创建的窗口的大小,即分辨率。flags表示一些位或标志,一般有以下几个:

pygame.FULLSCREEN    创建一个全屏的显示模式

pygame.DOUBLEBUF     建议和 HWSURFACE OPENGL组合

pygame.HWSURFACE     全屏下硬件加速

pygame.OPENGL           创建一个opengl 的渲染显示模式

pygame.RESIZABLE      显示窗口大小可变

pygame.NOFRAME       显示窗口没有边框

depth则表示当前Surface的位深。

screen = pygame.display.set_mode(SCREENRECT.size,  pygame.FULLSCREEN)

我们可以采用以上语句创建一个用于全屏显示的Surface对象,并且返回给全局变量screen。接下来我们从文件中读取一张图片并且将它显示到屏幕上来,pygame.image模块是用于图像的传输的,它包含了一些读取和保存图片的函数,读取图片可以采用pygame.image.load

。它的原型是:

pygame.image.load(filename) return Surface

从文件中载入一个图像,传入的是文件名。Pygame将会自动决定图像的类型(gif 或者 bmp)并且从数据中创建一个新的Surface对象。返回的Surface对象将会包含和文件中的原图一样的颜色格式、关键色和alpha通道。你可以返回Surface.convert()来创建一个拷贝,它在屏幕上绘制的时候效率更高。

       对于alpha通道,像png图像可以在载入后使用convert_alpha()方法使得图像的像素具有透明度。Pygame不总是支持所有的图像文件格式,但是它肯定支持的是标准的BMP文件,可以通过pygame.image.get_extended来检测它是否支持其他图像文件,例如png

       我们可以通过定义一个load_image函数来将图像的载入封装起来,以后用的时候就会方便许多了。

def load_image(file) :

    file = os.path.join('data', file)

    try:

        surface = pygame.image.load(file)

    except pygame.error:

        raise SystemExit, 'Can not load image %s' % pygame.get_error()

return surface.convert_alpha()

 

以上是将一个data文件夹下的名为file的图像文件读取并且返回一个Surface的过程。

调用如下:

myImage = load_image(‘hero.png’)

现在我们拥有两个Surface:一个是screen,表示屏幕显示设备;另外一个则是由图像文件中创建的myImage,如果想要将myImage显示到屏幕上来,只需要进行如下的操作:

       screen.blit(myImage, pos, srcRect, 0)

第一个参数是源Surface对象,pos则是传送到screen的左上角的位置,是一个二元组,表示xy坐标, srcRect表示的是一个矩形四元组,是将myImagesrcRect这个矩形的区域传送到screen上来,最后一个参数则是对两张Surface的一个混合的标志,BLEND_ADD表示将两者的对应点的颜色像素值相加,BLEND_SUB表示相减等等。到此为止,myImage还不能被显示到屏幕上来,因为blit的过程只是将myImage这个Surface传送到后备缓冲中,我们还需要调用pygame.display.flip()进行翻页。如此一来,就可以轻松得实现图像文件在屏幕的贴图了。

       大致了解了图像的显示之后让我们来看下框架代码的编写,C++开头一般都会包含一些头文件,Python也类似,PygamePython的一个模块,但是如果不进行导入是不能用它的东西的,Python中用import进行模块的导入:

import pygame, sys, os.path

sysos.path都是系统模块,当然,自己写的.py文件也可以作为一个模块来用于导入。

必要模块导入之后需要检测当前系统下是否支持除标准BMP以外的图像文件,可以调用pygame.image.get_extended()函数来检测,如果返回False则只能使用标准BMP文件了。

Python中有一个特殊的变量__name__,如果当前程序是被当成一个模块被导入的,那么它的值是模块名;如果是作为程序执行的,则它的值是’__main__’,所以我们需要对这个变量进行判断,像这样:

if __name__ == '__main__' : Go()

以上的Go函数就好比是C语言中的main()函数,不同的是它可以以任意的名字命名。所有的初始化工作可以放在Go函数的开头,我用Initialize函数将它封装起来了。

def Go():

    Initialize()

    while True :

        for event in pygame.event.get():

            if event.type == pygame.KEYDOWN :

                if event.key == K_ESCAPE :

                    pygame.quit()

                    sys.exit(0)

            elif event.type == pygame.QUIT :

                pygame.quit()

                sys.exit(0)

        keystatus       =  pygame.key.get_pressed()

              logical()

              render()

        pygame.display.update()

上面这段代码是Pygame的游戏框架,对图像之类的初始化工作被放在Initialize函数里,之后是游戏的主循环,循环内部首先进行的是事件处理,这里的事件是用的Pygame中的pygame.event模块,Pygame对事件的组织是通过事件队列的,pygame.event.get()将得到事件队列中所有的事件,并且将他们从事件队列中移除。每个事件有一个事件类型event.type,例如KEYDOWN表示键盘上的键按下,KEYUP表示键抬起等等。

       logical()render()分别是游戏的逻辑层和渲染层,可以在逻辑层中添加一些控件,并且设置它们的位置以及大小,然后渲染层则负责将这些东西显示到屏幕上来。(未完待续)

       以上内容均为原创 转载请注明出处


 

1-1

posted on 2011-04-23 20:39 英雄哪里出来 阅读(11882) 评论(1)  编辑 收藏 引用 所属分类: Pygame

评论

# re: Pygame游戏开发 之一  回复  更多评论   

持续关注
2011-04-24 12:56 | zhaoyg

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理