add all code

main
etstringy 2024-01-05 14:48:28 +00:00
commit 516f756124
34 changed files with 6467 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# /charts/*
# !/charts/test
.DS_Store

Binary file not shown.

BIN
assets/sfx/boop.mp3 Normal file

Binary file not shown.

BIN
assets/sfx/combobreak.mp3 Normal file

Binary file not shown.

BIN
assets/sfx/songselect.mp3 Normal file

Binary file not shown.

31
chartmgr.js Normal file
View File

@ -0,0 +1,31 @@
import { GameScreen } from "./screenGame.js";
/**
* Chart Manager
* Loads charts from server
*/
class ChartManager {
constructor() {
this.cache = new Map();
this.covers = new Map();
}
async get(id) {
if(!this.cache.has(id)) {
await fetch("./charts/" + id + "/chart.json")
.then(res => res.json())
.then(json => this.cache.set(id, json))
this.covers.set(id, loadImage("./charts/" + id + "/cover.jpg"));
}
return this.cache.get(id)
}
async loadChart(selectedChart) {
console.log("loading", selectedChart)
let ch = await this.get(selectedChart)
return new GameScreen(ch);
}
}
export default new ChartManager();

BIN
charts/bozo/bozo.mp3 Normal file

Binary file not shown.

2775
charts/bozo/chart.json Normal file

File diff suppressed because it is too large Load Diff

BIN
charts/bozo/cover.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

1139
charts/dashstar/chart.json Normal file

File diff suppressed because it is too large Load Diff

BIN
charts/dashstar/cover.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

779
charts/golddust/chart.json Normal file
View File

