原文:NumPy: Beginner’s Guide - Third Edition
协议:CC BY-NC-SA 4.0
译者:飞龙
本章适用于希望使用 NumPy 和 Pygame 快速轻松创建游戏的开发人员。 基本的游戏开发经验会有所帮助,但这不是必需的。
您将学到的东西如下:
Pygame 是 Python 框架,最初由 Pete Shinners 编写, 顾名思义,可用于制作视频游戏。 自 2004 年以来,Pygame 是免费的开放源代码,并获得 GPL 许可,这意味着您基本上可以制作任何类型的游戏。 Pygame 构建在简单 DirectMedia 层(SDL)。 SDL 是一个 C 框架,可以访问各种操作系统(包括 Linux,MacOSX 和 Windows)上的图形,声音,键盘和其他输入设备。
我们将在本节中安装 Pygame。 Pygame 应该与所有 Python 版本兼容。 在撰写时,Python3 存在一些不兼容问题,但很可能很快就会解决。
在 Debian 和 Ubuntu 上安装:Pygame 可以在 Debian 档案文件中找到。
在 Windows 上安装:从 Pygame 网站下载适用于您正在使用的版本的 Python 的二进制安装程序。
在 Mac 上安装 Pygame:适用于 MacOSX 10.3 及更高版本的二进制 Pygame 包可在这个页面中找到。
从源代码安装:Pygame 使用distutils
系统进行编译和安装。 要开始使用默认选项安装 Pygame,只需运行以下命令:
$ python setup.py
如果您需要有关可用选项的更多信息,请键入以下内容:
$ python setup.py help
要编译代码,您的操作系统需要一个编译器。 进行设置超出了本书的范围。 有关在 Windows 上编译 Pygame 的更多信息,可以在这个页面上找到。 有关在 MacOSX 上编译 Pygame 的更多信息,请参考这里。
我们将创建一个简单的游戏,在本章中我们将进一步改进 。 与编程书籍中的传统方法一样,我们从Hello World!
示例开始。
重要的是要注意所谓的主游戏循环,在该循环中所有动作都会发生,并使用Font
模块渲染文本。 在此程序中,我们将操纵用于绘制的 Pygame Surface
对象,并处理退出事件。
首先,导入所需的 Pygame 模块。 如果正确安装了 Pygame,则不会出现任何错误,否则请返回安装“实战时间”:
import pygame, sys
from pygame.locals import *
初始化 Pygame,按300
像素创建400
的显示,并将窗口标题设置为Hello world!
:
pygame.init()
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Hello World!')
游戏通常会有一个游戏循环,该循环将一直运行直到发生退出事件为止。 在此示例中,仅在坐标(100, 100)
上设置带有文本Hello world!
的标签。 文字的字体大小为 19,颜色为红色:
while True:
sysFont = pygame.font.SysFont("None", 19)
rendered = sysFont.render('Hello World', 0, (255, 100, 100))
screen.blit(rendered, (100, 100))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
我们得到以下屏幕截图作为最终结果:
以下是 HelloWorld 的完整代码示例:
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Hello World!')
while True:
sysFont = pygame.font.SysFont("None", 19)
rendered = sysFont.render('Hello World', 0, (255, 100, 100))
screen.blit(rendered, (100, 100))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
看起来似乎不多,但是我们在本节中学到了很多东西。 下表总结了通过审查的函数:
函数 | 描述 |
---|---|
pygame.init() |
此函数执行初始化,您必须在调用其他 Pygame 函数之前调用它。 |
pygame.display.set_mode((400, 300)) |
此函数创建一个要使用的所谓的Surface 对象。 我们给这个函数一个表示表面尺寸的元组。 |
pygame.display.set_caption('Hello World!') |
此函数将窗口标题设置为指定的字符串值。 |
pygame.font.SysFont("None", 19) |
此函数根据逗号分隔的字体列表(在本例中为无)和整数字体大小参数创建系统字体。 |
sysFont.render('Hello World', 0, (255, 100, 100)) |
此函数在Surface 上绘制文本。 最后一个参数是表示颜色的 RGB 值的元组。 |
screen.blit(rendered, (100, 100)) |
此函数使用Surface 。 |
pygame.event.get() |
此函数获取Event 对象的列表。 事件表示系统中的特殊事件,例如用户退出游戏。 |
pygame.quit() |
该函数清除由 Pygame 使用的资源。 退出游戏之前,请调用此函数。 |
pygame.display.update() |
此函数刷新表面。 |
大多数游戏,甚至是最静态的游戏,都有一定程度的动画效果。 从程序员的角度来看,动画就是 ,无非就是在不同的时间在不同的位置显示对象,从而模拟运动。
Pygame 提供了一个Clock
对象,该对象管理每秒绘制多少帧。 这样可以确保动画与用户 CPU 的速度无关。
我们将加载图像,然后再次使用 NumPy 定义屏幕周围的顺时针路径。
创建一个 Pygame 时钟,如下所示:
clock = pygame.time.Clock()
作为本书随附的源代码的一部分,应该有一张头像。 加载此图像并在屏幕上四处移动:
img = pygame.image.load('head.jpg')
定义一些数组来保存位置的坐标,我们希望在动画过程中将图像放置在这些位置。 由于我们将移动对象,因此路径有四个逻辑部分:right
,down
,left
和up
。 每个部分将具有40
等距步长。 将0
部分中的所有值初始化:
steps = np.linspace(20, 360, 40).astype(int)
right = np.zeros((2, len(steps)))
down = np.zeros((2, len(steps)))
left = np.zeros((2, len(steps)))
up = np.zeros((2, len(steps)))
设置图像位置的坐标很简单。 但是,需要注意一个棘手的问题-[::-1]
表示法会导致数组元素的顺序颠倒:
right[0] = steps
right[1] = 20
down[0] = 360
down[1] = steps
left[0] = steps[::-1]
left[1] = 360
up[0] = 20
up[1] = steps[::-1]
我们可以加入路径部分,但是在执行此操作之前,请使用T
运算符转置数组,因为它们未正确对齐以进行连接:
pos = np.concatenate((right.T, down.T, left.T, up.T))
在主事件循环中,让时钟以每秒 30 帧的速度计时:
clock.tick(30)
摇头的屏幕截图如下:
您应该能够观看此动画的电影。 它也是代码包(animation.mp4
)的一部分。
此示例的代码几乎使用了到目前为止我们学到的所有内容,但仍应足够简单以了解:
import pygame, sys
from pygame.locals import *
import numpy as np
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption('Animating Objects')
img = pygame.image.load('head.jpg')
steps = np.linspace(20, 360, 40).astype(int)
right = np.zeros((2, len(steps)))
down = np.zeros((2, len(steps)))
left = np.zeros((2, len(steps)))
up = np.zeros((2, len(steps)))
right[0] = steps
right[1] = 20
down[0] = 360
down[1] = steps
left[0] = steps[::-1]
left[1] = 360
up[0] = 20
up[1] = steps[::-1]
pos = np.concatenate((right.T, down.T, left.T, up.T))
i = 0
while True:
# Erase screen
screen.fill((255, 255, 255))
if i >= len(pos):
i = 0
screen.blit(img, pos[i])
i += 1
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
clock.tick(30)
在本节中,我们了解了一些有关动画的知识。 我们了解到的最重要的概念是时钟。 下表描述了我们使用的新函数:
函数 | 描述 |
---|---|
pygame.time.Clock() |
这将创建一个游戏时钟。 |
clock.tick(30) |
此函数执行游戏时钟的刻度。 此处,30 是每秒的帧数。 |
matplotlib
是一个易于绘制的开源库,我们在第 9 章,“matplotlib 绘图”中了解到。 我们可以将 matplotlib 集成到 Pygame 游戏中并创建各种绘图。
在本秘籍中,我们采用上一节的位置坐标,并对其进行绘制。
要将 matplotlib 与 Pygame 集成,我们需要使用非交互式后端; 否则,默认情况下,matplotlib 将为我们提供一个 GUI 窗口。 我们将导入主要的 matplotlib 模块并调用use()
函数。 在导入主 matplotlib 模块之后以及在导入其他 matplotlib 模块之前,立即调用此函数:
import matplotlib as mpl
mpl.use("Agg")
我们可以在 matplotlib 画布上绘制非交互式绘图。 创建此画布需要导入,创建图形和子图。 将数字指定为3
乘3
英寸大。 在此秘籍的末尾可以找到更多详细信息:
import matplotlib.pyplot as plt
import matplotlib.backends.backend_agg as agg
fig = plt.figure(figsize=[3, 3])
ax = fig.add_subplot(111)
canvas = agg.FigureCanvasAgg(fig)
在非交互模式下,绘制数据比在默认模式下复杂一些。 由于我们需要重复绘图,因此在函数中组织绘图代码是有意义的。 Pygame 最终在画布上绘制了绘图。 画布为我们的设置增加了一些复杂性。 在此示例的末尾,您可以找到有关这些函数的更多详细说明:
def plot(data):
ax.plot(data)
canvas.draw()
renderer = canvas.get_renderer()
raw_data = renderer.tostring_rgb()
size = canvas.get_width_height()
return pygame.image.fromstring(raw_data, size, "RGB")
下面的屏幕截图显示了正在运行的动画。 您还可以在代码包(matplotlib.mp4
)和 YouTube 上查看截屏视频。
更改后,我们将获得以下代码:
import pygame, sys
from pygame.locals import *
import numpy as np
import matplotlib as mpl
mpl.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.backends.backend_agg as agg
fig = plt.figure(figsize=[3, 3])
ax = fig.add_subplot(111)
canvas = agg.FigureCanvasAgg(fig)
def plot(data):
ax.plot(data)
canvas.draw()
renderer = canvas.get_renderer()
raw_data = renderer.tostring_rgb()
size = canvas.get_width_height()
return pygame.image.fromstring(raw_data, size, "RGB")
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption('Animating Objects')
img = pygame.image.load('head.jpg')
steps = np.linspace(20, 360, 40).astype(int)
right = np.zeros((2, len(steps)))
down = np.zeros((2, len(steps)))
left = np.zeros((2, len(steps)))
up = np.zeros((2, len(steps)))
right[0] = steps
right[1] = 20
down[0] = 360
down[1] = steps
left[0] = steps[::-1]
left[1] = 360
up[0] = 20
up[1] = steps[::-1]
pos = np.concatenate((right.T, down.T, left.T, up.T))
i = 0
history = np.array([])
surf = plot(history)
while True:
# Erase screen
screen.fill((255, 255, 255))
if i >= len(pos):
i = 0
surf = plot(history)
screen.blit(img, pos[i])
history = np.append(history, pos[i])
screen.blit(surf, (100, 100))
i += 1
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
clock.tick(30)
下表解释了绘图相关函数:
函数 | 描述 |
---|---|
mpl.use("Agg") |
此函数指定使用非交互式后端 |
plt.figure(figsize=[3, 3]) |
此函数创建一个3 x 3 英寸的图形 |
agg.FigureCanvasAgg(fig) |
此函数在非交互模式下创建画布 |
canvas.draw() |
此函数在画布上绘制 |
canvas.get_renderer() |
此函数为画布提供渲染器 |
Pygame surfarray
模块处理 Pygame Surface
对象与 NumPy 数组之间的转换 。 您可能还记得,NumPy 可以快速有效地处理大型数组。
在本节中,我们将平铺一个小图像以填充游戏屏幕。
array2d()
函数将像素复制到二维数组中(对于三维数组也有类似的功能)。 将头像图像中的像素复制到数组中:
pixels = pygame.surfarray.array2d(img)
使用数组的shape
属性从像素数组的形状创建游戏屏幕。 在两个方向上将屏幕放大七倍:
X = pixels.shape[0] * 7
Y = pixels.shape[1] * 7
screen = pygame.display.set_mode((X, Y))
使用 NumPy tile()
函数可以轻松平铺图像。 数据需要转换为整数值,因为 Pygame 将颜色定义为整数:
new_pixels = np.tile(pixels, (7, 7)).astype(int)
surfarray
模块具有特殊函数blit_array()
在屏幕上显示数组:
pygame.surfarray.blit_array(screen, new_pixels)
以下代码执行图像的平铺:
import pygame, sys
from pygame.locals import *
import numpy as np
pygame.init()
img = pygame.image.load('head.jpg')
pixels = pygame.surfarray.array2d(img)
X = pixels.shape[0] * 7
Y = pixels.shape[1] * 7
screen = pygame.display.set_mode((X, Y))
pygame.display.set_caption('Surfarray Demo')
new_pixels = np.tile(pixels, (7, 7)).astype(int)
while True:
screen.fill((255, 255, 255))
pygame.surfarray.blit_array(screen, new_pixels)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
以下是我们使用的新函数和属性的简要说明:
函数 | 描述 |
---|---|
pygame.surfarray.array2d(img) |
此函数将像素数据复制到二维数组中 |
pygame.surfarray.blit_array(screen, new_pixels) |
此函数在屏幕上显示数组值 |
通常,我们需要模仿游戏中的智能行为。 scikit-learn
项目旨在提供一种用于机器学习的 API,而我最喜欢的是其精美的文档。 我们可以使用操作系统的包管理器来安装scikit-learn
,尽管此选项可能有效或无效,具体取决于您的操作系统,但这应该是最方便的方法。 Windows 用户只需从项目网站下载安装程序即可。 在 Debian 和 Ubuntu 上,该项目称为python-sklearn
。 在 MacPorts 上,这些端口称为py26-scikits-learn
和py27-scikits-learn
。 我们也可以从源代码或使用easy_install
安装。 PythonXY, Enthought 和 NetBSD。
我们可以通过在命令行中键入来安装scikit-learn
:
$ [sudo] pip install -U scikit-learn
我们也可以键入以下内容而不是前一行:
$ [sudo] easy_install -U scikit-learn
由于权限的原因,这可能无法正常工作,因此您可能需要在命令前面放置sudo
或以管理员身份登录。
我们将生成一些随机点并将它们聚类,这意味着彼此靠近的点将放入同一簇中。 这只是scikit-learn
可以应用的许多技术之一。聚类是一种机器学习算法,旨在基于相似度对项目进行分组。 接下来,我们将计算平方亲和矩阵。亲和度矩阵是包含亲和度值的矩阵:例如,点之间的距离。 最后,我们将这些点与[HTG2]中的AffinityPropagation
类聚类。
在400 x 400
像素的正方形内生成 30 个随机点位置:
positions = np.random.randint(0, 400, size=(30, 2))
使用到原点的欧式距离作为亲和度度量来计算亲和度矩阵:
positions_norms = np.sum(positions ** 2, axis=1)
S = - positions_norms[:, np.newaxis] - positions_norms[np.newaxis, :] + 2 * np.dot(positions, positions.T)
给AffinityPropagation
类上一步的结果。 此类使用适当的群集编号标记点:
aff_pro = sklearn.cluster.AffinityPropagation().fit(S)
labels = aff_pro.labels_
为每个群集绘制多边形。 涉及的函数需要点列表,颜色(将其绘制为红色)和表面:
pygame.draw.polygon(screen, (255, 0, 0), polygon_points[i])
结果是每个群集的一堆多边形,如下图所示:
群集示例代码如下:
import numpy as np
import sklearn.cluster
import pygame, sys
from pygame.locals import *
np.random.seed(42)
positions = np.random.randint(0, 400, size=(30, 2))
positions_norms = np.sum(positions ** 2, axis=1)
S = - positions_norms[:, np.newaxis] - positions_norms[np.newaxis, :] + 2 * np.dot(positions, positions.T)
aff_pro = sklearn.cluster.AffinityPropagation().fit(S)
labels = aff_pro.labels_
polygon_points = []
for i in xrange(max(labels) + 1):
polygon_points.append([])
# Sorting points by cluster
for label, position in zip(labels, positions):
polygon_points[labels[i]].append(positions[i])
pygame.init()
screen = pygame.display.set_mode((400, 400))
while True:
for point in polygon_points:
pygame.draw.polygon(screen, (255, 0, 0), point)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
下表更详细地描述了人工智能示例中最重要的行 :
函数 | 描述 |
---|---|
sklearn.cluster.AffinityPropagation().fit(S) |
此函数创建AffinityPropagation 对象,并使用相似性矩阵执行拟合 |
pygame.draw.polygon(screen, (255, 0, 0), point) |
给定表面,颜色(在这种情况下为红色)和点列表,此函数绘制多边形 |
OpenGL 为二维和三维计算机图形指定了 API。 API 由函数和常量组成。 我们将专注于名为PyOpenGL
的 Python 实现。 使用以下命令安装PyOpenGL
:
$ [sudo] pip install PyOpenGL PyOpenGL_accelerate
您可能需要具有 root 访问权限才能执行此命令。 对应于easy_install
的命令如下:
$ [sudo] easy_install PyOpenGL PyOpenGL_accelerate
为了演示的目的,我们将使用 OpenGL 绘制一个 Sierpinski 地毯,也称为 Sierpinski 三角形或 Sierpinski 筛子。 这是由数学家 Waclaw Sierpinski 创建的三角形形状的分形图案。 三角形是通过递归且原则上是无限的过程获得的。
首先,首先初始化一些与 OpenGL 相关的原语。 这包括设置显示模式和背景颜色。 本节末尾提供逐行说明:
def display_openGL(w, h):
pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF)
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
gluOrtho2D(0, w, 0, h)
该算法要求我们显示点,越多越好。 首先,我们将绘图颜色设置为红色。 其次,我们定义一个三角形的顶点(我称它们为点)。 然后,我们定义随机索引,该随机索引将用于选择三个三角形顶点之一。 我们在中间的某个地方随机选择一个点,实际上并不重要。 之后,在上一个点和随机选取的一个顶点之间的一半处绘制点。 最后,刷新结果:
glColor3f(1.0, 0, 0)
vertices = np.array([[0, 0], [DIM/2, DIM], [DIM, 0]])
NPOINTS = 9000
indices = np.random.random_integers(0, 2, NPOINTS)
point = [175.0, 150.0]
for i in xrange(NPOINTS):
glBegin(GL_POINTS)
point = (point + vertices[indices[i]])/2.0
glVertex2fv(point)
glEnd()
glFlush()
Sierpinski 三角形如下所示:
带有所有导入的完整 Sierpinski 垫圈演示代码如下:
import pygame
from pygame.locals import *
import numpy as np
from OpenGL.GL import *
from OpenGL.GLU import *
def display_openGL(w, h):
pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF)
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
gluOrtho2D(0, w, 0, h)
def main():
pygame.init()
pygame.display.set_caption('OpenGL Demo')
DIM = 400
display_openGL(DIM, DIM)
glColor3f(1.0, 0, 0)
vertices = np.array([[0, 0], [DIM/2, DIM], [DIM, 0]])
NPOINTS = 9000
indices = np.random.random_integers(0, 2, NPOINTS)
point = [175.0, 150.0]
for i in xrange(NPOINTS):
glBegin(GL_POINTS)
point = (point + vertices[indices[i]])/2.0
glVertex2fv(point)
glEnd()
glFlush()
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
if __name__ == '__main__':
main()
如所承诺的,以下是该示例最重要部分的逐行说明:
函数 | 描述 |
---|---|
pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF) |
此函数将显示模式设置为所需的宽度,高度和 OpenGL 显示 |
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) |
此函数使用遮罩清除缓冲区。 在这里,我们清除颜色缓冲区和深度缓冲区位 |
gluOrtho2D(0, w, 0, h) |
此函数定义二维正交投影矩阵,其坐标为左,右,上和下剪切平面 |
glColor3f(1.0, 0, 0) |
此函数使用 RGB 的三个浮点值(红色,绿色,蓝色)定义当前图形颜色。 在这种情况下,我们将以红色绘制 |
glBegin(GL_POINTS) |
此函数定义了图元的顶点或图元的组。 这里的原语是点 |
glVertex2fv(point) |
此函数在给定顶点的情况下渲染点 |
glEnd() |
此函数关闭以glBegin() 开头的一段代码 |
glFlush() |
此函数强制执行 GL 命令 |
作为最后一个示例,我们将使用 Conway 的生命游戏模拟生命。 最初的生命游戏是基于一些基本规则。 我们从二维正方形网格上的随机配置开始。 网格中的每个单元可以是死的或活着的。 此状态取决于小区的邻居。 您可以在这个页面上详细了解规则。在每个时间步上,都会发生以下转换:
卷积可用于求值游戏的基本规则。 卷积过程需要 SciPy 包。
以下代码是生命游戏的实现 ,并进行了一些修改:
r
键可将网格重置为随机状态b
键根据鼠标位置创建块g
键创建滑翔机代码中最重要的数据结构是一个二维数组,其中包含游戏屏幕上像素的颜色值。 该数组用随机值初始化,然后针对游戏循环的每次迭代重新计算。 在下一部分中找到有关所涉及函数的更多信息。
要求值规则,请使用卷积,如下所示:
def get_pixar(arr, weights):
states = ndimage.convolve(arr, weights, mode='wrap')
bools = (states == 13) | (states == 12 ) | (states == 3)
return bools.astype(int)
使用我们在第 2 章,“从 NumPy 基础知识开始”中学习的基本索引技巧来画十字:
def draw_cross(pixar):
(posx, posy) = pygame.mouse.get_pos()
pixar[posx, :] = 1
pixar[:, posy] = 1
用随机值初始化网格:
def random_init(n):
return np.random.random_integers(0, 1, (n, n))
以下是完整的代码:
from __future__ import print_function
import os, pygame
from pygame.locals import *
import numpy as np
from scipy import ndimage
def get_pixar(arr, weights):
states = ndimage.convolve(arr, weights, mode='wrap')
bools = (states == 13) | (states == 12 ) | (states == 3)
return bools.astype(int)
def draw_cross(pixar):
(posx, posy) = pygame.mouse.get_pos()
pixar[posx, :] = 1
pixar[:, posy] = 1
def random_init(n):
return np.random.random_integers(0, 1, (n, n))
def draw_pattern(pixar, pattern):
print(pattern)
if pattern == 'glider':
coords = [(0,1), (1,2), (2,0), (2,1), (2,2)]
elif pattern == 'block':
coords = [(3,3), (3,2), (2,3), (2,2)]
elif pattern == 'exploder':
coords = [(0,1), (1,2), (2,0), (2,1), (2,2), (3,3)]
elif pattern == 'fpentomino':
coords = [(2,3),(3,2),(4,2),(3,3),(3,4)]
pos = pygame.mouse.get_pos()
xs = np.arange(0, pos[0], 10)
ys = np.arange(0, pos[1], 10)
for x in xs:
for y in ys:
for i, j in coords:
pixar[x + i, y + j] = 1
def main():
pygame.init ()
N = 400
pygame.display.set_mode((N, N))
pygame.display.set_caption("Life Demo")
screen = pygame.display.get_surface()
pixar = random_init(N)
weights = np.array([[1,1,1], [1,10,1], [1,1,1]])
cross_on = False
while True:
pixar = get_pixar(pixar, weights)
if cross_on:
draw_cross(pixar)
pygame.surfarray.blit_array(screen, pixar * 255 ** 3)
pygame.display.flip()
for event in pygame.event.get():
if event.type == QUIT:
return
if event.type == MOUSEBUTTONDOWN:
cross_on = not cross_on
if event.type == KEYDOWN:
if event.key == ord('r'):
pixar = random_init(N)
print("Random init")
if event.key == ord('g'):
draw_pattern(pixar, 'glider')
if event.key == ord('b'):
draw_pattern(pixar, 'block')
if event.key == ord('e'):
draw_pattern(pixar, 'exploder')
if event.key == ord('f'):
draw_pattern(pixar, 'fpentomino')
if __name__ == '__main__':
main()
您应该能够从代码包(life.mp4
)或 YouTube 上观看截屏视频。 正在运行的游戏的屏幕截图如下:
我们使用了一些 NumPy 和 SciPy 函数,这些函数需要说明:
函数 | 描述 |
---|---|
ndimage.convolve(arr, weights, mode='wrap') |
此函数在包装模式下使用权重将卷积运算应用于给定数组。 该模式与数组边界有关。 |
bools.astype(int) |
此函数将布尔数组转换为整数。 |
np.arange(0, pos[0], 10) |
此函数以 10 为步长创建一个从 0 到pos[0] 的数组。因此,如果pos[0] 等于 1000,我们将得到 0、10、20,… 990。 |
您可能会发现本书中提到 Pygame 有点奇怪。 但是,阅读本章后,我希望您意识到 NumPy 和 Pygame 可以很好地结合在一起。 毕竟,游戏涉及大量计算,因此 NumPy 和 SciPy 是理想的选择,并且它们还需要scikit-learn
中提供的人工智能功能。 无论如何,制作游戏都很有趣,我们希望最后一章相当于十道菜后的精美甜点或咖啡! 如果您仍然渴望更多,请查看《NumPy Cookbook 第二版》, Ivan Idris,Packt Publishing,在本书的基础上以最小的重叠为基础。
arange()
函数的功能arange(5) 做什么? |
它创建一个 NumPy 数组,其值为从 0-4 创建的 NumPy 数组的值,0、1、2、3 和 4 |
ndarray
的形状ndarray 的形状如何存储? |
它存储在一个元组中 |
哪个函数返回数组的加权平均值? | average |
哪个函数返回两个数组的协方差? | cov |
ufunc
mat 和bmat 函数接受的字符串中的行分隔符是什么? |
分号 |
哪个函数可以创建矩阵? | mat |
哪个 NumPy 模块处理随机数? | random |
assert_almost_equal 函数的哪个参数指定小数精度? |
decimal |
plot()
函数plot 函数有什么作用? |
它既不执行 1、2 也不执行 3 |
.mat
文件哪个函数加载.mat 文件? |
loadmat |
本附录包含指向相关网站的链接。
本附录包含有用的 NumPy 函数及其说明的列表。
numpy.apply_along_axis
(func1d, axis, arr, *args
):沿arr
的一维切片应用函数func1d
。
numpy.arange([start,] stop[, step,], dtype=None)
:创建一个 NumPy 数组,它在指定范围内均匀间隔。
numpy.argsort(a, axis=-1, kind='quicksort', order=None)
:返回对输入数组进行排序的索引。
numpy.argmax(a, axis=None)
:返回沿轴的最大值的索引。
numpy.argmin(a, axis=None)
:返回沿轴的最小值的索引。
numpy.argwhere(a)
:查找非零元素的索引。
numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
:从类似数组的序列(例如 Python 列表)创建 NumPy 数组。
numpy.testing.assert_allclose((actual, desired, rtol=1e-07, atol=0, err_msg='', verbose=True)
:如果两个对象在指定的精度下不相等,则引发错误。
numpy.testing.assert_almost_equal()
:如果两个数字在指定的精度下不相等,则引发异常。
numpy.testing.assert_approx_equal()
:如果两个数字在某个有效数字下不相等,则引发异常。
numpy.testing.assert_array_almost_equal()
:如果两个数组在指定的精度下不相等,则引发异常。
numpy.testing.assert_array_almost_equal_nulp(x, y, nulp=1)
:将数组与其最低精度单位(ULP)。
numpy.testing.assert_array_equal()
:如果两个数组不相等,则引发异常。
numpy.testing.assert_array_less()
:如果两个数组的形状不同,并且第一个数组的元素严格小于第二个数组的元素,则会引发异常。
numpy.testing.assert_array_max_ulp(a, b, maxulp=1, dtype=None)
:确定数组元素最多相差 ULP 的指定数量。
numpy.testing.assert_equal()
:测试两个 NumPy 数组是否相等。
numpy.testing.assert_raises()
:如果使用定义的参数调用的可调用对象未引发指定的异常,则失败。
numpy.testing.assert_string_equal()
:断言两个字符串相等。
numpy.testing.assert_warns()
:如果未引发指定的警告,则失败。
numpy.bartlett(M)
:返回带有M
点的 Bartlett 窗口。 此窗口类似于三角形窗口。
numpy.random.binomial(n, p, size=None)
:从二项分布中抽取随机样本。
numpy.bitwise_and(x1, x2[, out])
:计算数组的按位AND
。
numpy.bitwise_xor(x1, x2[, out])
:计算数组的按位XOR
。
numpy.blackman(M)
:返回一个具有M
点的布莱克曼窗口,该窗口接近最佳值,并且比凯撒窗口差。
numpy.column_stack(tup)
:堆叠以元组列形式提供的一维数组 。
numpy.concatenate ((a1, a2, ...), axis=0)
:将数组序列连接在一起。
numpy.convolve(a, v, mode='full')
:计算一维数组的线性卷积。
numpy.dot(a, b, out=None)
:计算两个数组的点积。
numpy.diff(a, n=1, axis=-1)
:计算给定轴的 N 阶差。
numpy.dsplit(ary, indices_or_sections)
:沿着第三轴将数组拆分为子数组。
numpy.dstack(tup)
:沿第三轴堆叠以元组形式给出的数组。
numpy.eye(N, M=None, k=0, dtype=
:返回单位矩阵。
numpy.extract(condition, arr)
:使用条件选择数组的元素。
numpy.fft.fftshift(x, axes=None)
:将信号的零频率分量移到频谱的中心。
numpy.hamming(M)
:返回带有M
点的汉明窗口。
numpy.hanning(M)
:返回具有M
点的汉宁窗口。
numpy.hstack(tup)
:水平堆叠以元组形式给出的数组。
numpy.isreal(x)
:返回一个布尔数组,其中True
对应于输入数组的实数(而不是复数)元素。
numpy.kaiser(M, beta)
:对于给定的beta
参数,返回带有M
点的凯撒窗口。
numpy.load(file, mmap_mode=None)
:从.npy
,.npz
,或腌制中加载 NumPy 数组或腌制对象。 内存映射的数组存储在文件系统中,不必完全加载到内存中。 这对于大型数组尤其有用。
numpy.loadtxt(fname, dtype=
:将文本文件中的数据加载到 NumPy 数组中。
numpy.lexsort (keys, axis=-1)
:使用多个键进行排序。
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
:返回在间隔内均匀间隔的数字。
numpy.max(a, axis=None, out=None, keepdims=False)
:沿轴返回数组的最大值。
numpy.mean(a, axis=None, dtype=None, out=None, keepdims=False)
:沿给定轴计算算术平均值。
numpy.median(a, axis=None, out=None, overwrite_input=False)
:沿给定轴计算中位数 。
numpy.meshgrid(*xi, **kwargs)
:返回坐标向量的坐标矩阵。 例如:
In: numpy.meshgrid([1, 2], [3, 4])
Out:
[array([[1, 2],
[1, 2]]), array([[3, 3],
[4, 4]])]
numpy.min(a, axis=None, out=None, keepdims=False)
:沿轴返回数组的最小值。
numpy.msort(a)
:返回沿第一轴排序的数组的副本。
numpy.nanargmax(a, axis=None)
:返回给定一个忽略 NaN 的轴的最大值的索引。
numpy.nanargmin(a, axis=None)
:返回给定的轴的最小值索引,忽略 NaN。
numpy.nonzero(a)
:返回非零数组元素的索引。
numpy.ones(shape, dtype=None, order='C')
:创建指定形状和数据类型的 NumPy 数组,包含 1s。
numpy.piecewise(x, condlist, funclist, *args, **kw)
:分段求值函数。
numpy.polyder(p, m=1)
:将多项式微分为给定阶数。
numpy.polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False)
:执行最小二乘多项式拟合。
numpy.polysub(a1, a2)
:减去多项式。
numpy.polyval(p, x)
:以指定值求值多项式。
numpy.prod(a, axis=None, dtype=None, out=None, keepdims=False)
:返回指定轴上数组元素的乘积 。
numpy.ravel(a, order='C')
:展平数组,或在必要时返回副本。
numpy.reshape(a, newshape, order='C')
:更改 NumPy 数组的形状 。
numpy.row_stack(tup)
:逐行堆叠数组。
numpy.save(file, arr)
:以 NumPy .npy
格式将 NumPy 数组保存到文件中。
numpy.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ')
:将 NumPy 数组保存到文本文件。
numpy.sinc(a)
:计算sinc
函数。
numpy.sort_complex(a)
:首先以实部,然后是虚部对数组元素进行排序。
numpy.split(a, indices_or_sections, axis=0)
:将数组拆分为子数组。
numpy.std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False)
:沿给定轴返回标准差。
numpy.take(a, indices, axis=None, out=None, mode='raise')
:使用指定的索引从数组中选择元素。
numpy.vsplit(a, indices_or_sections)
:将数组垂直拆分为子数组。
numpy.vstack(tup)
:垂直堆叠数组。
numpy.where(condition, [x, y])
:基于布尔条件从输入数组中选择数组元素。
numpy.zeros(shape, dtype=float, order='C')
:创建指定形状和数据类型的 NumPy 数组,其中包含零。