highscores

main
mae 2024-01-12 02:02:14 +00:00
parent b226782295
commit caa8723afe
7 changed files with 222 additions and 19 deletions

6
debug.js Normal file
View File

@ -0,0 +1,6 @@
export function debugMsg(msg) {
fill(255);
stroke(0);
textSize(12);
text(msg, 24, 24);
}

37
highscore.js Normal file
View File

@ -0,0 +1,37 @@
class HighscoreManager {
constructor() {
this._deserialize();
}
_deserialize() {
let raw = localStorage.getItem('rhythm.hst');
if(!raw) {
this._highscores = {};
this._serialize();
} else {
this._highscores = JSON.parse(atob(raw));
}
}
_serialize() {
localStorage.setItem('rhythm.hst', btoa(JSON.stringify(this._highscores)));
}
getHighscore(songId) {
return this._highscores[songId]
}
setHighscore(songId, name, score) {
let existing = this.getHighscore(songId);
if(existing != undefined && existing.score <= score)
return;
this._highscores[songId] = {
name,
score
}
this._serialize();
}
}
export default new HighscoreManager();

46
main.js
View File

@ -1,25 +1,21 @@
import {
Entity,
Sprite
} from './entity.js';
import { GameScreen } from './screenGame.js';
import { SongSelectScreen } from './screenSongSelect.js';
import {
KeyHint
} from './ui.js'
import chartmgr from './chartmgr.js';
import state from './state.js';
import { HighscoreInputScreen } from './screenHighscoreInput.js'
import { debugMsg } from './debug.js';
import highscore from './highscore.js';
const charts = [
"bozo",
"dashstar",
"golddust",
"pixelpalace"
"pixelpalace",
// "test"
]
// STUFF
let songSelectScreen;
export let highscoreInputScreen;
// ASSETS
let sndBoop;
@ -32,13 +28,6 @@ function blur(col, blurFactor) {
drawingContext.shadowBlur = blurFactor;
}
function debugMsg(msg) {
fill(255);
stroke(0);
textSize(12);
text(msg, 24, 24);
}
function drawFps() {
let fps = frameRate();
fill(255);
@ -105,6 +94,18 @@ function draw() {
break;
}
if(window.gameScreen.song.duration() - 0.01 < window.gameScreen.song.currentTime()) {
if(
highscore.getHighscore(window.gameScreen.chart.id) == undefined
|| window.gameScreen.score.score > highscore.getHighscore(this.chart.id)
) {
highscoreInputScreen = new HighscoreInputScreen(window.gameScreen.chart.id, window.gameScreen.score.score);
state.setState("highscoreInput")
} else {
state.setState("songselect")
}
}
window.gameScreen.calcBeat();
window.gameScreen.draw();
@ -117,6 +118,15 @@ function draw() {
}
songSelectScreen.draw()
break;
case "highscoreInput":
if(!highscoreInputScreen) {
debugMsg(`ERROR: HSI BUT NO SETUP`)
break;
}
highscoreInputScreen.draw();
break;
}
drawFps();
@ -131,6 +141,10 @@ function keyPressed() {
case "songselect":
songSelectScreen.keyPressed()
break;
case "highscoreInput":
highscoreInputScreen.keyPressed();
break;
}
}

View File