@ -0,0 +1,779 @@
{
"id": "golddust",
"file": "golddust.mp3",
"name": "Gold Dust",
"artist": "DJ Fresh",
"bpm": 177,
"difficulty": "Medium",
"len": "1:32",
"notes": [
{
"beat": 5,
"lane": 0
},
{
"beat": 6.5,
"lane": 0
},
{
"beat": 8,
"lane": 0
},
{
"beat": 9.5,
"lane": 0
},
{
"beat": 11,
"lane": 2
},
{
"beat": 12.5,
"lane": 2
},
{
"beat": 13,
"lane": 3
},
{
"beat": 14.5,
"lane": 3
},
{
"beat": 16,
"lane": 3
},
{
"beat": 17.5,
"lane": 3
},
{
"beat": 19,
"lane": 3
},
{
"beat": 20.5,
"lane": 3
},
{
"beat": 21,
"lane": 1
},
{
"beat": 22.5,
"lane": 1
},
{
"beat": 24,
"lane": 1
},
{
"beat": 25.5,
"lane": 1
},
{
"beat": 27,
"lane": 1
},
{
"beat": 28.5,
"lane": 1
},
{
"beat": 29,
"lane": 3
},
{
"beat": 30.5,
"lane": 3
},
{
"beat": 32,
"lane": 3
},
{
"beat": 33.5,
"lane": 3
},
{
"beat": 35,
"lane": 3
},
{
"beat": 36.5,
"lane": 3
},
{
"beat": 37,
"lane": 0
},
{
"beat": 38.5,
"lane": 0
},
{
"beat": 40,
"lane": 0
},
{
"beat": 41.5,
"lane": 0
},
{
"beat": 43,
"lane": 2
},
{
"beat": 44.5,
"lane": 2
},
{
"beat": 45,
"lane": 3
},
{
"beat": 46.5,
"lane": 3
},
{
"beat": 48,
"lane": 3
},
{
"beat": 49.5,
"lane": 3
},
{
"beat": 51,
"lane": 3
},
{
"beat": 52.5,
"lane": 3
},
{
"beat": 53,
"lane": 1
},
{
"beat": 54.5,
"lane": 1
},
{
"beat": 56,
"lane": 1
},
{
"beat": 57.5,
"lane": 1
},
{
"beat": 59,
"lane": 1
},
{
"beat": 60.5,
"lane": 1
},
{
"beat": 61,
"lane": 3
},
{
"beat": 62.5,
"lane": 3
},
{
"beat": 64,
"lane": 3
},
{
"beat": 65.5,
"lane": 3
},
{
"beat": 67,
"lane": 3
},
{
"beat": 68.5,
"lane": 3
},
{
"beat": 69,
"lane": 0
},
{
"beat": 70.5,
"lane": 0
},
{
"beat": 72,
"lane": 0
},
{
"beat": 73.5,
"lane": 0
},
{
"beat": 75,
"lane": 1
},
{
"beat": 76.5,
"lane": 1
},
{
"beat": 77,
"lane": 2
},
{
"beat": 78.5,
"lane": 2
},
{
"beat": 80,
"lane": 2
},
{
"beat": 81.5,
"lane": 2
},
{
"beat": 83,
"lane": 2
},
{
"beat": 84.5,
"lane": 2
},
{
"beat": 85,
"lane": 1
},
{
"beat": 86.5,
"lane": 1
},
{
"beat": 88,
"lane": 1
},
{
"beat": 89.5,
"lane": 1
},
{
"beat": 91,
"lane": 1
},
{
"beat": 92.5,
"lane": 1
},
{
"beat": 93,
"lane": 3
},
{
"beat": 94.5,
"lane": 3
},
{
"beat": 96,
"lane": 3
},
{
"beat": 97.5,
"lane": 3
},
{
"beat": 99,
"lane": 3
},
{
"beat": 100.5,
"lane": 3
},
{
"beat": 101,
"lane": 0
},
{
"beat": 102.5,
"lane": 0
},
{
"beat": 104,
"lane": 0
},
{
"beat": 105.5,
"lane": 0
},
{
"beat": 107,
"lane": 2
},
{
"beat": 108.5,
"lane": 2
},
{
"beat": 109,
"lane": 3
},
{
"beat": 110.5,
"lane": 3
},
{
"beat": 112,
"lane": 3
},
{
"beat": 113.5,
"lane": 3
},
{
"beat": 115,
"lane": 3
},
{
"beat": 116.5,
"lane": 3
},
{
"beat": 117,
"lane": 1
},
{
"beat": 118.5,
"lane": 1
},
{
"beat": 120,
"lane": 1
},
{
"beat": 121.5,
"lane": 1
},
{
"beat": 123,
"lane": 1
},
{
"beat": 124.5,
"lane": 1
},
{
"beat": 125,
"lane": 2
},
{
"beat": 126.5,
"lane": 2
},
{
"beat": 128,
"lane": 2
},
{
"beat": 129.5,
"lane": 2
},
{
"beat": 131,
"lane": 2
},
{
"beat": 132.5,
"lane": 2
},
{
"beat": 133,
"lane": 0
},
{
"beat": 134.5,
"lane": 0
},
{
"beat": 136,
"lane": 0
},
{
"beat": 137.5,
"lane": 0
},
{
"beat": 139,
"lane": 2
},
{
"beat": 140.5,
"lane": 2
},
{
"beat": 141,
"lane": 3
},
{
"beat": 142.5,
"lane": 3
},
{
"beat": 144,
"lane": 3
},
{
"beat": 145.5,
"lane": 3
},
{
"beat": 147,
"lane": 3
},
{
"beat": 148.5,
"lane": 3
},
{
"beat": 149,
"lane": 1
},
{
"beat": 150.5,
"lane": 1
},
{
"beat": 152,
"lane": 1
},
{
"beat": 153.5,
"lane": 1
},
{
"beat": 155,
"lane": 1
},
{
"beat": 156.5,
"lane": 1
},
{
"beat": 157,
"lane": 3
},
{
"beat": 158.5,
"lane": 3
},
{
"beat": 160,
"lane": 3
},
{
"beat": 161.5,
"lane": 3
},
{
"beat": 163,
"lane": 3
},
{
"beat": 164.5,
"lane": 3
},
{
"beat": 165,
"lane": 0
},
{
"beat": 166.5,
"lane": 0
},
{
"beat": 168,
"lane": 0
},
{
"beat": 169.5,
"lane": 0
},
{
"beat": 171,
"lane": 2
},
{
"beat": 172.5,
"lane": 2
},
{
"beat": 173,
"lane": 3
},
{
"beat": 174.5,
"lane": 3
},
{
"beat": 176,
"lane": 3
},
{
"beat": 177.5,
"lane": 3
},
{
"beat": 179,
"lane": 3
},
{
"beat": 180.5,
"lane": 3
},
{
"beat": 181,
"lane": 1
},
{
"beat": 182.5,
"lane": 1
},
{
"beat": 184,
"lane": 1
},
{
"beat": 185.5,
"lane": 1
},
{
"beat": 187,
"lane": 1
},
{
"beat": 188.5,
"lane": 1
},
{
"beat": 189,
"lane": 3
},
{
"beat": 190.5,
"lane": 3
},
{
"beat": 192,
"lane": 3
},
{
"beat": 193.5,
"lane": 3
},
{
"beat": 195,
"lane": 3
},
{
"beat": 196.5,
"lane": 3
},
{
"beat": 197,
"lane": 0
},
{
"beat": 198.5,
"lane": 0
},
{
"beat": 200,
"lane": 0
},
{
"beat": 201.5,
"lane": 0
},
{
"beat": 203,
"lane": 1
},
{
"beat": 204.5,
"lane": 1
},
{
"beat": 205,
"lane": 2
},
{
"beat": 206.5,
"lane": 2
},
{
"beat": 208,
"lane": 2
},
{
"beat": 209.5,
"lane": 2
},
{
"beat": 211,
"lane": 2
},
{
"beat": 212.5,
"lane": 2
},
{
"beat": 213,
"lane": 1
},
{
"beat": 214.5,
"lane": 1
},
{
"beat": 216,
"lane": 1
},
{
"beat": 217.5,
"lane": 1
},
{
"beat": 219,
"lane": 1
},
{
"beat": 220.5,
"lane": 1
},
{
"beat": 221,
"lane": 3
},
{
"beat": 222.5,
"lane": 3
},
{
"beat": 224,
"lane": 3
},
{
"beat": 225.5,
"lane": 3
},
{
"beat": 227,
"lane": 3
},
{
"beat": 228.5,
"lane": 3
},
{
"beat": 229,
"lane": 0
},
{
"beat": 230.5,
"lane": 0
},
{
"beat": 232,
"lane": 0
},
{
"beat": 233.5,
"lane": 0
},
{
"beat": 235,
"lane": 2
},
{
"beat": 236.5,
"lane": 2
},
{
"beat": 237,
"lane": 3
},
{
"beat": 238.5,
"lane": 3
},
{
"beat": 240,
"lane": 3
},
{
"beat": 241.5,
"lane": 3
},
{
"beat": 243,
"lane": 3
},
{
"beat": 244.5,
"lane": 3
},
{
"beat": 245,
"lane": 1
},
{
"beat": 246.5,
"lane": 1
},
{
"beat": 248,
"lane": 1
},
{
"beat": 249.5,
"lane": 1
},
{
"beat": 251,
"lane": 1
},
{
"beat": 252.5,
"lane": 1
},
{
"beat": 253,
"lane": 2
},
{
"beat": 254.5,
"lane": 2
},
{
"beat": 256,
"lane": 2
},
{
"beat": 257.5,
"lane": 2
},
{
"beat": 259,
"lane": 2
},
{
"beat": 260.5,
"lane": 2
}
]
}

