Sonolus Wiki

05. 区块和共享不可变数据

在本章中,我们将回顾区块的概念,以及如何在原型之间共享不可变的数据。

区块

在上一章中,初始化实体已经改变了我们的屏幕坐标系,来更好地适应我们引擎的需求。然而,其他原型现在不知道它们应该如何显示出来了。例如,舞台原型负责渲染判定线,它本来只是简单地从x = screen.l绘制到x = screen.r ,但现在它不知道应该向左或向右绘制多远了。

初始化实体保存了这些信息,它必须与其他原型共享这部分数据,但我们如何做到这一点?

区块是 Sonolus 中的内存共享机制。区块只是连续的内存块,可以通过 Sonolus 提供的低级函数访问。例如,当我们使用this.despawn = true取消生成时,它在后台的工作是调用低级Set函数,参数指向 Entity Despawn 块中的 despawn 标志。

Sonolus.js 抽象了这些低级操作并将其包装在一个对开发人员友好的 API 中。

关卡数据区块

为了能够让我们做到任何想做的事,我们可以使用一个区块,让我们写入任意值以及读取它们。有许多区块用于通用内存存储,但我们应该特别注意的一个是关卡数据区块。

关卡数据区块只能在preprocess回调期间写入,之后它就不可变了,只能读取。这种不可变性会带来表现上的优化,并且未来关于关卡数据区块读取的操作都将作为常量内联,使其具有极高的性能并适合共享不可变数据。

声明

我们需要让舞台原型知道新的判定线的左右坐标,同时让音符原型知道新的半径。让我们声明它们:

export const judgeLine = levelData({
    l: Number,
    r: Number,
})
export const judgeLine = levelData({
    l: Number,
    r: Number,
})
export const note = levelData({
    radius: Number,
})
export const note = levelData({
    radius: Number,
})

访问

现在我们可以像访问常规变量一样简单地访问它们:

export class Initialization extends Archetype {
    preprocess() {
        // ...

        judgeLine.l = screen.l / h
        judgeLine.r = screen.r / h

        note.radius = noteRadius / h

        // ...
    }

    // ...
}
export class Initialization extends Archetype {
    preprocess() {
        // ...

        judgeLine.l = screen.l / h
        judgeLine.r = screen.r / h

        note.radius = noteRadius / h

        // ...
    }

    // ...
}