AntDZ说 :网上关于pygame的中文文档不多,在下面的时间里我会去搜集一些放在这里。
Pygame is a python wrapper for SDL, written by Pete Shinners. What this means is that, using pygame, you can write games or other multimedia applications in Python that will run unaltered on any of SDL's supported platforms (Windows, Unix, Mac, beOS and others).
Pygame是一个由Pete Shinners编写的SDL的Python封装。这就意味着,使用pygame,你可以写出可以不作修改就可以在任何支持SDL的平台(Windows, Unix, Mac, BeOS,等等)上运行的游戏或者多媒体程序。
Pygame may be easy to learn, but the world of graphics programming can be pretty confusing to the newcomer. I wrote this to try to distill the practical knowledge I've gained over the past year or so of working with pygame, and it's predecessor, pySDL. I've tried to rank these suggestions in order of importance, but how relevent any particular hint is will depend on your own background and the details of your project.
Pygame不难学,但是图形编程的世界却会让新手糊涂。我撰写此文的目的,在于抽取出过去几年来在pygame和它的先驱,pySDL上的工作经验中获得的实用知识。我已经尝试着要把这些建议按照它们的
重要程度来分等级,但是它(指“重要程度”)却又与你的背景知识和你的工作细节相关。
1.Get comfortable working in Python.
1.熟练使用Python。
The most important thing is to feel confident using python. Learning something as potentially complicated as graphics programming will be a real chore if you're also unfamiliar with the language you're using. Write a few sizable non-graphical programs in python - parse some text files, write a guessing game or a journal-entry program or something. Get comfortable with string and list manipulation - know how to split, slice and combine strings and lists. Know how import works - try writing a program that is spread across several source files. Write your own functions, and practice manipulating numbers and characters; know how to convert between the two. Get to the point where the syntax for using lists and dictionaries is second-nature - you don't want to have to run to the documentation every time you need to slice a list or sort a set of keys. Resist the temptation to run to a mailing list, comp.lang.python, or irc when you run into trouble. Instead, fire up the interpreter and play with the problem for a few hours. Print out the Python 2.0 Quick Reference and keep it by your computer.
最 重要的事情是要有信心使用Python。如果你不熟悉你所使用的语言,那在学习实际上很复杂的东西比如说图形编程,这将会成为一个累赘。用python写 几个有一定规模的非图形程序——解析某些文本文件,写一个猜数游戏或者一个流水分录程序,或者别的什么。习惯于字符串和列表操作——学会怎么样分割,分 片,以及合并字符串或者列表。知道import是怎么样工作的——试着一个由数个源文件组成的程序。编写你自己的函数,并且练习操作数字和字符;知道怎么 样在它俩之间转换。直到使用列表和字典已经成为第二本能——你不用每次分片一个列表或者排序一个关键值集合的时候都求助于文档。当你遇到挫折时,抵制向邮 件列表,comp.lang.python,或者irc求救的诱惑。打开解释器,坐下来跟问题干上几个小时。把《Python 2.0 快速指南》打印出来,并且放到电脑边上。
This may sound incredibly dull, but the confidence you'll gain through your familiarity with python will work wonders when it comes time to write your game. The time you spend making python code second-nature will be nothing compared to the time you'll save when you're writing real code.
听起来难以置信的无聊,但是在你熟悉python的过程中所获得的益处却会在编写你自己的游戏时体现出来。跟你以后编写实战代码时省下的时候相比,熟悉python所花的时候不值一提。
2. Recognize which parts of pygame you really need.
2. 识别pygame的哪些部分是你所需要的。
Looking at the jumble of classes at the top of the pygame Documentation index may be confusing. The important thing is to realize that you can do a great deal with only a tiny subset of functions. Many classes you'll probably never use - in a year, I haven't touched the Channel, Joystick, cursors, Userrect, surfarray or version functions.
看着pygame文档顶部那些杂乱的类要让人眼花。重要的是认识到只利用这些功能的一个小子集就可以帮助你完成许多事。许多类你压根就不会用到——在一年 里,我没有接触到过Channel,Joystick,cursors,Userrect,surfarray或者版本函数。
Know what a surface is
3.知道什么是surface
The most important part of pygame is the surface. Just think of a surface as a blank piece of paper. You can do a lot of things with a surface - you can draw lines on it, fill parts of it with color, copy images to and from it, and set or read individual pixel colors on it. A surface can be any size (within reason) and you can have as many of them as you like (again, within reason). One surface is special - the one you create with pygame.display.set_mode(). This 'display surface' represents the screen; whatever you do to it will appear on the user's screen. You can only have one of these - that's an SDL limitation, not a pygame one.
Pygame的最重要部分是surface。就把surface想当成一张白纸吧。你要用对一个surface做许多的事——你可以在它上面画线,给它的 部分填充颜色,把图像拷进去或者拷出来,设置或者读取它上面的某个单独的像素的颜色值。一个surface可以是任何大小(可以理解)并且你要多少就有多 少(也可以理解)。有一个surface是特别的——你用pygame.display.set_mode()创建的那一个。这个display surface代表了屏幕;你对它做的任何事情都会呈现在用户屏幕上。你只能有一个这玩意——这是SDL的一个限制,而不是pygame的。
So how do you create surfaces? As mentioned above, you create the special 'display surface' with pygame.display.set_mode(). You can create a surface that contains an image by using image.load(), or you can make a surface that contains text with font.render(). You can even create a surface that contains nothing at all with Surface().
但是你怎么创建surface呢?正如上所说,可以用pygame.display_set_mode()来创建特殊的display surface。你可以用image.load()来创建一个包含了图像的surface,或者你可以用font.render()来创建一个包含了文字 的surface。甚至你可以用一个Surface()来创建一个什么都没有的surface。
Most of the surface functions are not critical. Just learn blit(), fill(), set_at() and get_at(), and you'll be fine.
大部分的surface函数都不是至关紧要的。只要学习blit(),fill(),set_at()和get_at()就够用了。
4.Use surface.convert()
4. 使用surface.convert()
When I first read the documentation for surface.convert(), I didn't think it was something I had to worry about. "I only use pngs, therefore everything I do will be in the same format. So I don't need convert()". It turns out I was very, very wrong.
当我第一次阅读surface.convert()的文档时,我并没有意识到这是我要注意的。“我只使用png格式,既然我用的都是同一个格式,所以我不需要convert()”。它证明了我是非常,非常错的。
The 'format' that convert() refers to isn't the file format (ie png, jpeg, gif), it's what's called the 'pixel format'. This refers to the particular way that a surface records individual colors in a specific pixel. If the surface format isn't the same as the display format, SDL will have to convert it on-the-fly for every blit - a fairly time-consuming process. Don't worry too much about the explanation; just note that convert() is necessary if you want to get any kind of speed out of your blits.
Convert()所指的“格式”并非指文件格式工(如png,jpeg,gif),它是所谓的“像素格式”。它代表了一个surface记录一个特定像 素的颜色的方法。如果surface格式跟显示格式不一样,那SDL就要在每次blit的时候去转化它——这是个相当费时的过程。不用关心解释,只要注意 到如果想在blit之外获得速度,那你就需要convert()。
How do you use convert? Just call it after creating a surface with the image.load() function. Instead of just doing:
那怎么转换呢?只需在用image.load()函数创建了一个surface后调用它。不使用:
surface = pygame.image.load('foo.png')
Do:
用:
surface = pygame.image.load('foo.png').convert()
It's that easy. You just need to call it once per surface, when you load an image off the disk. You'll be pleased with the results; I see about a 6x increase in blitting speed by calling convert().
相当简单,你只需要当从硬盘中加载图像的时候,对每个surface调用它一次。你会对结果满意的;我发现使用convert()时,blit的速度有了6倍的提高。
The only times you don't want to use convert() is when you really need to have absolute control over an image's internal format - say you were writing an image conversion program or something, and you needed to ensure that the output file had the same pixel format as the input file. If you're writing a game, you need speed. Use convert().
你不需要使用convert()的唯一情况,就是当你真的想对图像的内部格式有绝对的控制权的时候——比如说你正在写一个图像转换程序或者其它的,但是你要保证输出文件和输入文件有相同的像素格式。如果你在写一个游戏,你需要速度,就用convert()。
5. Dirty rect animation
5. 脏矩形动画
The most common cause of inadequate frame rates in pygame programs results from misunderstanding the pygame.display.update() function. With pygame, merely drawing something to the display surface doesn't cause it to appear on the screen - you need to call pygame.display.update(). There are three ways of calling this function:
Pygame程序中导致帧率不足的的最常见原因就是误用了pygame.display.update()函数。在pygame中,仅仅把东西画到 display surface中并不会让它显示在屏幕上——你要调用pygame.display.update()。有三种方法去调用它:
pygame.display.update() - This updates the whole window (or the whole screen for fullscreen displays).
pygame.display.update()——更新整个窗口(或者在全屏显示下是整个屏幕)。
pygame.display.flip() - This does the same thing, and will also do the right thing if you're using doublebuffered hardware acceleration, which you're not, so on to...
Pygame.display.flip()——这个干了相同的活,只是如果你同时使用了双缓冲硬件加速时它也会帮你该做的事,但如果你没有,那当什么都没发生过……
pygame.display.update(a rectangle or some list of rectangles) - This updates just the rectangular areas of the screen you specify.
Pygame.display.update(一个矩形或者矩形列表) ——这个只更新屏幕上你指定矩形区域。
Most people new to graphics programming use the first option - they update the whole screen every frame. The problem is that this is unacceptably slow for most people. Calling update() takes 35 milliseconds on my machine, which doesn't sound like much, until you realize that 1000 / 35 = 28 frames per second maximum. And that's with no game logic, no blits, no input, no AI, nothing. I'm just sitting there updating the screen, and 28 fps is my maximum framerate. Ugh.
很多图形编程的新丁使用第一个选择——他们在每一帧里更新整个屏幕。问题是这样做对大多数人来说慢得不能忍受。在我的电脑上调用update()花费35 毫秒,听起来不多,除非你看到一秒最多有1000/35=28帧,并且还是没有任何游戏逻辑,没有blit,没有输入,没有人工智能,什么都没有。我只是 坐在凳子上去更新屏幕,而28fps就是我的最高帧率。啊!
The solution is called 'dirty rect animation'. Instead of updating the whole screen every frame, only the parts that changed since the last frame are updated. I do this by keeping track of those rectangles in a list, then calling update(the_dirty_rectangles) at the end of the frame. In detail for a moving sprite, I:
解决方法叫做“脏矩形动画”。替换每帧更新整个屏幕,而只更新自上一帧已经改变过的部分。我是通过用一个列表来跟踪这些矩形,然后在帧结束时调用update(the_dirty_rectangles)来实现的。比如说对于一个移动中的精灵,我:
1.Blit a piece of the background over the sprite's current location, erasing it.
1. 在背景上blit精灵所在的位置,擦掉它。
2.Append the sprite's current location rectangle to a list called dirty_rects.
2. 把精灵的当前区域矩形加到一个叫dirty_rects的列表中去。
3.Move the sprite.
3. 移动这个精灵。
4.Draw the sprite at it's new location.
4. 在新的区域画这个精灵。
5.Append the sprite's new location to my dirty_rects list.
5. 把精灵的新区域加到我的dirty_rects中去。
6.Call display.update(dirty_rects)
6. 调用display.update(dirty_rects)
The difference in speed is astonishing. Consider that Solarwolf has dozens of constantly moving sprites updating smoothly, and still has enough time left over to display a parallax starfield in the background, and update that too.
速度的差异让人吃惊。想想Solarwolf有大量持续移动的精灵亦平滑更新,并且还有时间去显示一个视差粒子效果,并且也被更新。
There are two cases where this technique just won't work. The first is where the whole window or screen really is being updated every frame - think of a smooth-scrolling engine like an overhead real-time strategy game or a side-scroller. So what do you do in this case? Well, the short answer is - don't write this kind of game in pygame. The long answer is to scroll in steps of several pixels at a time; don't try to make scrolling perfectly smooth. Your player will appreciate a game that scrolls quickly, and won't notice the background jumping along too much.
有两种情况是用不上这种技术的。其一是当整个窗口或者屏幕的确需要在每一帧被更新——考虑一下一个平滑滚动的引擎,像一个实时战略游戏或者一个边滚动条。 那在这种情况下你应该用什么?呃,简单的答案就是不要在pygame中写这种游戏。而详细的答案是一个步骤里滚动数个像素,试要企图做出绝对平滑的滚动。 玩你游戏的人会喜欢一个滚动得快的游戏,而不太会注意到背景的跳跃。
A final note - not every game requires high framerates. A strategic wargame could easily get by on just a few updates per second - in this case, the added complexity of dirty rect animation may not be necessary.
最后一点——不是所有的游戏都需要高帧率。一个策略战争游戏在一秒钟内只需要更新几次就足够了——在这种情况下,脏矩形动画带来的复杂性是多余的。
6.There is NO rule six.
6. 没有第六条军规。
Hardware surfaces are more trouble than they're worth.
7. 硬件surface弊大于利。
If you've been looking at the various flags you can use with pygame.display.set_mode(), you may have thought like this: "Hey, HWSURFACE! Well, I want that - who doesn't like hardware acceleration. Ooo... DOUBLEBUF; well, that sounds fast, I guess I want that too!". It's not your fault; we've been trained by years of 3-d gaming to believe that hardware acceleration is good, and software rendering is slow.
如 果你已经看过可以用在pygame.display.set_mode()中可以使用的众多标志值时,你可能会这样想:“嘿,HWSURFACE!嗯,我 需要它——谁不喜欢硬件加速?噢……DOUBLEBUF;嗯,听起来挺快的,我看我也需要它!”这不是你的错,我们经受过多年的3D游戏训练,已经默认了 把硬件加速是优秀的,而软件加速是缓慢的。
Unfortunately, hardware rendering comes with a long list of drawbacks:
很不幸,硬件渲染天生就有一长串的缺陷:
It complicates per-pixel access. If you have a hardware surface, you need to Lock the surface before writing or reading individual pixel values on it. If you don't, Bad Things Happen. Then you need to quickly Unlock the surface again, before the OS gets all confused and starts to panic. Most of this process is automated for you in pygame, but it's something else to take into account.
它复杂化了每个像素的访问。如果你有一个硬件surface,你必须在读写单独的像素值的时候锁定屏幕。如果你不这样做,就会坏了大事。接着你又要赶在系统被搞蒙并且开始抱怨之前马上解锁。这些过程都是pygame自动为你做的,但是它值得注意。
8.Don't get distracted by side issues.
8. 不要纠缠于细枝末节。
Sometimes, new game programmers spend too much time worrying about issues that aren't really critical to their game's success. The desire to get secondary issues 'right' is understandable, but early in the process of creating a game, you cannot even know what the important questions are, let alone what answers you should choose. The result can be a lot of needless prevarication.
有时候,游戏编程新人在某些对游戏的成功并非紧要的地方花了太多时间。把将要的要素做“对”是可理解的,但是在创作游戏的早期,你并不知道哪些是重要的问题,更不要说你应该选择的答案了。结果就是带来一堆的借口。
For example, consider the question of how to organize your graphics files. Should each frame have its own graphics file, or each sprite? Perhaps all the graphics should be zipped up into one archive? A great deal of time has been wasted on a lot of projects, asking these questions on mailing lists, debating the answers, profiling, etc, etc. This is a secondary issue; any time spent discussing it should have been spent coding the actual game.
举例说,思考一下怎么样组织你的图形文件的问题。是每一帧有它自己的图像文件好呢,还是每个精灵都有?或者把所有的图像都打包成一个压缩包?许多项目的许 多时间被浪费在在邮件列表提问,争论问题的答案,比较,等等等等。这些都是次要矛盾;花在争论上的时间原本都应该用到编码实战游戏中去。
The insight here is that it is far better to have a 'pretty good' solution that was actually implemented, than a perfect solution that you never got around to writing.
这里的主旨就是说,一个已经实现了的“恰当地好”的解决方案,要远远优于一个没有开始动手的完美的解决方案。
9.Rects are your friends.
9. Rect是你的好朋友。
Pete Shinners' wrapper may have cool alpha effects and fast blitting speeds, but I have to admit my favorite part of pygame is the lowly Rect class. A rect is simply a rectangle - defined only by the position of its top left corner, its width, and its height. Many pygame functions take rects as arguments, and they also take 'rectstyles', a sequence that has the same values as a rect. So if I need a rectangle that defines the area between 10, 20 and 40, 50, I can do any of the following:
Pete Shinners的封闭可能有很酷的alpha效果,和快速的blit速度,但是我不得不说我最喜欢pygame部分是底层的Rect类。一个rect就 是一个矩形——由它左上角的位置,它的宽度,它的高度定义。Pygame的许多函数都用rect作参数,也接受“矩形形式”,一个跟rect有相同值的序 列。因此,如果我需要一个位于10, 20和40, 50之间的区域时,我可以做以下几个中的一个:
rect = pygame.Rect(10, 20, 30, 30)
rect = pygame.Rect((10, 20, 30, 30))
rect = pygame.Rect((10, 20), (30, 30))
rect = (10, 20, 30, 30)
rect = ((10, 20, 30, 30))
If you use any of the first three versions, however, you get access to Rect's utility functions. These include functions to move, shrink and inflate rects, find the union of two rects, and a variety of collision-detection functions.
如果你使用开头三个中的任何一个,你就可以使用rect的实用函数。它们包括移动,收缩和膨胀矩形,找出两个矩形的并集,和一堆的碰撞检测函数。
For example, suppose I'd like to get a list of all the sprites that contain a point (x, y) - maybe the player clicked there, or maybe that's the current location of a bullet. It's simple if each sprite has a .rect member - I just do:
例如,假设我想得到包含了点(x, y)——可能用户点击了这里,也可能是子弹的当前位置——的所有精灵。如果每个精灵都有一个.rect成员,事情就会很简单——我只消:
sprites_clicked = [sprite for sprite in all_my_sprites_list if sprite.rect.collidepoint(x, y)]
Rects have no other relation to surfaces or graphics functions, other than the fact that you can use them as arguments. You can also use them in places that have nothing to do with graphics, but still need to be defined as rectangles. Every project I discover a few new places to use rects where I never thought I'd need them.
除了能用rect作为参数,rect 跟surface和图像函数没别的瓜葛。你也可以把它们用到跟图形没啥关系,却又需要矩形的地方去。我几乎在每个工程里都发现几个需要使用rect的地方,而我从来没想到我也要在这里用上它们。
10.Don't bother with pixel-perfect collision detection.
10. 不要对像素级的碰撞检测费心。
So you've got your sprites moving around, and you need to know whether or not they're bumping into one another. It's tempting to write something like the following:
至此你已经让你的精灵动了起来,你需要知道他们到底会不会撞上别人。像下面这样做是很有诱惑性的:
1.Check to see if the rects are in collision. If they aren't, ignore them.
1. 看看矩形是不是碰撞了,如果不是,忽略它们。
2.For each pixel in the overlapping area, see if the corresponding pixels from both sprites are opaque. If so, there's a collision.
2. 对于重叠区域的每一个像素,检查它在每个精灵对应的像素是不是不透明的,如果的确是这样,则它们碰撞了。
There are other ways to do this, with ANDing sprite masks and so on, but any way you do it in pygame, it's probably going to be too slow. For most games, it's probably better just to do 'sub-rect collision' - create a rect for each sprite that's a little smaller than the actual image, and use that for collisions instead. It will be much faster, and in most cases the player won't notice the inprecision.
有很多方法实现这个想法,对精灵进行“与运算”等,但无论如何,它都会很慢。甚至对多数游戏来,更恰当的是做“子矩形碰撞”——对每个精灵做一个比其真实图像略小的矩形,用它来进行碰撞。这样会快得多,并且大数多情况下玩家不会注意到这个不精确的做法。
11.Managing the event subsystem
11. 管理好事件子系统。
Pygame's event system is kind of tricky. There are actually two different ways to find out what an input device (keyboard, mouse or joystick) is doing.
Pygame的事件系统很巧妙。有两种不同的方法找出输入设备(键盘,鼠标或游戏控制杆)在做什么。
The first is by directly checking the state of the device. You do this by calling, say, pygame.mouse.get_pos() or pygame.key.get_pressed(). This will tell you the state of that device at the moment you call the function.
第一种方法是直接检查设备的状态。通过调用叫pygame.mouse.get_pos()或pygame.key.get_press()的方法来实现。它们会告诉你当你调用这函数时设备的状态。
The second method uses the SDL event queue. This queue is a list of events - events are added to the list as they're detected, and they're deleted from the queue as they're read off.
第二种方法是使用SDL的事件队列。这个队列是一个事件的列表——当事件发生时就会被加到列表中,如果被读过了,它们就会被删除掉。
There are advantages and disadvantages to each system. State-checking (system 1) gives you precision - you know exactly when a given input was made - if mouse.get_pressed([0]) is 1, that means that the left mouse button is down right at this moment. The event queue merely reports that the mouse was down at some time in the past; if you check the queue fairly often, that can be ok, but if you're delayed from checking it by other code, input latency can grow. Another advantage of the state-checking system is that it detects "chording" easily; that is, several states at the same time. If you want to know whether the t and f keys are down at the same time, just check:
这两套系统各有利弊。状态检查(第一套系统)很精确——你准确知道一个输入什么时候发生——如果mouse.get_pressed([0])的值是1, 说明那时的鼠标左键点下了。而事件队列仅仅告诉我们在过去某个时间鼠标被点下了;如果你很频繁地检查队列,那没事,但如果你延迟了检查,潜在的输入就会越 来越多。状态检查系统的另一个优势就是可以很方便地检测“和音”,也就是说,在同一时间里同时生了多种状态。如果你要检查t和f键是不是被同时按下了,只 要检查:
if (key.get_pressed[K_t] and key.get_pressed[K_f]):
print "Yup!"
In the queue system, however, each keypress arrives in the queue as a completely separate event, so you'd need to remember that the t key was down, and hadn't come up yet, while checking for the f key. A little more complicated.
在队列系统中,每个到达队列的按键都作为一个单独的事件,所以你必须记得,在你检查f键的时候,t键被按下了但没有弹起。有点复杂。
The state system has one great weakness, however. It only reports what the state of the device is at the moment it's called; if the user hits a mouse button then releases it just before a call to mouse.get_pressed(), the mouse button will return 0 - get_pressed() missed the mouse button press completely. The two events, MOUSEBUTTONDOWN and MOUSEBUTTONUP, will still be sitting in the event queue, however, waiting to be retrieved and processed.
但状态系统有一个巨大的缺陷。它只报告被调用的那一刻的设备状态。如果鼠标被按下了,并且在释放之前调用了mouse.get_pressed(),鼠标 会返回0——get_pressed()完全错过了鼠标按下事件。这两个事件,MOUSEBUTTONDOWN和MOUSEBUTTONUP,仍然被放到 事件队列中去,等待读取和处理。
The lesson is: choose the system that meets your requirements. If you don't have much going on in your loop - say you're just sitting in a 'while 1' loop, waiting for input, use get_pressed() or another state function; the latency will be lower. On the other hand, if every keypress is crucial, but latency isn't as important - say your user is typing something in an editbox, use the event queue. Some keypresses may be slightly late, but at least you'll get them all.
教训就是:选择最适合你的需要的系统。如果不需要在循环中做太多事——也就是说你只需坐在板凳上,在一个'while 1'循环中待输入,用get_pressed()或者其它状态函数,延迟会比较短。相反,如果每一个按键都很关键,但是延迟不那么重要——比如你的用户在 一个编辑框里输入某些东西,就使用事件队列。某些按键会有点延迟,但至少你会一个不缺。
A note about event.poll() vs. wait() - poll() may seem better, since it doesn't block your program from doing anything while it's waiting for input - wait() suspends the program until an event is received. However, poll() will consume 100% of available cpu time while it runs, and it will fill the event queue with NOEVENTS. Use set_blocked() to select just those event types you're interested in - your queue will be much more manageable.
关于event.poll()和wait()对比的注记——poll()看起来会好点,因为它在等待输入的时候不会阻塞你的程序做事。Wait()则挂起 程序,直到接收到一个事件。不过,poll()运行时会花掉所有可用的CPU时间,并且它会用NOEVENTS来塞满事件队列。用 set_blocked()来选择你只需要哪些事件类型——你的队列看起来会更好管理。
12.Colorkey vs. Alpha
12. 色键 vs. Alpha
There's a lot of confusion around these two techniques, and much of it comes from the terminology used.
这两种技术常常混淆,并且大多来自于对术语的误用。
'Colorkey blitting' involves telling pygame that all pixels of a certain color in a certain image are transparent instead of whatever color they happen to be. These transparent pixels are not blitted when the rest of the image is blitted, and so don't obscure the background. This is how we make sprites that aren't rectangular in shape. Simply call surface.set_colorkey(color), where color is a rgb tuple - say (0,0,0). This would make every pixel in the source image transparent instead of black.
“色键”告诉pygame,特定图像的具有某种特定颜色的所有像素都被当成透明的。当其它部分的图像被blit的时候,这些透明像素不会被blit,所以 不会破坏背景。这就是我们怎么样使得精灵的形状不是矩形的。简单调用surface.set_colorkey(color),其中color是一个 RGB元组——像(0, 0, 0)。它会把图像中黑色的像素当作透明的。
'Alpha' is different, and it comes in two flavors. 'Image alpha' applies to the whole image, and is probably what you want. Properly known as 'translucency', alpha causes each pixel in the source image to be only partially opaque. For example, if you set a surface's alpha to 192 and then blitted it onto a background, 3/4 of each pixel's color would come from the source image, and 1/4 from the background. Alpha is measured from 255 to 0, where 0 is completely transparent, and 255 is completely opaque. Note that colorkey and alpha blitting can be combined - this produces an image that is fully transparent in some spots, and semi-transparent in others.
“Alpha”则不同,它有两种形式。“图像Alpha”应用于整个图像,这通常是你需要的。如大家所知的“半透明”,alpha让源图像的每个像素只有 部分不透明。比如说,你设置了一个surface的alpha为192,然后把它blit到一个背景上去时,每个像素的3/4颜色值会来自源图像,而1 /4来自背景图像。Alpha用255到0的一个数来衡量,其中0表示完全透明,255表示完全不透明。注意,颜色键和alpha可以混合——产品就是一 部分完全透明另一部分半透明的图像。
'Per-pixel alpha' is the other flavor of alpha, and it's more complicated. Basically, each pixel in the source image has its own alpha value, from 0 to 255. Each pixel, therefore, can have a different opacity when blitted onto a background. This type of alpha can't be mixed with colorkey blitting, and it overrides per-image alpha. Per-pixel alpha is rarely used in games, and to use it you have to save your source image in a graphic editor with a special alpha channel. It's complicated - don't use it yet.
“按像素alpha”是alpha的另一种表现,它更加复杂。简单说,源图像上每个像素都有它自己的alpha值,从0到255。在blit到背景上的时 候,每个像素都有一个不同的不透明度。这种类型的alpha不能跟色键混使用,并且要覆盖整个图像alpha。游戏中很少会用到按像素alpha的,如果 要用它,你要先用一个图像编辑器让它保留下一个alpha通道。很复杂——不要用它了。
13. Do things the pythony way.
13. 用Python的方法去干活。
A final note (this isn't the least important one; it just comes at the end). Pygame is a pretty lightweight wrapper around SDL, which is in turn a pretty lightweight wrapper around your native OS graphics calls. Chances are pretty good that if your code is still slow, and you've done the things I've mentioned above, then the problem lies in the way you're addressing your data in python. Certain idioms are just going to be slow in python no matter what you do. Luckily, python is a very clear language - if a piece of code looks awkward or unweildy, chances are its speed can be improved, too. Read over Python Performance Tips for some great advice on how you can improve the speed of your code. That said, premature optimisation is the root of all evil; if it's just not fast enough, don't torture the code trying to make it faster. Some things are just not meant to be :)
最后一个要点(这并不是最不重要的一个,只是它恰好应该放在最一个说)了。Pygame是SDL的一个优秀的轻量级封装,同时也是你本地操作系统图形调用 的一个完美的轻量级封装。如果你的代码依然很慢,而你已经做完了我上面提到的事情,那么大好机会来了,你所面对的问题就是你怎么样组合Python代码造 成的。某些运行得很慢的惯用语跟你所做的事情没什么关系。很幸运,python是一个很纯净的语言——如果一段代码看起来很笨拙不实用,那么就有机会改善 它的运行速度。阅读关于提高Python性能的技巧,从中获取提高你的代码速度的建议。有人说,过早的优化是万恶之源。如果它只是不够快,不要改动代码来 尝试让它更快。某些东西并不一定要那样。
There you go. Now you know practically everything I know about using pygame. Now, go write that game!
就这样吧。现在你知道了所有我所知道的关于的pygame的东西。现在,写你的游戏去吧!