BIN
charts/golddust/cover.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

BIN
charts/pixelpalace/pp.mp3 Normal file

Binary file not shown.

20
charts/test/chart.json Normal file
View File

@ -0,0 +1,20 @@
{
"id": "test",
"file": "song.wav",
"name": "Test Chart",
"artist": "Untitled Band",
"len": "0:08",
"bpm": 120,
"notes": [
{ "beat": 2, "lane": 1},
{ "beat": 4, "lane": 0},
{ "beat": 4, "lane": 1},
{ "beat": 6, "lane": 2},
{ "beat": 8, "lane": 3},
{ "beat": 8.25, "lane": 3},
{ "beat": 8.5, "lane": 3},
{ "beat": 8.75, "lane": 3}
]
}

BIN
charts/test/song.wav Normal file

Binary file not shown.

16
config.js Normal file
View File

@ -0,0 +1,16 @@
export const KEYS = [
68, // D
70, // F
74, // J
75 // K
]
export const LANE_COLORS = [
[28, 237, 102],
[245, 201, 27],
[66, 110, 255],
[255, 94, 180]
];
export const GRACE_BEAT = 0.175;
export let NOTE_SPEED = 80; // this isnt a constant so players can adjust their notespeed
export const getPixelsPerBeat = () => NOTE_SPEED * 3.5

25
entity.js Normal file
View File

@ -0,0 +1,25 @@
/**
* Entity
* Anything with an X and Y
*/
export class Entity {
x;
y;
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
/**
* Sprite
* Anything that can be drawn to the screen
*/
export class Sprite extends Entity {
constructor(x = 0, y = 0) {
super(x, y)
}
draw() {
}
}

2
ext/p5.min.js vendored Normal file

File diff suppressed because one or more lines are too long

3
ext/p5.sound.min.js vendored Normal file

File diff suppressed because one or more lines are too long

114
highway.js Normal file
View File

@ -0,0 +1,114 @@
import { Sprite } from './entity.js';
import { LANE_COLORS, getPixelsPerBeat } from './config.js';
import { KeyHint } from './ui.js';
class BeatLine extends Sprite {
constructor() {
super((700 - 300) / 2, 40)
}
draw() {
stroke(190)
strokeWeight(1)
line(this.x, this.y, this.x + 300, this.y)
}
}
export class PressIndicator extends Sprite {
constructor(lane) {
super(((width - 300) / 2) + (75*lane), height - 40 - 24);
this.heldFor = 0;
this.laneTransparency = 0
this.transparency = 0
this.hit = false;
}
draw(held) {
// console.log("hf", this.heldFor, held)
if(held) {
if(this.hit) {
blur(color(255,255,255), 16)
if(this.heldFor == 0) {
this.transparency = 255
this.laneTransparency = 100
} else {
this.transparency = lerp(this.transparency, 50, 0.2)
}
} else {
this.transparency = lerp(this.transparency, 50, 0.6);
}
} else {
this.transparency = lerp(this.transparency, 0, 0.5)
}
fill(255, 255, 255, this.transparency)
noStroke()
rect(this.x, this.y, 75, 24)
// lane
this.laneTransparency = lerp(this.laneTransparency, 0, 0.05)
fill(255, 255, 255, this.laneTransparency)
noStroke()
rect(this.x, 0, 75, height)
if(this.hit) {
blur(0, 0)
}
if(!held && this.heldFor > 0)
this.heldFor = 0;
if(held)
this.heldFor += 1;
if(this.hit && held)
this.hit = false;
}
}
export class Highway extends Sprite {
constructor() {
super(0,0)
}
static draw(curBeat) {
noStroke()
blur(color(20), 16)
fill(140)
rect((width - 300) / 2, 0, 300, height)
blur(0, 0)
fill(80)
rect((width - 300) / 2, height - 28 - 12, 300, 28 + 12)
// purple bar
for(let i = 0; i < LANE_COLORS.length; i++) {
let c = color(LANE_COLORS[i][0], LANE_COLORS[i][1], LANE_COLORS[i][2])
fill(lerpColor(c, color(0), 0.5))
rect((width - 300) / 2 + ((300/4) * i), height - 28 - 24 - 12, (300 / 4), 24)
}
// Lines
let PIXELS_PER_BEAT = getPixelsPerBeat();
let beatLineX = height - 40
while(beatLineX > 0) {
stroke(170);
strokeWeight(2);
line(
(width - 300) / 2,
beatLineX + (PIXELS_PER_BEAT * (curBeat % 1) - 1),
(width - 300) / 2 + 300,
beatLineX + (PIXELS_PER_BEAT * (curBeat % 1) - 1)
);
beatLineX -= PIXELS_PER_BEAT;
}
KeyHint.draw("D", (width/2) + 182 - (300 / 4)*4, height - 14)
KeyHint.draw("F", (width/2) + 182 - (300 / 4)*3, height - 14)
KeyHint.draw("J", (width/2) + 182 - (300 / 4)*2, height - 14)
KeyHint.draw("K", (width/2) + 182 - (300 / 4)*1, height - 14)
}
}

28
index.html Normal file
View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
}
main {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<script src="./ext/p5.min.js"></script>
<script src="./ext/p5.sound.min.js"></script>
<!-- module type allows import+export-->
<script src="main.js" type="module"></script>
</body>
</html>

149
main.js Normal file
View File

@ -0,0 +1,149 @@
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';
const charts = [
"bozo",
"dashstar",
"golddust",
"pixelpalace"
// "test"
]
// STUFF
let songSelectScreen;
// ASSETS
let sndBoop;
let sndCombobreak;
let sndSongselect;
let fntRenogare;
function blur(col, blurFactor) {
drawingContext.shadowColor = col;
drawingContext.shadowBlur = blurFactor;
}
function debugMsg(msg) {
fill(255);
stroke(0);
textSize(12);
text(msg, 24, 24);
}
function drawFps() {
let fps = frameRate();
fill(255);
stroke(0);
textSize(12);
text("FPS: " + fps.toFixed(2), 10, height - 10);
}
async function preload() {
console.log("preloading..")
// load sounds
soundFormats('mp3')
sndCombobreak = loadSound('./assets/sfx/combobreak');
sndCombobreak.volume = 0.6
sndBoop = loadSound('./assets/sfx/boop')
sndBoop.volume = 0.6
sndSongselect = loadSound('./assets/sfx/songselect')
sndSongselect.volume = 0.4
// load fonts
fntRenogare = loadFont("./assets/fonts/Renogare-Regular.otf");
}
async function setup() {
console.log("setting up..")
// frameRate(144)
frameRate(60)
createCanvas(1280, 720)
for await (let chartid of charts) {
try {
await chartmgr.get(chartid)
} catch(e) {
console.log(`error loading chart ${chartid}`, e)
}
}
songSelectScreen = new SongSelectScreen();
// gameScreen = await chartmgr.loadChart('test')
}
function draw() {
textFont(fntRenogare);
background(10)
switch(state.state) {
case "game":
if(!window.gameScreen) {
debugMsg("err: gamescreen not initialized!")
break;
}
if(!window.gameScreen.song.isLoaded()) {
fill(255);
stroke(0);
textSize(12);
text("Loading song..", (width - textWidth("Loading song..")) / 2, height /2);
fill(40, 40, 255)
rect(0,0,window.gameScreen.loadPercent * width, 12)
break;
}
window.gameScreen.calcBeat();
window.gameScreen.draw();
break;
case "songselect":
if(!songSelectScreen) {
debugMsg(`loading charts (${chartmgr.cache.size}/${charts.length})`)
break;
}
songSelectScreen.draw()
break;
}
drawFps();
}
function keyPressed() {
switch(state.state) {
case "game":
window.gameScreen.checkHit();
break;
case "songselect":
songSelectScreen.keyPressed()
break;
}
}
// make p5 work in a js module environment because variables
// arent exposed to window by default in module
window.preload = preload;
window.setup = setup;
window.draw = draw;
window.keyPressed = keyPressed;
export {
sndCombobreak,
sndBoop,
sndSongselect,
fntRenogare
}

42
note.js Normal file
View File

@ -0,0 +1,42 @@
import { Sprite } from './entity.js';
import { GRACE_BEAT, LANE_COLORS, getPixelsPerBeat } from './config.js';
import { sndCombobreak } from './main.js';
let PIXELS_PER_BEAT = getPixelsPerBeat();
export class Note extends Sprite {
constructor(lane, beat) {
super((width - 300)/ 2 + (lane * 75) + 4, 0)
this.lane = lane;
this.beat = beat;
this.symbol = Symbol();
this.pressed = false;
}
draw(curBeat) {
strokeWeight(2);
stroke(6);
fill(LANE_COLORS[this.lane])
rect(this.x, this.y, 68, 16) // 20
let initialPos = ((height - 40) - 20 / 2)
this.y = initialPos - (PIXELS_PER_BEAT * (this.beat - curBeat))
if(this.beat + GRACE_BEAT < curBeat) {
// remove note from array
this.remove();
if(!this.pressed) {
// sndIncorrect.play();
if(window.gameScreen.score.combo > 4) {
sndCombobreak.play();
}
window.gameScreen.score.combo = 0;
}
}
}
remove() {
window.gameScreen.notes.splice(window.gameScreen.notes.findIndex(n => n.symbol == this.symbol), 1);
}
}

19
score.js Normal file
View File

@ -0,0 +1,19 @@
export class ScoreManager {
constructor() {
this.score = 0;
this.combo = 0
}
addScore(toAdd) {
this.score += toAdd
}
onHit() {
this.combo += 1;
this.score += 200 * Math.min(1, (Math.min(this.combo, 16) /4))
}
resetCombo() {
this.combo = 0;
}
}

123
screenGame.js Normal file
View File

@ -0,0 +1,123 @@
import {
ScoreUi,
CurrentSongUi
} from './ui.js'
import { KEYS, GRACE_BEAT } from './config.js'
import { PressIndicator, Highway } from './highway.js';
import { Note } from './note.js';
import { ScoreManager } from './score.js'
import chartmgr from './chartmgr.js';
export class GameScreen {
constructor(chart) {
this.chart = chart;
this.score = new ScoreManager();
this.scoreUi = new ScoreUi();
this.curBeat = 1;
this.background = 10;
this.started = false;
this.pressIndicators = [];
// populate press indicators
KEYS.forEach((_, i) => {
this.pressIndicators.push(new PressIndicator(i));
})
// load song
this.notes = []
if(this.chart) {
this.chart.notes.forEach(n => {
this.notes.push(new Note(n.lane, n.beat))
})
}
this.song = loadSound("./charts/" + this.chart.id + "/" + this.chart.file, null, null, (percent) => {
this.loadPercent = percent
console.log(percent)
});
this.loadPercent = 0;
}
draw() {
this.background = lerp(this.background, 50, 0.02)
background(this.background)
if(this.background > 40 &&
!this.started && this.song.isLoaded() && this.chart.id != "test") {
this.song.play();
this.started = true;
}
Highway.draw(this.curBeat);
// notes
for(let i = 0; i < this.notes.length; i++) {
this.notes[i].draw(this.curBeat)
}
// key indicators
for(let i = 0; i < this.pressIndicators.length; i++) {
let pi = this.pressIndicators[i];
pi.draw(keyIsDown(KEYS[i]))
};
// draw score
this.scoreUi.draw();
if(!this.chart) {
return debugMsg("no chart data!")
} else if (!this.song) {
return debugMsg("audio not loaded!")
}
CurrentSongUi.draw(chartmgr.covers.get(this.chart.id), this.chart.name, this.chart.artist);
}
calcBeat() {
if(this.song) {
let beatSecs = 60 / this.chart.bpm;
this.curBeat = (this.song.currentTime() / beatSecs) + 1
}
}
checkHit() {
let pressTime = this.song.currentTime();
let pressBeat = (pressTime / (60 / this.chart.bpm)) + 1
// scan for notes
if(this.notes.length < 1) return;
let targetNotes = []
targetNotes.push(this.notes[0])
while(true) {
if(this.notes.length < 2)
break;
if(!this.notes[targetNotes.length])
break;
if(
this.notes[targetNotes.length].beat == targetNotes[targetNotes.length - 1].beat
&& this.notes[targetNotes.length].beat == targetNotes[targetNotes.length - 1].beat) {
targetNotes.push(this.notes[targetNotes.length])
} else {
break;
}
}
for(let i = 0; i < targetNotes.length; i++) {
let k = targetNotes[i];
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;
this.notes.find(n=> n.symbol == k.symbol).remove();
this.pressIndicators[k.lane].hit = true;
this.score.onHit();
}
}
}
}

