Sonolus Wiki

09. Note Spawning

In this chapter, we will implementing spawning logic of Note.

Target Time

We first need to calculate a note's target time. Sonolus.js provides bindings to convert beat directly to time using the low level functions provided by Sonolus.

Because target time is an unchanging property of each note entity and needed for spawning logic, we should calculate it once during preprocess and store it in Entity Memory:

export class Note extends Archetype {
    // ...

    targetTime = this.entityMemory(Number)

    preprocess() {
        this.targetTime = bpmChanges.at(this.import.beat).time
    }

    // ...
}
export class Note extends Archetype {
    // ...

    targetTime = this.entityMemory(Number)

    preprocess() {
        this.targetTime = bpmChanges.at(this.import.beat).time
    }

    // ...
}

Spawn Time

With target time calculated, let's say we want notes to spawn 1 second early and falls down from above in order to give player time to prepare, we can calculate spawn time.

Just like target time, spawn time is also an unchanging property of each note entity and needed for spawning logic, we should calculate it once during preprocess and store it in Entity Memory:

export class Note extends Archetype {
    // ...

    spawnTime = this.entityMemory(Number)

    preprocess() {
        // ...

        this.spawnTime = this.targetTime - 1
    }

    // ...
}
export class Note extends Archetype {
    // ...

    spawnTime = this.entityMemory(Number)

    preprocess() {
        // ...

        this.spawnTime = this.targetTime - 1
    }

    // ...
}

Spawning Logic

Notes should be spawned in order of their spawn time, but we also need to make sure notes are spawned only after Initialization.

A simple way is to just add 1000:

export class Note extends Archetype {
    // ...

    spawnOrder() {
        return 1000 + this.spawnTime
    }

    // ...
}
export class Note extends Archetype {
    // ...

    spawnOrder() {
        return 1000 + this.spawnTime
    }

    // ...
}

For shouldSpawn, the logic would be to simply compare current time to spawn time:

export class Note extends Archetype {
    // ...

    shouldSpawn() {
        return time.now >= this.spawnTime
    }

    // ...
}
export class Note extends Archetype {
    // ...

    shouldSpawn() {
        return time.now >= this.spawnTime
    }

    // ...
}