区块与共享不可变数据
在本章中,您将会学习到:
- 区块的概念
- 如何声明区块变量
- 如何访问区块变量
区块
在之前的章节中,Initialization
原型已经变换了我们的屏幕坐标系,以更好的满足我们引擎的需要。然而,其他原型目前还并不知道如何渲染。比如说,Stage
原型负责渲染判定线,也就是简单地从 x = screen.l
到 x = screen.r
画一条线,但目前它还不知道左右的界限在哪里。
Initialization
原型拥有这些数据,并且必须将这些数据分享给其它原型,但我们该怎么做?
区块是 Sonolus 的内存共享机制,由一段简单的连续内存块组成。通过 Sonolus 提供的低级函数,您可以简单地访问这些内存块。举个例子,当我们使用 EntityDespawn.set(0, true)
销毁实体时,我们实际做的是调用 Set
低级函数,其参数指向 EntityDespawn
区块中的 despawn
标记。
Sonolus.h 抽象化了这些低级操作并将其转化为了对开发者友好的 API。
LevelData
区块
为了达成我们的目的,我们可以使用一个区块写入任意值并且读取他们。Sonolus 有许多能够用作通用内存存储的区块,其中我们需要特别注意的一个区块就是 LevelData
区块。
LevelData
区块只能在 preprocess
回调函数中被写入,在之后它将不允许写入,只允许读取。其不可变性会有性能上的优化,并且随后所有读取 LevelData
区块的操作都将作为常量内联,这使得其有更加优良的性能,更适合我们的共享不可变数据。
声明
我们需要让 Stage
原型知道新的判定线的左右边界,并让 Note
原型知道新的半径。让我们定义:
class JudgeLine {
public:
Variable<LevelDataId> l;
Variable<LevelDataId> r;
Variable<LevelDataId> y;
}judgeLine;
class Note {
public:
Variable<LevelDataId> radius;
}note;
访问
现在我们就可以像正常的变量一样访问他们:
class Initialization: public Archetype {
// ...
SonolusApi preprocess() {
FUNCBEGIN
// ...
judgeLine.l = screen.l;
judgeLine.r = screen.r;
judgeLine.y = judgeLineY;
note.radius = noteRadius;
// ...
return VOID;
}
// ...
};