10
screenResults.js Normal file
View File

@ -0,0 +1,10 @@
class ResultsScreen {
constructor(chart, score) {
this.chart = chart
this.score = score
}
draw() {
}
}

88
screenSongSelect.js Normal file
View File

@ -0,0 +1,88 @@
import state from './state.js';
import chartmgr from './chartmgr.js';
import { KeyHint } from './ui.js'
import { sndBoop, sndSongselect } from './main.js';
export class SongSelectScreen {
constructor() {
this.covers = [...chartmgr.covers.entries()].map(c => c[1])
this.songs = [...chartmgr.cache.entries()].map(c => c[1])
this.curSelection = 0;
}
draw() {
KeyHint.draw(">", width - 48 - 4, (height / 2) + 100)
KeyHint.draw("<", 48 - 8, (height / 2) + 100)
KeyHint.draw("Enter", (width/2) - 24, height - 40)
textSize(36);
fill(255);
text("Select a song", 16, 48);
fill(215);
stroke(0);
// current song
image(this.covers[this.curSelection], (width-256)/2, (height-256)/2, 256, 256)
textSize(48);
text(this.songs[this.curSelection].name,
(width / 2) - (textWidth(this.songs[this.curSelection].name) / 2),
height - 128 - 36);
textSize(24);
text(this.songs[this.curSelection].artist,
(width / 2) - (textWidth(this.songs[this.curSelection].artist) / 2),
height - 128);
let etcmeta = this.songs[this.curSelection].difficulty + " - " + this.songs[this.curSelection].len
textSize(18);
text(etcmeta,
(width - textWidth(etcmeta) ) / 2,
height - 128 + 32);
let nextSelection = (this.curSelection + 1 > this.songs.length - 1)
? 0
: this.curSelection + 1
let prevSelection = (this.curSelection - 1 < 0)
? this.songs.length - 1
: this.curSelection - 1
image(this.covers[prevSelection],
32, (height - 128) / 2, 128, 128);
image(this.covers[nextSelection],
(width - 128) - 32, (height - 128) / 2, 128, 128);
}
async keyPressed() {
switch(keyCode) {
case 37:
if(this.curSelection - 1 < 0) {
this.curSelection = this.songs.length - 1
} else {
this.curSelection -= 1
}
sndBoop.play()
break;
case 39: //right
if(this.curSelection + 1 > this.songs.length - 1) {
this.curSelection = 0
} else {
this.curSelection += 1
}
sndBoop.play()
break;
case 13: //enter
sndSongselect.play();
window.gameScreen = await chartmgr.loadChart(this.songs[this.curSelection].id)
state.setState("game");
redraw()
break;
}
}
}

