1
Fork 0

Add lunardash

This commit is contained in:
Matei Adriel 2023-10-29 02:29:24 +02:00
parent 5317e1a48e
commit 26be488d70
18 changed files with 1908 additions and 3 deletions

View file

@ -1,5 +1,6 @@
# Typescript # Typescript
| Name | Description | | 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
View file

@ -0,0 +1,4 @@
.build
build
web_modules
node_modules

View file

@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}

View 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.

View 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"
}
}

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,11 @@
body,
html {
padding: 0;
margin: 0;
}
#canvas {
display: block;
width: 100vw;
height: 100vh;
}

View 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>

View 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

View file

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

Binary file not shown.

View 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: {
/* ... */
},
};

View 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;
}

View 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;
}

View 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;
}
};

View 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
View 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 */