Skip to content

10 Replay ​

In this chapter, we will implement replay logic of Note.

Judgment and Accuracy ​

Replay recreates the recorded gameplay in watch mode.

In order to achieve that, we need the judgment and accuracy information:

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

    import = this.defineImport({
        // ...
        judgment: { name: EngineArchetypeDataName.Judgment, type: DataType<Judgment> },
        accuracy: { name: EngineArchetypeDataName.Accuracy, type: Number },
    })

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

    import = this.defineImport({
        // ...
        judgment: { name: EngineArchetypeDataName.Judgment, type: Number },
        accuracy: { name: EngineArchetypeDataName.Accuracy, type: Number },
    })

    // ...
}

Despawn Time ​

We accuracy, we can adjust despawn time accordingly:

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

    despawnTime() {
        return replay.isReplay
            ? timeScaleChanges.at(this.targetTime + this.import.accuracy).scaledTime
            : this.visualTime.max
    }

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

    despawnTime() {
        return replay.isReplay
            ? timeScaleChanges.at(this.targetTime + this.import.accuracy).scaledTime
            : this.visualTime.max
    }

    // ...
}

SFX ​

Similarly, we can adjust SFX based on both judgment and accuracy:

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

    preprocess() {
        // ...

        if (replay.isReplay) {
            const hitTime = this.targetTime + this.import.accuracy

            switch (this.import.judgment) {
                case Judgment.Perfect:
                    effect.clips.perfect.schedule(hitTime, 0.02)
                    break
                case Judgment.Great:
                    effect.clips.great.schedule(hitTime, 0.02)
                    break
                case Judgment.Good:
                    effect.clips.good.schedule(hitTime, 0.02)
                    break
            }
        } else {
            effect.clips.perfect.schedule(this.targetTime, 0.02)
        }

        // ...
    }

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

    preprocess() {
        // ...

        if (replay.isReplay) {
            const hitTime = this.targetTime + this.import.accuracy

            switch (this.import.judgment) {
                case Judgment.Perfect:
                    effect.clips.perfect.schedule(hitTime, 0.02)
                    break
                case Judgment.Great:
                    effect.clips.great.schedule(hitTime, 0.02)
                    break
                case Judgment.Good:
                    effect.clips.good.schedule(hitTime, 0.02)
                    break
            }
        } else {
            effect.clips.perfect.schedule(this.targetTime, 0.02)
        }

        // ...
    }

    // ...
}

Particle Effect ​

Lastly, we should skip playing particle effect if player did not hit the note:

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

    terminate() {
        // ...
        if (replay.isReplay && !this.import.judgment) return

        // ...
    }

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

    terminate() {
        // ...
        if (replay.isReplay && !this.import.judgment) return

        // ...
    }

    // ...
}