1. 绘制图像的三个步骤
介绍一下怎么样把图像文件中保存的图像数据, 绘制到游戏的屏幕上,先明确一下什么是图像文件以及要使用图像文件,第1步应该做什么, 在之前准备项目的时候,在项目中添加了一个images 目录,
在这个目录下保存有大量的图像文件,
这些图像文件默认情况下是保存在磁盘上的.
在开发时,如果想要使用这些图像文件中保存的数据,第1步应该把图像文件中保存的数据加载到内存,譬如现在做一个双击的动作,双击之后可以在屏幕右侧看到图像的内容,
之所以能够看到图像的内容,是因为双击的动作,会把图像文件中保存的数据加载到内存, 加载之后,才能够看到图像的内容.
刚刚确认了一下图像文件,默认情况下都是保存在磁盘上的,
在开发中如果想要使用图像文件中保存的数据,第1步就应该把图像文件中保存的数据加载到内存,这个概念明确之后。接下来看一下在使用pygame开发的时候,怎么样把图像文件中保存的数据绘制到游戏的窗口中.
要想实现这个目标啊,只需要编写三句代码,
第1句代码,让pygame的image 模块来调用一下load()方法, load()有加载的意思,传入一个要加载的图像文件路径,
这个方法就会返回一个加载之后的图像数据.load()方法,负责加载图像的数据.
那加载之后呢,第2步就使用 游戏屏幕 对象调用一个blit 方法,
blit 方法需要传入两个参数,第一个参数就是刚刚加载得到的图像数据, 第2个参数呢,可以是一个元组,也可以是一个矩形对象,
总而言之,第2个参数就是指定在游戏屏幕的什么位置来绘制这个图像,第三步, 绘制之后还不够,如果希望在屏幕上看到最终的绘制结果,还需要调用一个非常重要的方法,需要调用一下pygame.display 这个模块提供的一个update方法,
update有更新的意思,只有更新了整个屏幕,才能够在屏幕上看到最终的绘制结果,这样就是使用pygame来绘制一张图像的三个步骤。
那接下来就针对三个步骤来做一个简单的演练,在这个演练中就加载一下背景图像,加载之后把背景图片绘制在(0, 0) 的位置,也就是游戏窗口的左上角,绘制完成调用一下update() 方法来看到最终的显示结果.
演练目标明确之后,粘贴之后, 就把光标放在第8行,
要绘制图像,应该在无限循环的上方来绘制,先编写一下注释,目标明确之后,以注释的方式来明确一下绘制背景图像的三个步骤,
现在123, 3个步骤写完,就先来使用image 模块的load 方法加载一下图像.
要想使用pygame的image模块,选中load 方法,然后在方法的小括号内部传入要加载的图像名称,先敲一个点表示当前目录,
图片加载完成.
同时注意load 方法是有返回结果的, 所以在前面定义一个变量来接收一下,
图像数据加载完成,可以让屏幕对象bg 来调用blit 方法,就让screen这个对象调用blit 的方法,把刚刚加载的背景图像传递进来,
然后呢,跟一个逗号, 在逗号后面跟上一个元组,这个元组呢就指定一下在游戏窗口的什么位置来绘制这个背景图像.(0, 0) 是在屏幕的左上角来绘制背景图,现在绘制的动作也做完.
update 方法是display模块提供的,那现在就用pygame点找到display,直接敲一个update,好1 23, 三个步骤写完, 来运行一下程序,
现在屏幕上已经可以看到背景图片,
现在把绘制背景图像的位置改一下,x值写一个100,y值同样也写一个100,
现在再运行一下,
再演示一下,最后一句代码.如果让屏幕执行完绘制动作之后,不调用update方法就没有办法在屏幕上看到最终的绘制结果.
现在就把update的方法注释一下,再来运行一下程序,
游戏启动了,这个黑黑的窗口上并没有任何的内容.这样就是不调用update方法看到的一个结果.
把这个方法的注释打开,重新运行一下程序.
然后选择停止所有.
选择停止之后,
重新运行一下程序, 程序启动了, 并且可以看到背景图片的绘制,
2. 绘制英雄和透明图像
接下来再针对绘制的图像在做一个案例演练,来把英雄的图像画在屏幕上,通过这个案例演练,首先要强化一下上一小节学习的加载图像以及绘制图像的代码,并且介绍一下什么叫做透明图像.
明确了演练目标之后,来看一下演练步骤,在这一小节,首先从me1.png 这个图像文件来加载一下飞机的数据,当把飞机的数据加载完成之后,就把英雄的飞机挂在屏幕的水平方向,200的位置,垂直方向500的位置.
当让screen对象调用了blit 方法,
完成了绘制之后,还需要调一下display模块提供的update的方法,
只有调用了update 方法,才能够在屏幕上看到最终绘制的结果, 也就是英雄的飞机.
做一下演练,首先来找到image的文件夹,
来看看在这一小节要绘制的英雄图片,
找到并双击,
这些小格子就是图片的透明区域,至于透明区域会看到什么效果,等下编写完代码,就可以一目了然了.
再找到我们上一小节完成的代码, CTRL a选中, CTRL c复制,然后切换到一个全新的空白文件CTRL v粘贴进来.
把光标放在第16行, 注意要想绘制飞机的图片,就应该在无限循环的上方来编写代码.
先增加一个单行注释, 来明确一下这一小节要绘制的目标英雄的飞机,目标明确之后,要想在屏幕上绘制一个图像,第1步应该加载图像,
那现在先给英雄起个名字hero,然后呢使用pygame 模块来调用load 方法,load 方法的参数就是要加载图像文件的完整路径,
那现在写一个点, 表示当前路径,
然后呢跟上images表示图像目录下的,
然后呢再跟上me1.png 这个图像文件名,
图像数据加载完成,接下来让screen 这个对象来调用blit 方法,
blit 方法可以接收两参数,第1个参数就是刚刚加载的图像数据,就把hero传递过来,
第2个参数是一个元组,这个元组的第1个数值是水平方向的坐标,元组的第2个数值是垂直方向的坐标,现在指定一个200和500,
让屏幕对象执行了blit 方法之后, 还需要调用一下display这个模块提供的update方法.
调一下update方法,
好三句代码写完, 先来运行一下程序,看看英雄的飞机能不能出现在屏幕上.
英雄的飞机已经出现在屏幕上,
下方是一个背景图片,上方有一个英雄的小飞机.
现在英雄的飞机已经出现了,如果希望英雄出现的位置向左偏一点,应该修改第1个数值,第1个数值表示水平方向的x值.
那现在就把程序停止一下,
然后把水平的200修改成150,现在再运行一下程序, 英雄的小飞机位置发生变化了,
观察一下英雄飞机下方有一个陨石,但是陨石并没有被小飞机全部遮挡住,有一半的陨石能够透露出来, 这个就是透明图片的效果.
再看一下要加载的图像,在图像上有一些灰色的小格子,这些灰色的小格子就是透明区域,
在显示图像时,如果下方有其他的图像内容,这些透明的小格子, 就会把其他的图像内容通过小格子透露出来, 同样也可以让我们肉眼看到.这个就是透明图像的概念.
所谓透明图像,就是png 这种格式是支持透明的,在显示的时候,如果下方已经有内容就会透过透明区域显示出来,这样呢就可以看到两张图片完全融合的效果.
譬如小飞机叠在陨石上,这个就是透明图片的效果.
3.update 方法的作用
介绍一下display模块提供的update方法的作用,要想绘制图像, 就让screen 对象来调一下blit 方法.
要想看到绘制的结果,就调用一下display模块提供的update的方法.
一个绘制图像,一个更新显示,那现在试想一下,假设开发的游戏,需要绘制非常非常多的图像.
那么在编写代码的时候,如果每绘制一张图像就调用一次update 方法,每绘制一张图像就更新一下显示,如果这样编写代码就显得太繁琐了.
有更简单的方法.
其实在开发时可以让screen 对象完成了所有blit 方法之后,即完成所有绘制方法之后,再最后统一调一次update的方法,同样可以在屏幕上看到最终的绘制结果.
验证一下,先把绘制背景的注释删除一下,这样呢可以让代码看起来更加直观一些,
大家看在第3行初始化了一下pygame,
第6行调用set_mode方法,创建了一个游戏的屏幕,
然后呢,连续的三句代码是非常类似的,
先来加载图像,
然后绘制图像,
紧接着更新显示,
更新显示可以在屏幕对象完成所有绘制动作之后统一调用.
增加一个注释, 可以在所有绘制工作完成之后统一调用update方法,
update 方法会把screen 对象中最终的绘制结果统一输出到屏幕上来.
既然如此,第11行这个更新显示的代码就可以注释掉了.
把第11行代码注释一下, 来运行一下程序,
看看背景图像和英雄的飞机能不能被最终的显示在屏幕上来,现在运行一下程序,背景图片也好,英雄的飞机也好,都能够显示在屏幕上,
这个就是在开发时,可以先让screen 对象顺序调用blit 方法,按照程序的需求,在不同的位置绘制不同的图像,当所有绘制工作完成之后,最后统一调一次update的方法.
这种方式编写代码, 就不用在每次绘制完图像都调用一次更新.
只需要在最后统一调一次update的方法就可以.
为什么update 方法只需要用一次就可以了呢?之前介绍set_mode方法的时候,提到过,暂时可以把screen 对象理解成游戏的屏幕,其实啊,screen 对象本质上是一个内存中的屏幕的数据对象,
它只是一个数据对象,可以把screen 对象理解成一个油画的画布,画一个示意图,现在这个红色的框框,就是screen 这个对象,
可以在screen 对象上调用blit 方法,就可以完成图像的绘制工作.
先来画一个英雄的飞机,
画完英雄的飞机之后,如果还希望画一个敌人的飞机,那么就可以使用blit 方法, 再画一个敌人的飞机,
如果游戏中的图像比较多,非常有可能出现几张图像之间彼此覆盖彼此重叠的情况,
但是不管有多少张图像,彼此覆盖和重叠,最终看到的结果只是一个而已.
让screen 对象调用blit 方法,可以在内存中进行虚拟的绘制,把需要展现的所有图像全部绘制完成,紧接着呢,就调一下update方法, update 方法会把screen 对象中绘制的最终结果,一次性的绘制到游戏屏幕上.
screen 对象只是一个内存中的数据对象,而最终要在屏幕上看到的结果是通过update 方法把screen 对象的最终结果,一次性的画在屏幕上, 这种方式可以提高屏幕的绘制效率, 可以提高屏幕每次更新的效率,从而呢可以提高游戏的流畅度.