基本数据类型
数据类型
我们预定义了部分基本数据类型,如下:
var
Array<T, size>
Collection<T, size> // 等同于 C++ 中的 vector
Dictionary<T1, T2, size> = Map<T1, T2, size> // 等同于 C++ 中的 map
Matrix = Mat
Quadratic = Quad
Range = Rg
Rectangle = Rect
Vector = Vec // 并非 C++ 中的 vector
var- 基础变量类型。
- 变量存储的区块将会根据用户代码自动调整,目前只会自动分配
LevelMemory,EntityMemory和TemporaryMemory三个区块的内存。如果需要自行指定区块和偏移,请使用var a = var(EntitySharedMemory, offset);定义变量。 - 如果需要更换自动分配的区块 id,请修改
OptionId全局变量,并在分配完后记得将OptionId修改回去!
Array<T, size>- 定长数组类型。会根据
T和OptionId自动分配内存。 - 支持自定义 class 作为
T模板参数。
- 定长数组类型。会根据
Collection<T, size>- 不定长数组类型。通过
size指定预分配T数量。 - 支持自定义 class 作为
T模板参数。
- 不定长数组类型。通过
Dictionary<T1, T2, size>- 键值对类型。通过
size指定预分配T1,T2对数量。 - 支持自定义 class 作为
T模板参数。
- 键值对类型。通过
Matrix4x4矩阵类型。内部通过二维Array实现。- 可通过
Matrix.m[i][j]获取/修改矩阵第i行第j列的数据。
Quadratic- 四边形类型。内部通过两个
Array实现。 - 可通过
Quadratic.x[i]/Quadratic.y[i]获取/修改第i个顶点坐标。
- 四边形类型。内部通过两个
Range- 范围类型。内部通过
var min, max实现。
- 范围类型。内部通过
Rectangle- 矩形类型。内部通过
var l, b, r, t实现。
- 矩形类型。内部通过
VectorVector2D类型。内部通过var x, y实现。
var 变量
在 Sonolus.h 中,我们提供了 var 类型来简化开发者的数据存储过程。
var 类型内部包含两个成员变量,allocatorId(区块id) 以及 index(数据偏移)。
您可以将 Sonolus 的单个区块看成一大块连续内存,var 类型即为指向该区块中偏移为 index 内存的指针。
var 类型的构造函数如下:
var(); // 在默认区块上分配一块内存
var(FuncNode value); // 在默认区块上分配一块内存并赋值
var(double value); // 在默认区块上分配一块内存并赋值
var(int blockId, int index); // 直接定义一个指针,指向指定区块的指定偏移,不分配内存
var(int blockId, FuncNode index); // 直接定义一个指针,指向指定区块的指定偏移,不分配内存
var(const var &value); // 分配一块内存并进行拷贝
var(const var &value, int offset); // 直接定义一个指针,其指向的偏移为 value.index + offset。不分配内存
对于前三种构造方法,根据 var 类型被定义的位置不同,可以将 var 变量大致定义为三种类型: 原型外全局变量,原型内全局变量,函数局部变量。
var 类型变量几乎支持所有的操作符运算,这意味着您完全可以将 var 类型看作 C/C++ 中的 double 类型并正常编写代码。
对于取模运算,C/C++ 中的 double 类型是不支持的,但是 Sonolus 支持且将该运算扩展到了实数域,其结果应等同于 x % y = x - y * Ceil(x / y) 而非乘法逆元的运算结果。这在一些运算中非常有用。
原型外全局变量
原型外全局变量是在所有原型外部定义的全局变量,其默认分配的区块 id 为 LevelMemoryId/TutorialMemoryId/PreviewDataId/LevelMemoryId。
在定义原型外全局变量时,不允许使用赋值操作。您只能通过 var a; 或 var a = var(blockId, index); 或 var a = var(b, offset) 的方式初始化变量,否则会出现 '%s' block is not writable in '' callback at '' archetype! 的报错。
原型内全局变量
原型内全局变量是定义在单一原型内部的全局变量,其默认分配的区块 id 为 EntityMemoryId/-/EntitySharedMemoryId/EntityMemoryId。
在定义原型内全局变量时,同样不允许使用赋值操作。您只能通过 var a; 或 var a = var(blockId, index); 或 var a = var(b, offset) 的方式初始化变量,否则会出现 '%s' block is not writable in '%s' callback at '%s' archetype! 的报错。其中 callback 名和 archetype 并非真实的回调函数和原型名,应为上一个回调函数和原型名。
函数局部变量
函数局部变量是定义在函数内部的局部变量,其默认分配的区块 id 均为 TemporaryMemoryId。
函数局部变量的定义可以使用赋值操作。您在进行赋值操作的时候需要注意回调函数是否具有该区块的写入权限,否则会出现 '%s' block is not writable in '%s' callback at '%s' archetype! 的报错。其中 callback 名和 archetype 均为真实的回调函数和原型名。
样例
以下代码展示了三种变量的定义方法和使用方法。
// 定义原型外全局变量
var a;
var b = var(LevelDataId, 0);
var c = var(a, 1);
// 原型定义
class Test: public Archetype {
public:
string name = "Test Archetype";
bool hasInput = false;
// 定义原型内全局变量
var d;
var e = var(EntitySharedMemoryId, 0);
var f = var(d, 1);
SonolusApi preprocess() {
// 按需修改原型外全局变量和原型内全局变量
a = 1, b = 2, c = 3;
d = 4, e = 5, f = 6;
// 定义函数局部变量
var g = 0;
var h = var(TemporaryMemoryId, 0);
var i = var(g, 1);
var j = g * h + i;
}
}