高级SpriteList技术#

本页提供了高级技术的概述。不能保证可运行的示例,因为读者应该能够将工作投入到实现它们中。

初学者应该注意以下几个部分。如果使用不当,其中一些技术可能会降低您的游戏速度或使其崩溃。

绘图顺序排序(&S)#

在某些情况下,您可以结合SpriteList的两个功能:

首先,考虑其他选择#

在Python中,排序是一个很慢的、受CPU限制的函数。考虑使用以下技术来消除或最小化此成本:

  • 使用多个精灵列表或 arcade.Scene 实现分层

  • 将你的游戏世界分成更小的区域,每个区域都有精灵列表,只有当里面的东西移动或变化时才排序

  • 使用 Sprite.depth 具有的属性 shaders 在GPU上排序的步骤

有关商业2D游戏中使用的组块的概念性概述,请参阅以下内容:

排序SpriteList#

尽管上面列出的替代方法通常更好,但对精灵列表进行排序以控制绘制顺序仍然很有用。

就像Python的内置功能 list.sort() ,您可以传递一个 callable object 通过key参数指定如何排序,以及可选的 reverse 关键字来反转排序方向。

下面是一个如何使用排序来快速创建低效原型的示例:

import random
import arcade


# Warning: the bottom property is extra slow compared to other attributes!
def bottom_edge_as_sort_key(sprite):
    return sprite.bottom


class InefficientTopDownGame(arcade.Window):
    """
    Uses sorting to allow the player to move in front of & behind shrubs

    For non-prototyping purposes, other approaches will be better.
    """

    def __init__(self, num_shrubs=50):
        super().__init__(800, 600, "Inefficient Top-Down Game")

        self.background_color = arcade.color.SAND
        self.shrubs = arcade.SpriteList()
        self.drawable = arcade.SpriteList()

        # Randomly place pale green shrubs around the screen
        for i in range(num_shrubs):
            shrub = arcade.SpriteSolidColor(20, 40, color=arcade.color.BUD_GREEN)
            shrub.position = random.randrange(self.width), random.randrange(self.height)
            self.shrubs.append(shrub)
            self.drawable.append(shrub)

        self.player = arcade.SpriteSolidColor(16, 30, color=arcade.color.RED)
        self.drawable.append(self.player)

    def on_mouse_motion(self, x, y, dx, dy):
        # Update the player position
        self.player.position = x, y
        # Sort the sprites so the highest on the screen draw first
        self.drawable.sort(key=bottom_edge_as_sort_key, reverse=True)

    def on_draw(self):
        self.clear()
        self.drawable.draw()


game = InefficientTopDownGame()
game.run()

自定义纹理图集#

A TextureAtlas 表示 Texture 视频内存中并排打包的数据。随着纹理的添加,贴图集会增长以将它们全部放入您的GPU内存的同一部分。

默认情况下,每个 SpriteList 使用相同的默认地图集。使用 atlas 关键字参数指定实例的自定义地图集。

这对于防止在使用大纹理或形状奇怪的纹理时出现问题特别有用。

有关更多信息,请参阅以下内容:

懒惰精灵列表#

您可以延迟为 SpriteList 通过路过 lazy=True 关于创作:

sprite_list = SpriteList(lazy=True)

SpriteList不会创建OpenGL资源,除非受到以下任一条件的强制:

  1. 第一 SpriteList.draw() 呼唤它

  2. SpriteList.initialize()

  3. GPU支持的冲突(如果已启用

此行为在以下情况下最有用:

案例

主要目的

在窗口前创建SpriteList

仅限CPU unit tests 永远不会抽签

并行化SpriteList创建

通过以下方式实现更快的加载和世界生成 threadingsubprocess & pickle

并行加载#

为了提高加载速度并减少游戏过程中的卡顿,您可以并行运行游戏前任务,例如预先生成地图或将资源从磁盘预先加载到RAM中。

警告

只允许主线程访问OpenGL!

尝试从非主线程访问OpenGL将引发OpenGL错误!

为了安全地实现并行加载,在允许游戏开始之前,您需要使用以下一般方法:

  1. 经过 lazy=True 在创建时 SpriteList 如上所述,在加载代码中添加

  2. 加载完成后,将SpriteList数据同步回主线程或进程

  3. 在主线程内部,调用 Spritelist.initialize() 在每个精灵列表上,一旦它准备好分配GPU资源

非常高级的用户可以使用 subprocess 在另一个进程中创建SpriteList,并且 pickle 模块来帮助将数据传回主进程。

有关其他信息,请参阅以下内容: