Add lunardash
This commit is contained in:
parent
5317e1a48e
commit
26be488d70
|
@ -1,5 +1,6 @@
|
|||
# Typescript
|
||||
|
||||
| Name | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| [wave38](./wave38/) | Remake of [wave37](https://github.com/Mateiadrielrafael/wave37) I dropped super early in development. |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| [lunardash](./lunardash/) | Rhythm game I dropped super early into development |
|
||||
| [wave38](./wave38/) | Remake of [wave37](https://github.com/Mateiadrielrafael/wave37) I dropped super early into development. |
|
||||
|
|
4
typescript/lunardash/.gitignore
vendored
Normal file
4
typescript/lunardash/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
.build
|
||||
build
|
||||
web_modules
|
||||
node_modules
|
4
typescript/lunardash/.prettierrc
Normal file
4
typescript/lunardash/.prettierrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
24
typescript/lunardash/README.md
Normal file
24
typescript/lunardash/README.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# New Project
|
||||
|
||||
> ✨ Bootstrapped with Create Snowpack App (CSA).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
### npm start
|
||||
|
||||
Runs the app in the development mode.
|
||||
Open http://localhost:8080 to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### npm run build
|
||||
|
||||
Builds a static copy of your site to the `build/` folder.
|
||||
Your app is ready to be deployed!
|
||||
|
||||
**For the best production performance:** Add a build bundler plugin like [@snowpack/plugin-webpack](https://github.com/snowpackjs/snowpack/tree/main/plugins/plugin-webpack) or [snowpack-plugin-rollup-bundle](https://github.com/ParamagicDev/snowpack-plugin-rollup-bundle) to your `snowpack.config.mjs` config file.
|
||||
|
||||
### Q: What about Eject?
|
||||
|
||||
No eject needed! Snowpack guarantees zero lock-in, and CSA strives for the same.
|
20
typescript/lunardash/package.json
Normal file
20
typescript/lunardash/package.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"scripts": {
|
||||
"start": "snowpack dev",
|
||||
"build": "snowpack build",
|
||||
"test": "echo \"This template does not include a test runner by default.\" && exit 1",
|
||||
"format": "prettier --write \"src/**/*.{ts,js}\"",
|
||||
"lint": "prettier --check \"src/**/*.{ts,js}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"canvas-confetti": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@snowpack/plugin-typescript": "^1.2.1",
|
||||
"@types/canvas-confetti": "^1.0.0",
|
||||
"@types/snowpack-env": "^2.3.3",
|
||||
"prettier": "^2.2.1",
|
||||
"snowpack": "^3.3.7",
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
}
|
1463
typescript/lunardash/pnpm-lock.yaml
Normal file
1463
typescript/lunardash/pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
BIN
typescript/lunardash/public/favicon.ico
Normal file
BIN
typescript/lunardash/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
11
typescript/lunardash/public/index.css
Normal file
11
typescript/lunardash/public/index.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
body,
|
||||
html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
display: block;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
17
typescript/lunardash/public/index.html
Normal file
17
typescript/lunardash/public/index.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="description" content="Web site created using create-snowpack-app" />
|
||||
<link rel="stylesheet" type="text/css" href="/index.css" />
|
||||
<title>Lunardash</title>
|
||||
|
||||
<script type="module" defer src="/dist/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
</body>
|
||||
</html>
|
7
typescript/lunardash/public/logo.svg
Normal file
7
typescript/lunardash/public/logo.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path fill="#E44D26" d="M107.6 470.9l-33-370.3h362.8l-33.1 370.2L255.8 512z"/>
|
||||
<path fill="#F16529" d="M256 480.5l120-33.3 28.3-316.3H256z"/>
|
||||
<path fill="#EBEBEB" d="M256 268.2h-60.1l-4.1-46.5H256v-45.4H142.1l1.1 12.2 11.2 125.1H256zM256 386.2h-.2l-50.6-13.6-3.2-36.3h-45.6l6.4 71.3 93 25.9.2-.1z"/>
|
||||
<path d="M108.4 0h23v22.8h21.2V0h23v69h-23V46h-21.1v23h-23.1V0zM206 22.9h-20.3V0h63.7v22.9h-20.3V69H206V23zM259.5 0h24l14.9 24.3L313.2 0h24v69h-23V34.8l-15.8 24.6h-.4l-16-24.6V69h-22.5V0zM348.7 0h23.1v46.2h32.5V69h-55.6V0z"/>
|
||||
<path fill="#FFF" d="M255.8 268.2v45.4h56l-5.3 58.9-50.7 13.7v47.2l93.1-25.8.7-7.6 10.7-119.6 1.1-12.2h-12.2zM255.8 176.3v45.4H365.5l.9-10.2 2.1-23 1.1-12.2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 767 B |
3
typescript/lunardash/public/robots.txt
Normal file
3
typescript/lunardash/public/robots.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
BIN
typescript/lunardash/public/songs/heracles.mp3
Normal file
BIN
typescript/lunardash/public/songs/heracles.mp3
Normal file
Binary file not shown.
33
typescript/lunardash/snowpack.config.mjs
Normal file
33
typescript/lunardash/snowpack.config.mjs
Normal file
|
@ -0,0 +1,33 @@
|
|||
/** @type {import("snowpack").SnowpackUserConfig } */
|
||||
export default {
|
||||
mount: {
|
||||
public: { url: '/', static: true },
|
||||
src: { url: '/dist' },
|
||||
},
|
||||
plugins: [
|
||||
[
|
||||
'@snowpack/plugin-typescript',
|
||||
{
|
||||
/* Yarn PnP workaround: see https://www.npmjs.com/package/@snowpack/plugin-typescript */
|
||||
...(process.versions.pnp ? { tsc: 'yarn pnpify tsc' } : {}),
|
||||
},
|
||||
],
|
||||
],
|
||||
routes: [
|
||||
/* Enable an SPA Fallback in development: */
|
||||
// {"match": "routes", "src": ".*", "dest": "/index.html"},
|
||||
],
|
||||
optimize: {
|
||||
/* Example: Bundle your final build: */
|
||||
// "bundle": true,
|
||||
},
|
||||
packageOptions: {
|
||||
/* ... */
|
||||
},
|
||||
devOptions: {
|
||||
/* ... */
|
||||
},
|
||||
buildOptions: {
|
||||
/* ... */
|
||||
},
|
||||
};
|
17
typescript/lunardash/src/Chart.ts
Normal file
17
typescript/lunardash/src/Chart.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
export const enum Axis {
|
||||
Negative = -1,
|
||||
Zero = 0,
|
||||
Positive = 1,
|
||||
}
|
||||
|
||||
export type Direction = [Axis, Axis];
|
||||
|
||||
export interface Note {
|
||||
stamp: number;
|
||||
orientation: Direction;
|
||||
}
|
||||
|
||||
export interface Chart {
|
||||
path: Array<Note>;
|
||||
song: HTMLAudioElement;
|
||||
}
|
37
typescript/lunardash/src/State.ts
Normal file
37
typescript/lunardash/src/State.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import type { Chart } from './Chart';
|
||||
|
||||
export const enum NoteJudgement {
|
||||
Missed,
|
||||
Far,
|
||||
Perfect,
|
||||
}
|
||||
|
||||
export const enum NoteTiming {
|
||||
Early,
|
||||
Late,
|
||||
}
|
||||
|
||||
export interface NoteState {
|
||||
judgement: NoteJudgement;
|
||||
timing: NoteTiming;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
song: HTMLAudioElement;
|
||||
currentNote: number;
|
||||
notes: NoteState[];
|
||||
readonly chart: Chart;
|
||||
readonly settings: Settings;
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
offset: number;
|
||||
judgments: {
|
||||
perfect: number;
|
||||
far: number;
|
||||
};
|
||||
scrollSpeed: number;
|
||||
implicitScrollSpeed: number;
|
||||
windowCenter: number;
|
||||
noteSize: number;
|
||||
}
|
176
typescript/lunardash/src/index.ts
Normal file
176
typescript/lunardash/src/index.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
import type { Chart, Note } from './Chart';
|
||||
import { NoteJudgement, NoteTiming, State } from './State';
|
||||
|
||||
const canvas = document.getElementById('canvas')! as HTMLCanvasElement;
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
|
||||
const song = new Audio('/songs/heracles.mp3');
|
||||
|
||||
const heracles: Chart = {
|
||||
song,
|
||||
path: [
|
||||
{
|
||||
stamp: 1.906999,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
{
|
||||
stamp: 3.115963,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
{
|
||||
stamp: 4.365792,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
{
|
||||
stamp: 5.645609,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
{
|
||||
stamp: 6.894808,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
{
|
||||
stamp: 8.099023,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
{
|
||||
stamp: 9.337156,
|
||||
orientation: [0, 1],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let started = false;
|
||||
|
||||
const state: State = {
|
||||
chart: heracles,
|
||||
currentNote: 0,
|
||||
notes: [],
|
||||
song,
|
||||
settings: {
|
||||
offset: 0.05,
|
||||
judgments: {
|
||||
far: 0.1,
|
||||
perfect: 0.042,
|
||||
},
|
||||
scrollSpeed: 4,
|
||||
implicitScrollSpeed: 100,
|
||||
windowCenter: 100,
|
||||
noteSize: 10,
|
||||
},
|
||||
};
|
||||
|
||||
const start = () => {
|
||||
started = true;
|
||||
|
||||
state.song.play();
|
||||
|
||||
main();
|
||||
resize();
|
||||
};
|
||||
|
||||
const resize = () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
};
|
||||
|
||||
const main = () => {
|
||||
if (state.song.currentTime > state.chart.path[state.currentNote].stamp) {
|
||||
state.currentNote++;
|
||||
}
|
||||
|
||||
const time = state.song.currentTime - state.settings.offset;
|
||||
|
||||
while (true) {
|
||||
const firstNote = state.chart.path[state.notes.length];
|
||||
const delta = time - firstNote.stamp;
|
||||
|
||||
if (delta > state.settings.judgments.far) {
|
||||
state.notes.push({
|
||||
timing: NoteTiming.Late,
|
||||
judgement: NoteJudgement.Missed,
|
||||
});
|
||||
} else break;
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, 3000, 3000);
|
||||
|
||||
ctx.fillStyle = 'rgba(0,0,0,0.3)';
|
||||
ctx.fillRect(0, 200, window.innerWidth, 100);
|
||||
|
||||
ctx.fillStyle = 'blue';
|
||||
ctx.fillRect(
|
||||
state.settings.windowCenter - state.settings.noteSize / 2,
|
||||
200,
|
||||
state.settings.noteSize,
|
||||
100,
|
||||
);
|
||||
|
||||
ctx.fillStyle = 'rgba(0,0,256,0.3)';
|
||||
const farSize =
|
||||
state.settings.judgments.far *
|
||||
state.settings.scrollSpeed *
|
||||
state.settings.implicitScrollSpeed;
|
||||
|
||||
ctx.fillRect(state.settings.windowCenter - farSize, 200, farSize * 2, 100);
|
||||
|
||||
for (let index = 0; index < heracles.path.length; index++) {
|
||||
const note = heracles.path[index];
|
||||
if (state.notes[index]?.judgement === NoteJudgement.Missed)
|
||||
ctx.fillStyle = 'red';
|
||||
else if (state.notes[index]?.judgement === NoteJudgement.Far)
|
||||
ctx.fillStyle =
|
||||
state.notes[index].timing === NoteTiming.Late ? 'orange' : 'blue';
|
||||
else if (state.notes[index]?.judgement === NoteJudgement.Perfect)
|
||||
ctx.fillStyle = 'green';
|
||||
else ctx.fillStyle = 'yellow';
|
||||
|
||||
ctx.fillRect(
|
||||
state.settings.windowCenter +
|
||||
(note.stamp - song.currentTime) *
|
||||
state.settings.scrollSpeed *
|
||||
state.settings.implicitScrollSpeed,
|
||||
200,
|
||||
state.settings.noteSize,
|
||||
100,
|
||||
);
|
||||
}
|
||||
|
||||
requestAnimationFrame(main);
|
||||
};
|
||||
|
||||
canvas.onclick = () => {
|
||||
if (!started) return start();
|
||||
|
||||
const time = state.song.currentTime - state.settings.offset;
|
||||
|
||||
while (true) {
|
||||
const firstNote = state.chart.path[state.notes.length];
|
||||
|
||||
if (!firstNote) return;
|
||||
|
||||
const delta = time - firstNote.stamp;
|
||||
const absoluteDelta = Math.abs(delta);
|
||||
const timing = delta < 0 ? NoteTiming.Early : NoteTiming.Late;
|
||||
|
||||
console.log({ timing, delta, firstNote, absoluteDelta, time });
|
||||
|
||||
if (delta > state.settings.judgments.far) {
|
||||
state.notes.push({
|
||||
timing: NoteTiming.Late,
|
||||
judgement: NoteJudgement.Missed,
|
||||
});
|
||||
continue;
|
||||
} else if (absoluteDelta > state.settings.judgments.far) return;
|
||||
else
|
||||
state.notes.push({
|
||||
timing,
|
||||
judgement:
|
||||
absoluteDelta < state.settings.judgments.perfect
|
||||
? NoteJudgement.Perfect
|
||||
: NoteJudgement.Far,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
29
typescript/lunardash/tsconfig.json
Normal file
29
typescript/lunardash/tsconfig.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"include": ["src", "types"],
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"jsx": "preserve",
|
||||
"baseUrl": "./",
|
||||
/* paths - import rewriting/resolving */
|
||||
"paths": {
|
||||
// If you configured any Snowpack aliases, add them here.
|
||||
// Add this line to get types for streaming imports (packageOptions.source="remote"):
|
||||
// "*": [".snowpack/types/*"]
|
||||
// More info: https://www.snowpack.dev/guides/streaming-imports
|
||||
},
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"importsNotUsedAsValues": "error",
|
||||
/* more strict checking for errors that per-file transpilers like `esbuild` would crash */
|
||||
"isolatedModules": true,
|
||||
/* noEmit - We only use TypeScript for type checking. */
|
||||
"noEmit": true,
|
||||
/* Additional Options */
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"useDefineForClassFields": true
|
||||
}
|
||||
}
|
59
typescript/lunardash/types/static.d.ts
vendored
Normal file
59
typescript/lunardash/types/static.d.ts
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Use this file to declare any custom file extensions for importing */
|
||||
/* Use this folder to also add/extend a package d.ts file, if needed. */
|
||||
|
||||
/* CSS MODULES */
|
||||
declare module '*.module.css' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
declare module '*.module.scss' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
declare module '*.module.sass' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
declare module '*.module.less' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
declare module '*.module.styl' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
|
||||
/* CSS */
|
||||
declare module '*.css';
|
||||
declare module '*.scss';
|
||||
declare module '*.sass';
|
||||
declare module '*.less';
|
||||
declare module '*.styl';
|
||||
|
||||
/* IMAGES */
|
||||
declare module '*.svg' {
|
||||
const ref: string;
|
||||
export default ref;
|
||||
}
|
||||
declare module '*.bmp' {
|
||||
const ref: string;
|
||||
export default ref;
|
||||
}
|
||||
declare module '*.gif' {
|
||||
const ref: string;
|
||||
export default ref;
|
||||
}
|
||||
declare module '*.jpg' {
|
||||
const ref: string;
|
||||
export default ref;
|
||||
}
|
||||
declare module '*.jpeg' {
|
||||
const ref: string;
|
||||
export default ref;
|
||||
}
|
||||
declare module '*.png' {
|
||||
const ref: string;
|
||||
export default ref;
|
||||
}
|
||||
|
||||
/* CUSTOM: ADD YOUR OWN HERE */
|
Loading…
Reference in a new issue