Sonolus Wiki

06. 打印时间

在本章中,我们将实现时间打印。

打印

即使预览模式已经工作并且我们可以看见所有音符,但对于玩家来说很容易在滚动屏幕时迷失。

这就是为什么我们在面板的每一边留下了一些空间,因此我们可以打印有用的信息,比如说时间和刻度。在接下来的章节中,我们还将使用这些空间打印 BPM 和倍速。

让我们使用一个实用函数来更简单地打印信息:

export const print = (
    value: number,
    time: number,
    format: PrintFormat,
    decimalPlaces: number | 'auto',
    color: PrintColor,
    side: 'left' | 'right',
) =>
    canvas.print({
        value,
        format,
        decimalPlaces,
        anchor: getAnchor(panel.getPos(time).translate(side === 'left' ? -1.5 : 1.5, 0)),
        pivot: { x: side === 'left' ? 1 : 0, y: 0.5 },
        size: { x: screen.h / 10, y: screen.h / 20 },
        rotation: 0,
        color,
        alpha: 1,
        horizontalAlign: side === 'left' ? HorizontalAlign.Right : HorizontalAlign.Left,
        background: false,
    })

const getAnchor = (pos: Vec) => {
    const anchor = pos.transform(skin.transform)
    anchor.y = Math.clamp(anchor.y, screen.b + screen.h / 40, screen.t - screen.h / 40)

    return anchor
}
export const print = (value, time, format, decimalPlaces, color, side) =>
    canvas.print({
        value,
        format,
        decimalPlaces,
        anchor: getAnchor(panel.getPos(time).translate(side === 'left' ? -1.5 : 1.5, 0)),
        pivot: { x: side === 'left' ? 1 : 0, y: 0.5 },
        size: { x: screen.h / 10, y: screen.h / 20 },
        rotation: 0,
        color,
        alpha: 1,
        horizontalAlign: side === 'left' ? HorizontalAlign.Right : HorizontalAlign.Left,
        background: false,
    })

const getAnchor = (pos) => {
    const anchor = pos.transform(skin.transform)
    anchor.y = Math.clamp(anchor.y, screen.b + screen.h / 40, screen.t - screen.h / 40)

    return anchor
}

这个实用函数在特定时间简单地绘制了一个值,并提供一些选项。另外它还确保了当它过于接近屏幕的顶部和底部时,打印出的文字总是可见的。

时间

现在我们可以遍历持续时间,并在每一秒打印一次:

export class Stage extends Archetype {
    // ...

    render() {
        // ...

        this.printTimes()
    }

    // ...

    printTimes() {
        for (let i = 1; i <= Math.floor(chart.duration); i++) {
            print(i, i, PrintFormat.Time, 0, PrintColor.Neutral, 'left')
        }
    }
}
export class Stage extends Archetype {
    // ...

    render() {
        // ...

        this.printTimes()
    }

    // ...

    printTimes() {
        for (let i = 1; i <= Math.floor(chart.duration); i++) {
            print(i, i, PrintFormat.Time, 0, PrintColor.Neutral, 'left')
        }
    }
}

注意到我们从 1 开始而不是 0,这是因为在关卡开始会有 BPM 变化和倍速变化,我们不想遮挡它们。

尽管它可能因引擎而异,但我们经常在左边打印与时间相关的信息,在右边打印与节拍相关的信息。时间经常以中性色绘制,这样不会引起过多注意。