使用pygame编写游戏(1)
1. 介绍
游戏是编程应用较多的地方。即使是写一个最简单的游戏,你要熟悉UI制作,数学,物理学,甚至人工智能。这是一个练习编程的非常有趣的方式。
如果你是(或者不是)python语言的粉丝,你对游戏很感兴趣,那么pygame是一个非常棒的游戏编程库,你需要仔细的来学习它。它可以运行在所有的主流平台上,提供简单的工具函数就能处理复杂的图像处理,比如图像的移动、声音等。
网上有很多pygame的入门教程,但它们很多都是讲基本的。甚至Pygame book也属于介绍性级别的。为了更进一步提高对pygame的掌握,我决定写一个我自己的教程,希望能为使用pygame的人提供更进一步的合理学习。
本教程明确鼓励你去改进代码,并强烈推荐做一下后面的练习题,这些练习题可以让你对学到内容有更好的认知。
2. 写在前面
基于以上说的,这个教程并不适合初学者。如果你刚开始学习pygame,你可以看一下这些教程,推荐看这些基本的介绍教程。
在这里,我认为你具备以下知识:
1. Python(你可能不是它的高级用户,但也完全不是一个初学者)。
2. 数学和物理学的基本知识(向量,正方形,运动定律,概率等等)。我会解释所有非常见的知识点,但我不会教你怎么增加向量,等等。
3. 对pygame的认知。比如,你已经学习过我之前提到的介绍性的pygame教程。、
还有要说的是,我之关注2D游戏,3D游戏会是更高层次更复杂,我会提出一个不是很完整的3D游戏样本。
3. 让我们开始吧
在这个部分,我们完整写一个游戏样例:模拟爬虫,一些生物在屏幕上移动,从墙上弹回来,时不时的改变方向。
虽然这称不上是一个游戏,但这是我们实现更多不同想法的好的起点。I’ll leave myself the luxury of postponing the decision of which game it will eventually be, for now.
4. 代码
第一部分完整的代码包,包括需要的图片,可以在这里下载。我建议你下载下来并运行它。一遍看教程,一遍看代码将会对你非常有好处。我在python2.5.2,pygame1.8.1上测试过了,也可能会在其它版本上运行比较好。
5. pygame的文档
pygame的API文档很全。这里有pygame全部模块,类,常量,函数的列表,我建议对你不熟悉的类或者方法,多去查找这个文档。
6. 爬虫
好吧,我先明确以下该部分的目标:
- 我们想让爬虫能在屏幕上移动
- 爬虫的总数是可以轻易的配置的
- 爬虫碰到墙后能反弹
- 为让游戏更有趣,爬虫需要表现出半随机的动作
那么爬虫是什么?
爬虫是一张图片,在pygame的驱动下,能够移动或者旋转。由于图片的制作超出我的能力,我只让爬虫能够向左右上下移动,而45度方向移动无法实现。
爬虫的图片包含在下载包中的小的.png文件中。
注意到所有的爬虫图片头部方向都是一致的。
爬虫是怎么移动的?如果你确定读过一个基本的pygame教程(没有吗?),你会知道移动其实是一种幻觉。电脑屏幕上没真正移动的东西。其实,程序会对一系列图片以比人眼睛快的多的速度进行移位。每秒30次或更多次刷新,会让图片看上去更加平滑。为了实现周期性的刷屏,游戏有一个"game loop"
7. 游戏循环
和GUI程序一样,每个游戏都有一个“主循环”。在pygame中,使用了一个简单的循环,如下:
# The main game loop # while True: # Limit frame speed to 50 FPS # time_passed = clock.tick(50) for event in pygame.event.get(): if event.type == pygame.QUIT: exit_game() # Redraw the background screen.fill(BG_COLOR) # Update and redraw all creeps for creep in creeps: creep.update(time_passed) creep.blitme() pygame.display.flip()
就如我说的,这是一个基本的python循环--直到用户点击关闭窗口后,会给出退出消息,响应pygame.QUIT处理退出。
循环执行频度如何?这要取决于对clock.tick的调用。clock是pygame.time.Clock的对象,在此之前已经创建。调用tick的意思是:在下一个1/50秒到来前主循环休眠。在实际生活中,这限制了游戏的速度为50FPS,这是有好处的。一方面,我们可以让游戏更加平滑真实,另一方面,可以使游戏不能占用太多cpu资源。你可以尝试修改这个值,比如,当此值小于10,那么这个程序将会是什么样呢?我们看练习1和3.
现在是时候去看看关于tick的文档了。
每次循环都会重绘背景颜色,并且所有的爬虫会更新绘制。最终,整个屏幕会使用flip进行刷新(你应该看看它的文档了)。
8. 在循环之前
现在让我们看看在主循环之前都做了那些事情:ow let’s see what comes before the main loop:
# Game parameters
SCREEN_WIDTH, SCREEN_HEIGHT = 400, 400
BG_COLOR = 150, 150, 80
CREEP_FILENAMES = [
'bluecreep.png',
'pinkcreep.png',
'graycreep.png']
N_CREEPS = 20
pygame.init()
screen = pygame.display.set_mode(
(SCREEN_WIDTH, SCREEN_HEIGHT), 0, 32)
clock = pygame.time.Clock()
# Create N_CREEPS random creeps.
creeps = []
for i in range(N_CREEPS):
creeps.append(Creep(screen,
choice(CREEP_FILENAMES),
( randint(0, SCREEN_WIDTH),
randint(0, SCREEN_HEIGHT)),
( choice([-1, 1]),
choice([-1, 1])),
0.1))
开始的几行都是可以自说明的,我认为你已经了解如何初始化pygame,并且创建display对象。但是爬虫对象的创建呢?
爬虫是一系列爬虫对象的集合,这是整个游戏的心脏和灵魂。下面是爬虫类的声明和其构造函数的定义。
class Creep(Sprite): """ A creep sprite that bounces off walls and changes its direction from time to time. """ def __init__( self, screen, img_filename, init_position, init_direction, speed): """ Create a new Creep. screen: The screen on which the creep lives (must be a pygame Surface object, such as pygame.display) img_filaneme: Image file for the creep. init_position: A vec2d or a pair specifying the initial position of the creep on the screen. init_direction: A vec2d or a pair specifying the initial direction of the creep. Must have an angle that is a multiple of 45 degres. speed: Creep speed, in pixels/millisecond (px/ms) """
构造函数的参数有详细的说明文档,你可以看到它们在爬虫被创建时如何匹配的。
creeps.append(Creep(screen, choice(CREEP_FILENAMES), ( randint(0, SCREEN_WIDTH), randint(0, SCREEN_HEIGHT)), ( choice([-1, 1]), choice([-1, 1])), 0.1))
首先,我们传递screen surface给爬虫类。爬虫将使用它判读如何从墙上反弹回来,如何去绘制自己。
其次,爬虫可以从图片列表中任意选择一个(choice是一个标准的python模块),它有一个屏幕随机位置,随机的方向,移动速度被设定为0.1像素/每毫秒,或者说100个像素/秒。英文原地址 http://eli.thegreenplace.net/2008/12/13/writing-a-game-in-python-with-pygame-part-i/