基本数据类型
数据类型
我们预定义了部分基本数据类型,如下:
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
模板参数。
- 键值对类型。通过
Matrix
4x4
矩阵类型。内部通过二维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
实现。
- 矩形类型。内部通过
Vector
Vector2D
类型。内部通过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;
}
}