Sonolus Wiki

05. Note Drawing

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

Declaring

Declare the note skin sprite to be used:

export const skin = defineSkin({
    sprites: {
        // ...
        note: SkinSpriteName.NoteHeadCyan,
    },
})
export const skin = defineSkin({
    sprites: {
        // ...
        note: SkinSpriteName.NoteHeadCyan,
    },
})

Scaled Screen

Unlike in play mode, in preview we have changed screen coordinate system to have different scaling in X and Y axis.

In order for notes to draw correctly, we should provide a width to height scaling factor:

export const scaledScreen = {
    wToH: panel.h / 20,
}
export const scaledScreen = {
    wToH: panel.h / 20,
}

Calculating Position

Using panel's parameters, we can calculate position at a certain time.

export const panel = {
    // ...

    getX(time: number) {
        return Math.floor(time / this.h) * this.w
    },

    getY(time: number) {
        return time % this.h
    },

    getPos(time: number) {
        return new Vec(this.getX(time), this.getY(time))
    },
}
export const panel = {
    // ...

    getX(time) {
        return Math.floor(time / this.h) * this.w
    },

    getY(time) {
        return time % this.h
    },

    getPos(time) {
        return new Vec(this.getX(time), this.getY(time))
    },
}

Drawing

With all the above, we can draw the note sprite of correct size at the correct position:

export class Note extends Archetype {
    // ...

    render() {
        const time = bpmChanges.at(this.import.beat).time
        const pos = panel.getPos(time)

        const layout = Rect.one.mul(options.noteSize).scale(1, scaledScreen.wToH).add(pos)
        const z = 1000 - time

        skin.sprites.note.draw(layout, z, 1)
    }
}
export class Note extends Archetype {
    // ...

    render() {
        const time = bpmChanges.at(this.import.beat).time
        const pos = panel.getPos(time)

        const layout = Rect.one.mul(options.noteSize).scale(1, scaledScreen.wToH).add(pos)
        const z = 1000 - time

        skin.sprites.note.draw(layout, z, 1)
    }
}