Sonolus Wiki

04. Screen Coordinate System

In this chapter, we will go over the screen coordinate system and how to transform it for our engine.

Default

Sonolus uses a default screen coordinate system where (0, 0) lies on center of the screen, with y goes from -1 (bottom) to 1 (top), and x goes from -1 * screen.aspectRatio (left) to screen.aspectRatio (right). These values are provided in the screen object, as well as a convenient property screen.rect.

Transform

Although you can write engines with the default screen coordinate system, it is more convenient to first transform it to suit specific engine's needs.

In VSRGs (Vertical Scroll Rhythm Games), a commonly used coordinate system has y goes from 0 (top of note spawn) to 1 (judgment line), and the center lane lies on x = 0, where each unit is one lane (for example, x = 2 would be two lanes to the right of center lane).

Calculate and Apply

Let's calculate and apply this transformation to our engine.

In the default screen coordinate system, let's decide that our notes should has a radius of 0.2, which spawn from just outside of player's view (screen.t + radius) and fall to the judgment line at y = -0.6. As for x, since our engine only has one lane, we can simply scale it the same as y.

Since we don't intend on our screen coordinate system to change, we can do it in preprocess of Initialization:

export class Initialization extends Archetype {
    preprocess() {
        const noteRadius = 0.2
        const judgeLineY = -0.6

        const t = screen.t + noteRadius
        const b = judgeLineY
        const h = t - b

        const transform = Mat.identity.scale(h, -h).translate(0, t)

        skin.transform.set(transform)
        particle.transform.set(transform)

        // ...
    }

    // ...
}
export class Initialization extends Archetype {
    preprocess() {
        const noteRadius = 0.2
        const judgeLineY = -0.6

        const t = screen.t + noteRadius
        const b = judgeLineY
        const h = t - b

        const transform = Mat.identity.scale(h, -h).translate(0, t)

        skin.transform.set(transform)
        particle.transform.set(transform)

        // ...
    }

    // ...
}