11
state.js Normal file
View File

@ -0,0 +1,11 @@
class State {
constructor() {
this.state = "songselect"
}
setState(newState) {
this.state = newState;
}
}
export default new State();

59
ui.js Normal file
View File

@ -0,0 +1,59 @@
import { Sprite } from './entity.js';
class ScoreUiTextValue extends Sprite {
constructor(title, x, y) {
super(x, y)
this.title = title;
}
setTitle(newTitle) {
this.title = newTitle;
}
draw(val) {
fill(255);
textSize(18);
text(this.title, this.x, this.y - 48)
textSize(48);
text(val, this.x, this.y)
}
}
export class ScoreUi extends Sprite {
constructor() {
super((width / 2) + 175, height - 40);
this.score = new ScoreUiTextValue("SCORE", this.x, this.y);
this.combo = new ScoreUiTextValue("COMBO", this.x, this.y - 86);
}
draw() {
this.combo.draw(window.gameScreen.score.combo);
this.score.draw(window.gameScreen.score.score);
}
}
export class CurrentSongUi extends Sprite {
static draw(img, name, artist) {
fill(255);
textSize(18);
text(artist, (width / 2) + 175 + 40, 40 + 24)
textSize(24);
text(name, (width / 2) + 175 + 40, 40)
}
}
export class KeyHint extends Sprite {
static draw(innerText, x, y) {
stroke(255)
noFill()
textSize(16)
rect(x - 8, y - 20, textWidth(innerText) + 16, 28)
fill(255)
noStroke()
text(innerText, x, y)
}
}