@ -8,6 +8,7 @@ import { PressIndicator, Highway } from './highway.js';
import { Note } from './note.js';
import { ScoreManager } from './score.js'
import chartmgr from './chartmgr.js';
import { debugMsg } from './debug.js';
export class GameScreen {
constructor(chart) {
@ -109,7 +110,6 @@ export class GameScreen {
if(targetNotes[0].beat + GRACE_BEAT > pressBeat
&& targetNotes[0].beat - GRACE_BEAT < pressBeat
&& keyIsDown(KEYS[k.lane])){
// console.log("HIT", k.lane)
// hit note!
this.notes.find(n=> n.symbol == k.symbol).pressed = true;

114
screenHighscoreInput.js Normal file
View File

@ -0,0 +1,114 @@
import chartmgr from "./chartmgr.js"
import { Sprite } from './entity.js';
import highscore from "./highscore.js";
import state from "./state.js";
import { KeyHint } from "./ui.js";
import { sndBoop } from "./main.js";
class HighscoreSong extends Sprite {
static draw(img, name, artist, x, y) {
fill(255);
noStroke();
let wth = 0;
textSize(18);
let artistTextWidth = textWidth(artist);
textSize(24);
let songTextWidth = textWidth(artist);
wth += Math.max(artistTextWidth, songTextWidth)
wth += 128
fill(50)
rect(x - (wth / 2) - 16, y - 16, wth + 32, 64 + 32, 8)
fill(255)
textSize(18);
text(artist, x + 64 + 16 - (wth / 2), y + 56)
textSize(24);
text(name, x + 64 + 16 - (wth / 2), y + 32)
image(img, x - (wth / 2), y, 64, 64);
}
}
export class HighscoreInputScreen {
constructor(...args) {
this._init(...args);
this.name = "";
}
async _init(songId, score) {
this.song = await chartmgr.get(songId);
this.cover = chartmgr.covers.get(songId);
this.score = score;
}
draw() {
if(!this.song)
return;
let bigTitle = "NEW HIGHSCORE!";
fill(255);
textSize(64);
let bigTitleW = (width - textWidth(bigTitle));
text(bigTitle, bigTitleW / 2, 128);
HighscoreSong.draw(this.cover, this.song.name, this.song.artist,
width / 2,
(height / 2) - 128
)
fill(255);
textSize(48);
text(this.score, (bigTitleW / 2) + 128 + 32, 256 + 128 + 32 + 4);
fill(255);
textSize(24);
text("NAME:", bigTitleW / 2, 256 + 128);
for(let i = 0; i < 3; i++) {
fill(255);
if(i == this.name.length && (frameCount % 32) > 16) {
console.log(i)
fill(255,255,255,0)
}
text((this.name.length > i) ? this.name[i] : "_", (bigTitleW / 2) + (i*20), 256 + 128 + 36);
}
if(this.name.length > 2)
KeyHint.draw("Enter", (bigTitleW / 2) + 8 + 64, 256 + 128 + 36 - 4)
}
keyPressed() {
switch(keyCode) {
case 8: // backspace
this.name = this.name.slice(0, this.name.length - 1)
return;
case 13: //enter
if(this.name.length > 2) {
sndBoop.play();
highscore.setHighscore(this.song.id, this.name, this.score)
state.setState("songselect")
}
return;
}
if(this.name.length > 2)
return
// special characters are > 1 letter (eg. SHIFT)
if(key.length > 1)
return;
// regex to check if letter
if(!key.match(/[a-z]/i))
return
sndBoop.play();
this.name += key.toUpperCase();
}
}

View File

@ -2,6 +2,7 @@ import state from './state.js';
import chartmgr from './chartmgr.js';
import { KeyHint } from './ui.js'
import { sndBoop, sndSongselect } from './main.js';
import highscore from './highscore.js';
export class SongSelectScreen {
constructor() {
@ -25,16 +26,19 @@ export class SongSelectScreen {
// current song
image(this.covers[this.curSelection], (width-256)/2, (height-256)/2, 256, 256)
// song name
textSize(48);
text(this.songs[this.curSelection].name,
(width / 2) - (textWidth(this.songs[this.curSelection].name) / 2),
height - 128 - 36);
// song artist
textSize(24);
text(this.songs[this.curSelection].artist,
(width / 2) - (textWidth(this.songs[this.curSelection].artist) / 2),
height - 128);
// song meta
let etcmeta = this.songs[this.curSelection].difficulty + " - " + this.songs[this.curSelection].len
textSize(18);
@ -42,6 +46,8 @@ export class SongSelectScreen {
(width - textWidth(etcmeta) ) / 2,
height - 128 + 32);
// cover art side
let nextSelection = (this.curSelection + 1 > this.songs.length - 1)
? 0
: this.curSelection + 1
@ -55,6 +61,30 @@ export class SongSelectScreen {
image(this.covers[nextSelection],
(width - 128) - 32, (height - 128) / 2, 128, 128);
noStroke()
textSize(24);
if(highscore.getHighscore(this.songs[this.curSelection].id) != undefined) {
let hsw = textWidth("HIGH SCORE")
text("HIGH SCORE",
((width - hsw) / 2) - 48,
height - 512 - 64
);
textSize(16);
text(highscore.getHighscore(this.songs[this.curSelection].id).name,
((width - hsw) / 2) - 48,
height - 512 - 32
);
textAlign(RIGHT);
text(highscore.getHighscore(this.songs[this.curSelection].id).score,
(((width + 256) / 2)),
height - 512 - 32
);
textAlign(LEFT);
}
}
async keyPressed() {

6
ui.js
View File

@ -38,11 +38,13 @@ export class CurrentSongUi extends Sprite {
static draw(img, name, artist) {
fill(255);
image(img, (width / 2) + 175, 40 - 32 + 6, 64, 64 + 4);
textSize(18);
text(artist, (width / 2) + 175 + 40, 40 + 24)
text(artist, (width / 2) + 175 + 40 + 32 + 4, 40 + 24 + 4)
textSize(24);
text(name, (width / 2) + 175 + 40, 40)
text(name, (width / 2) + 175 + 40 + 32 + 4, 40 + 4)
}
}