前言
用Python写程序很有趣,写游戏程序也很有趣。那么,用Python写游戏程序就更有趣了。 不幸的是,这方面的入门教程非常少。我想改变这种状况,所以我写了这个教程。
安装
这些说明适用于pyglet 1.5
pyglet是一个纯python库,因此安装不需要特殊步骤。您可以用多种方式安装它,或者简单地复制pyglet直接放入项目中。如果您不确定该怎么做,建议的方法是通过pip
pip install pyglet --user
要播放压缩音频和视频文件(WAV除外),您需要安装FFmpeg
编写pyglet应用程序
开始使用一个新的库或框架可能会让人望而生畏,特别是当有大量的参考资料要阅读时。
hello, world
首先导入pyglet
import pyglet
创建pyglet.window.Window通过调用其默认构造函数。窗口将在创建后立即可见,并将为其所有参数提供合理的默认值:
window = pyglet.window.Window()
为了显示文本,我们将创建一个Label关键字参数用于设置标签的字体、位置和锚点:
label = pyglet.text.Label('Hello, world',
font_name='Times New Roman',
font_size=36,
x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
**on_draw()**事件被调度到窗口,使其有机会重新绘制其内容。pyglet提供了几种将事件处理程序连接到对象的方法;一种简单的方法是使用装饰器:
@window.event
def on_draw():
window.clear()
label.draw()
最后,请使用:
pyglet.app.run()
这将进入pyglet的默认事件循环,并让pyglet响应鼠标和键盘等应用程序事件**run()**方法将仅在关闭所有应用程序窗口时返回。
显示图片
大多数游戏和应用程序都需要在屏幕上加载和显示图像。在本例中,我们将从应用程序的目录中加载图像并在窗口中显示:
import pyglet
window = pyglet.window.Window()
image = pyglet.resource.image('images/kitten.png')
@window.event
def on_draw():
window.clear()
image.blit(0, 0)
pyglet.app.run()
blit方法用来显示图片位置,就像tkinter里的place。
但是pyglet的坐标是从左下角开始的。
我们用了pyglet.resource加载图片。还有一种方法:
pyglet.image.load()
处理鼠标和键盘事件
键盘事件
到目前为止,使用的唯一事件是on_draw()事件。要对键盘和鼠标事件做出反应,还需要为这些事件编写和附加事件处理程序:
import pyglet
window = pyglet.window.Window()
@window.event
def on_key_press(symbol, modifiers):
print('A key was pressed')
@window.event
def on_draw():
window.clear()
pyglet.app.run()
键盘事件有两个参数:被按下的键symbol,以及任何的modifiers按位如(ctrl或shift键)
接下来我们把on_key_press写完整。
@window.event
def on_key_press(symbol, modifiers):
if symbol == key.A:
print('The "A" key was pressed.')
elif symbol == key.LEFT:
print('The left arrow key was pressed.')
elif symbol == key.ENTER:
print('The enter key was pressed.')
注意在这之前请先
from pyglet.window import key
鼠标事件
鼠标事件的处理方式和键盘类似:
from pyglet.window import mouse
@window.event
def on_mouse_press(x, y, button, modifiers):
if button == mouse.LEFT:
print('The left mouse button was pressed.')
x和y参数给出按下按钮时鼠标相对于窗口左下角的位置。
button可能是鼠标左键,右键或者中键。modifiers是附加键
如ctrl或shift
一个窗口可以处理20多种事件类型。找到所需事件名称和参数的一个简单方法是将以下代码添加到程序中:
因为这将使窗口上接收到的所有事件都打印到控制台上。
event_logger = pyglet.window.event.WindowEventLogger()
window.push_handlers(event_logger)
播放声音
pyglet可以很容易地播放和混合多种声音
import pyglet
music = pyglet.resource.media('music.mp3')
music.play()
pyglet.app.run()
与前面介绍的图像加载示例一样,media()在应用程序的目录(而不是工作目录)中查找声音文件。如果您知道实际的文件系统路径(相对路径或绝对路径),请使用pyglet.media.load()
默认情况下,播放时会播放音频流。这对较长的音乐包很有效。短的声音,例如游戏中使用的枪声,应该在使用前在内存中正确解码。这使得它们可以更快地播放,并减少CPU性能损失。它还允许在不重新加载的情况下重复播放相同的声音,但是得在指定streaming=False
的情况下:
sound = pyglet.resource.media('shot.wav', streaming=False)
sound.play()
MP3和其他压缩音频格式需要安装FFmpeg。但是WAV文件可以在没有FFmpeg的情况下播放。
上面的例子向您展示了如何在屏幕上显示一些内容,以及如何执行一些基本任务。关于这些例子,你可能会有很多问题,但别担心。本编程指南的其余部分将详细介绍pyglet的许多特性。如果你是一个有经验的开发人员,你也许可以直接进入你感兴趣的部分。
对于新用户来说,一次通读所有内容可能会让人望而生畏。如果您感到不知所措,我们建议您浏览每个章节的开头部分,然后再看一个更深入的示例项目。
要编写高级三维应用程序或在2d应用程序中获得最佳性能,您需要直接使用OpenGL。
窗口
Window在pyglet中,对应于操作系统提供的顶层窗口。窗口可以是浮动的(与其他应用程序窗口重叠)或全屏显示。
创建窗口
window = pyglet.window.Window()
此刻我们就创建了一个pyglet窗口。
它的参数如下:
- width:窗口的宽度,默认是640像素,我们刚才指定的800
- height:窗口的高度,默认是480像素,我们刚才指定的600
- caption:窗口的标题,默认是sys.argv[0],我们看到刚才窗口的标题就是我们的文件路径
- resizable:bool类型,表示窗口是否可以调整大小,就是你把鼠标放在窗口边缘,是否可以进行方向上的拉伸。默认是False,不可以。
- style:用于指定窗口的边界风格,支持的选择如下:
WINDOW_STYLE_DEFAULT
(默认选项)、
WINDOW_STYLE_DIALOG
、
WINDOW_STYLE_TOOL
、
WINDOW_STYLE_BORDERLESS
,
这几个都在Window这个类里面,可以通过
pyglet.window.Window.style
指定 - fullscreen:是否全屏,默认是False
- visible:在窗口创建之后是否立刻显示,默认为True。如果你想在窗口显示之前修改某些属性,那么可以设置为False
- vsync:这个参数比较难理解,如果为True,那么缓冲区翻转将会同步到主屏幕的帧回描上面,从而消除闪烁。默认是为True,我们不需要管它。
- display:指定使用的显示设备,这个不需要管。
- 还剩下4个参数,基本上用不到,就不说了。
如果不传参数,使用的默认参数为:
- 窗口的大小将为640x480,并且不能调整大小。
- 窗口标题将是正在执行的Python脚本的位置。
窗口在创建后立即可见,除非visible=False
。
window = pyglet.window.Window(visible=False)
# 显示窗口
window.set_visible()
全屏窗口
如果fullscreen=True
参数指定给窗口构造函数,则窗口将绘制为整个屏幕而不是浮动窗口。不会显示窗口边框或控件,因此必须确保提供其他方法退出应用程序。
默认情况下,将使用默认显示上的默认屏幕,但您可以选择指定另一个屏幕来代替。例如,下面的代码在辅助屏幕上创建一个全屏窗口:
screens = display.get_screens()
window = pyglet.window.Window(fullscreen=True, screen=screens[1])
无法创建跨越多个窗口的全屏窗口(例如,如果您希望创建一个跨多个监视器的沉浸式三维环境)。相反,您应该为每个屏幕创建一个单独的全屏窗口,并将相同的事件处理程序附加到所有窗口。
窗口不仅可以切换到全屏模式还可以退出全屏模式。例如,要从全屏返回窗口模式:
window.set_fullscreen(False)
尺寸和位置
此部分仅适用于非全屏的窗口。全屏幕窗口始终具有其填充屏幕的宽度和高度。
窗口的“大小”是指窗口中的可绘制空间,不包括标题栏以及菜单栏。
您可以允许用户通过指定resizable=True
在构造函数中。如果您这样做,您可能还需要处理on_resize()活动:
window = pyglet.window.Window(resizable=True)
@window.event
def on_resize(width, height):
print('The window was resized to %dx%d' % (width, height))
您可以使用set_minimum_size()
和set_maximum_size()
方法限制窗口大小:
window.set_minimum_size(320, 200)
window.set_maximum_size(1024, 768)
也可以使用set_size()
方法设置大小:
window.set_size(1280, 720)
窗口最初将由操作系统定位。通常,它将使用自己的算法将窗口定位在一个不会阻塞其他应用程序窗口或与其级联的位置。您可以手动调整窗口的位置
用于获取的get_location()
和
用于设置的set_location()
方法:
x, y = window.get_location()
window.set_location(x + 20, y + 20)
请注意,窗口位置是以屏幕从左上角定位的。
窗口样式详解
风格 | windows | Mac os |
---|---|---|
WINDOW_STYLE_DEFAULT | ||
WINDOW_STYLE_DIALOG | ||
WINDOW_STYLE_TOOL |
这些窗口样式的不可调整大小的变体可能会略有不同(例如,“最大化”按钮将被禁用或不存在)。
除了外观上的变化,窗口样式还影响窗口的行为。例如,工具窗口通常不会出现在任务栏中,并且无法接收键盘焦点。无法最小化对话框窗口。为您的windows选择适当的窗口样式意味着您的应用程序将在其运行的平台上正常运行,但是这种行为在windows、Linux和Mac OS X之间可能不一致。
windows在Linux中的外观和行为会因发行版、窗口管理器和用户偏好而有很大的不同。
无边界窗口(WINDOW_STYLE_BORDERLESS
)完全不受操作系统的修饰,也无法在桌面上调整大小或移动。这些对于实现初始屏幕或自定义窗口边框非常有用。
标题
窗口的标题出现在标题栏和任务栏图标中(在windows和一些Linux窗口管理器上)。您可以在创建窗口期间或在以后的任何时间使用set_caption()
方法:
window = pyglet.window.Window(caption='Initial caption')
window.set_caption('A different caption')
icon图标
在Windows和Linux上,窗口图标显示在标题栏和任务栏图标中,在Mac OS X上,窗口图标显示在dock图标中。对话框和工具窗口不一定显示它们的图标。
Windows、Mac OS X和Linux窗口管理器都有各自的首选图标大小:
- Windows XP系统
标题栏和任务栏的16x16图标。
一个32x32图标,用于Alt Tab switcher。 - Mac OS X操作系统
分辨率为16x16、24x24、32x32、48x48、72x72和128x128的任意数量的图标。实际显示的图像将从提供的图像中插值到正确的大小。 - Linux系统
没有限制,但是大多数窗口管理器将使用16x16和a32x32图标,与WindowsXP相同。
set_icon()
方法允许您将任意数量的图像设置为图标。pyglet将选择最合适的图像并将其应用于窗口。如果需要替代尺寸但未提供,pyglet将使用简单的插值算法将图像缩放到正确的大小。
以下示例同时提供16x16和32x32图像作为窗口图标:
window = pyglet.window.Window()
icon1 = pyglet.image.load('16x16.png')
icon2 = pyglet.image.load('32x32.png')
window.set_icon(icon1, icon2)
您可以使用pyglet支持的任何格式的图像,但建议使用支持alpha透明性的格式,如PNG。Mac OS X.icons文件根本不受支持。
请注意,您在运行时设置的图标不必与应用程序图标有任何关系,应用程序图标必须在applicationbinary中进行特殊编码
可见度
多个状态的窗口具有可见性。显示的是visible
显示或隐藏窗口的属性。
窗口可以最小化,这相当于隐藏窗口,只是它们仍然显示在任务栏上(或者在OS X上最小化到dock上)。用户可以通过单击标题栏中的相应按钮来最小化窗口。您也可以使用minimize
方法(也有相应的maximize
方法)
当窗口可见时on_show()
事件被触发。当它被隐藏的时候on_hide()
事件被触发。在Windows和Linux上,只有当您手动更改窗口的可见性或最小化或还原窗口时,才会发生这些事件。用户也可以在Mac操作系统上使用快捷方式隐藏窗口。
窗口的继承
继承窗口对于要显示的每种类型的窗口,或作为主应用程序类。有几个好处:
- 您可以从构造函数加载字体和其他资源,确保已经创建了扩展上下文。
- 只需在类上定义事件处理程序,就可以添加它们。这个on_resize()事件将在创建窗口后立即调用(这通常不会发生,因为必须先创建窗口,然后才能附加事件处理程序)。
- 减少了对全局变量的需求,因为您可以在窗口上维护applicationstate。
class HelloWorldWindow(pyglet.window.Window):
def __init__(self):
super(HelloWorldWindow, self).__init__()
self.label = pyglet.text.Label('Hello, world!')
def on_draw(self):
self.clear()
self.label.draw()
if __name__ == '__main__':
window = HelloWorldWindow()
pyglet.app.run()