nise/nise-frontend/src/corelib/components/replay-viewer/replay-viewer.component.ts

110 lines
2.6 KiB
TypeScript
Raw Normal View History

2024-02-29 02:02:14 +00:00
import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {getEvents} from "./decode-replay";
import {DecimalPipe, JsonPipe} from "@angular/common";
import {beatmapData, replayData} from "./sample-replay";
import {ReplayService} from "./replay-service";
import {FormsModule} from "@angular/forms";
import {parseHitObjects} from "./decode-beatmap";
import {processReplay} from "./process-replay";
export enum KeyPress {
M1 = 1,
M2 = 2,
K1 = 5,
K2 = 10,
Smoke = 16,
}
export interface ReplayEvent {
/**
* Time in milliseconds since the previous action
*/
timeDelta: number;
/**
* x-coordinate of the cursor from 0 - 512
*/
x: number;
/**
* y-coordinate of the cursor from 0 - 384
*/
y: number;
/**
* Key being pressed.
*/
key: KeyPress;
}
@Component({
selector: 'app-replay-viewer',
standalone: true,
imports: [
JsonPipe,
FormsModule,
DecimalPipe
],
templateUrl: './replay-viewer.component.html',
styleUrl: './replay-viewer.component.css'
})
export class ReplayViewerComponent implements OnInit, AfterViewInit {
@ViewChild('replayCanvas') replayCanvas!: ElementRef<HTMLCanvasElement>;
private ctx!: CanvasRenderingContext2D;
2024-03-01 11:52:12 +00:00
// TODO: Calculate AudioLeadIn
// TODO: Calculate circle size (CS)
// TODO: Hard-Rock, DT, Easy
// TODO: Cursor trail and where keys are pressed
// TODO: Button for -100 ms, +100 ms, etc (precise seeking) (or keyboard shortcuts)
// TODO: Way to obtain replay+beatmap info from the backend
// TODO: UR bar
// Todo: Customizable speed
// TODO: Customizable zoom
// TODO: Fullscreen mode
// TODO: Hit/Miss, Combo, Accuracy
// TODO: Compare two replays for similarity (different cursor color)
2024-02-29 02:02:14 +00:00
constructor(public replayService: ReplayService) { }
ngOnInit() {
// Assume getEvents() method returns a promise of ReplayEvent[]
getEvents(replayData).then(events => {
this.replayService.setEvents(processReplay(events));
this.replayService.setHitObjects(parseHitObjects(beatmapData))
});
}
ngAfterViewInit() {
this.ctx = this.replayCanvas.nativeElement.getContext('2d')!;
this.replayService.setCanvasElement(this.replayCanvas);
this.replayService.setCanvasContext(this.ctx);
this.replayService.start(); // Start the animation loop
}
togglePlayPause() {
if (this.replayService.getIsPlaying()) {
this.replayService.pause();
} else {
this.replayService.start();
}
}
seek(time: number) {
this.replayService.seek(time);
if (!this.replayService.getIsPlaying()) {
// Redraw the canvas for the new current time without resuming playback
}
}
}