mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-06-15 10:44:42 -04:00
Build and deploy of version 29030872
This commit is contained in:
parent
e14e958686
commit
57cb73128f
10 changed files with 2827 additions and 6487 deletions
|
@ -11,8 +11,8 @@ android {
|
||||||
applicationId = "me.lecaro.breakout"
|
applicationId = "me.lecaro.breakout"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 29028296
|
versionCode = 29030872
|
||||||
versionName = "29028296"
|
versionName = "29030872"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
|
|
File diff suppressed because one or more lines are too long
3854
dist/index.html
vendored
3854
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -31,4 +31,4 @@
|
||||||
"<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30'><path d='M9 20.502h0A7.5 7.5 0 0 1 1.5 28 7.5 7.5 0 0 0-6 35.5h0a7.5 7.5 0 0 1-7.5 7.499 7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1-21 35.5h0a7.5 7.5 0 0 1 7.5-7.5A7.5 7.5 0 0 0-6 20.502h0a7.5 7.5 0 1 1 15 0zm15 0h0A7.5 7.5 0 0 1 16.5 28a7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1 9 20.502h0c0-2.072-.84-3.947-2.197-5.303A7.477 7.477 0 0 0 1.5 13.002a7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1-6 5.503h0a7.5 7.5 0 1 1 15 0h0c0 2.07.84 3.945 2.196 5.303a7.476 7.476 0 0 0 5.304 2.196c2.07 0 3.945.84 5.303 2.197A7.471 7.471 0 0 1 24 20.502zm15 0h0A7.5 7.5 0 0 1 31.5 28a7.5 7.5 0 0 0-7.5 7.5h0a7.5 7.5 0 0 1-7.5 7.499 7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1 9 35.5h0a7.5 7.5 0 0 1 7.5-7.5 7.5 7.5 0 0 0 7.5-7.498h0a7.5 7.5 0 1 1 15 0zm0-30h0A7.5 7.5 0 0 1 31.5-2 7.5 7.5 0 0 0 24 5.5h0a7.5 7.5 0 0 1-7.5 7.499 7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1 9 5.5h0A7.5 7.5 0 0 1 16.5-2 7.5 7.5 0 0 0 24-9.498h0a7.5 7.5 0 1 1 15 0zm-22.5 37.5a7.5 7.5 0 0 0-7.5 7.5c0-2.072-.84-3.947-2.197-5.303A7.477 7.477 0 0 0 1.5 28.002 7.5 7.5 0 0 0 9 20.503c0 2.07.84 3.945 2.196 5.303a7.476 7.476 0 0 0 5.304 2.196zm15-15a7.5 7.5 0 0 0-7.5 7.5c0-2.072-.84-3.947-2.197-5.303a7.477 7.477 0 0 0-5.303-2.197A7.5 7.5 0 0 0 24 5.503c0 2.07.84 3.945 2.196 5.303a7.476 7.476 0 0 0 5.304 2.196z' stroke-width='1' stroke='white' fill='none'/></svg>",
|
"<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30'><path d='M9 20.502h0A7.5 7.5 0 0 1 1.5 28 7.5 7.5 0 0 0-6 35.5h0a7.5 7.5 0 0 1-7.5 7.499 7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1-21 35.5h0a7.5 7.5 0 0 1 7.5-7.5A7.5 7.5 0 0 0-6 20.502h0a7.5 7.5 0 1 1 15 0zm15 0h0A7.5 7.5 0 0 1 16.5 28a7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1 9 20.502h0c0-2.072-.84-3.947-2.197-5.303A7.477 7.477 0 0 0 1.5 13.002a7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1-6 5.503h0a7.5 7.5 0 1 1 15 0h0c0 2.07.84 3.945 2.196 5.303a7.476 7.476 0 0 0 5.304 2.196c2.07 0 3.945.84 5.303 2.197A7.471 7.471 0 0 1 24 20.502zm15 0h0A7.5 7.5 0 0 1 31.5 28a7.5 7.5 0 0 0-7.5 7.5h0a7.5 7.5 0 0 1-7.5 7.499 7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1 9 35.5h0a7.5 7.5 0 0 1 7.5-7.5 7.5 7.5 0 0 0 7.5-7.498h0a7.5 7.5 0 1 1 15 0zm0-30h0A7.5 7.5 0 0 1 31.5-2 7.5 7.5 0 0 0 24 5.5h0a7.5 7.5 0 0 1-7.5 7.499 7.476 7.476 0 0 1-5.304-2.196A7.482 7.482 0 0 1 9 5.5h0A7.5 7.5 0 0 1 16.5-2 7.5 7.5 0 0 0 24-9.498h0a7.5 7.5 0 1 1 15 0zm-22.5 37.5a7.5 7.5 0 0 0-7.5 7.5c0-2.072-.84-3.947-2.197-5.303A7.477 7.477 0 0 0 1.5 28.002 7.5 7.5 0 0 0 9 20.503c0 2.07.84 3.945 2.196 5.303a7.476 7.476 0 0 0 5.304 2.196zm15-15a7.5 7.5 0 0 0-7.5 7.5c0-2.072-.84-3.947-2.197-5.303a7.477 7.477 0 0 0-5.303-2.197A7.5 7.5 0 0 0 24 5.503c0 2.07.84 3.945 2.196 5.303a7.476 7.476 0 0 0 5.304 2.196z' stroke-width='1' stroke='white' fill='none'/></svg>",
|
||||||
"<svg xmlns='http://www.w3.org/2000/svg' width='40' height='69.282'><path d='M13.333-3.849v23.094M6.667-15.396l20 11.547M13.333-19.245l20 11.547M20 0v23.094m20-34.641l-6.667 3.849-6.666 3.849L20 0M0-11.547l6.667 3.849 6.666 3.849L20 0m0-23.094l20 11.547v23.094L20 23.094l-6.667-3.849-6.666-3.849L0 11.547v-23.094l6.667-3.849 6.666-3.849zM40-3.769L20 7.698m20-3.849l-16.253 9.384L20 15.396M6.667-7.698v23.094m6.666 50.037v23.094M6.667 53.886l20 11.547M13.333 50.037l20 11.547M20 69.282v23.094m20-34.641l-6.667 3.849-6.666 3.849L20 69.282M0 57.735l6.667 3.849 6.666 3.849L20 69.282m0-23.094l20 11.547v23.094L20 92.376l-6.667-3.849-6.666-3.849L0 80.829V57.735l6.667-3.849 6.666-3.849zm20 19.325L20 76.98m20-3.849L20 84.678M6.667 61.584v23.094m26.666-53.886v23.094m-6.666-34.641l20 11.547M33.333 15.396l20 11.547M40 34.641v23.094m20-34.641l-6.667 3.849-6.666 3.849L40 34.641M20 23.094l6.667 3.849 6.666 3.849L40 34.641m0-23.094l20 11.547v23.094L40 57.735l-6.667-3.849-6.666-3.849L20 46.188V23.094l6.667-3.849 6.666-3.849zm20 19.325L40 42.339m20-3.849L40 50.037M26.667 26.943v23.094M-6.667 30.792v23.094m-6.666-34.641l20 11.547M-6.667 15.396l20 11.547M0 34.641v23.094m20-34.641l-6.667 3.849-6.666 3.849L0 34.641m-20-11.547l6.667 3.849 6.666 3.849L0 34.641m0-23.094l20 11.547v23.094L0 57.735l-6.667-3.849-6.666-3.849L-20 46.188V23.094l6.667-3.849 6.666-3.849zm20 19.325L0 42.339m20-3.849L0 50.037m-13.333-23.094v23.094' stroke-width='1' stroke='white' fill='none'/></svg>",
|
"<svg xmlns='http://www.w3.org/2000/svg' width='40' height='69.282'><path d='M13.333-3.849v23.094M6.667-15.396l20 11.547M13.333-19.245l20 11.547M20 0v23.094m20-34.641l-6.667 3.849-6.666 3.849L20 0M0-11.547l6.667 3.849 6.666 3.849L20 0m0-23.094l20 11.547v23.094L20 23.094l-6.667-3.849-6.666-3.849L0 11.547v-23.094l6.667-3.849 6.666-3.849zM40-3.769L20 7.698m20-3.849l-16.253 9.384L20 15.396M6.667-7.698v23.094m6.666 50.037v23.094M6.667 53.886l20 11.547M13.333 50.037l20 11.547M20 69.282v23.094m20-34.641l-6.667 3.849-6.666 3.849L20 69.282M0 57.735l6.667 3.849 6.666 3.849L20 69.282m0-23.094l20 11.547v23.094L20 92.376l-6.667-3.849-6.666-3.849L0 80.829V57.735l6.667-3.849 6.666-3.849zm20 19.325L20 76.98m20-3.849L20 84.678M6.667 61.584v23.094m26.666-53.886v23.094m-6.666-34.641l20 11.547M33.333 15.396l20 11.547M40 34.641v23.094m20-34.641l-6.667 3.849-6.666 3.849L40 34.641M20 23.094l6.667 3.849 6.666 3.849L40 34.641m0-23.094l20 11.547v23.094L40 57.735l-6.667-3.849-6.666-3.849L20 46.188V23.094l6.667-3.849 6.666-3.849zm20 19.325L40 42.339m20-3.849L40 50.037M26.667 26.943v23.094M-6.667 30.792v23.094m-6.666-34.641l20 11.547M-6.667 15.396l20 11.547M0 34.641v23.094m20-34.641l-6.667 3.849-6.666 3.849L0 34.641m-20-11.547l6.667 3.849 6.666 3.849L0 34.641m0-23.094l20 11.547v23.094L0 57.735l-6.667-3.849-6.666-3.849L-20 46.188V23.094l6.667-3.849 6.666-3.849zm20 19.325L0 42.339m20-3.849L0 50.037m-13.333-23.094v23.094' stroke-width='1' stroke='white' fill='none'/></svg>",
|
||||||
"<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><path d='M46.231 19.999a5.937 7.48 0 01-5.937 7.48A5.937 7.48 0 0134.357 20a5.937 7.48 0 015.937-7.48 5.937 7.48 0 015.937 7.48zm-40.421 0a5.937 7.48 0 01-5.937 7.48A5.937 7.48 0 01-6.064 20a5.937 7.48 0 015.937-7.48 5.937 7.48 0 015.937 7.48zm20.21 20.285a5.937 7.48 0 01-5.937 7.48 5.937 7.48 0 01-5.936-7.48 5.937 7.48 0 015.936-7.48 5.937 7.48 0 015.937 7.48zm0-40.57a5.937 7.48 0 01-5.937 7.48 5.937 7.48 0 01-5.936-7.48 5.937 7.48 0 015.936-7.48 5.937 7.48 0 015.937 7.48zM-5.732 46.942c1.676-.944 3.556-1.6 5.478-1.587 1.924.011 3.796.69 5.463 1.653 1.668.962 3.156 2.202 4.637 3.434 1.48 1.233 2.97 2.471 4.641 3.428 1.67.957 3.547 1.627 5.47 1.627 1.924 0 3.8-.67 5.47-1.627s3.161-2.195 4.642-3.428c1.48-1.232 2.968-2.472 4.636-3.434 1.667-.963 3.54-1.642 5.463-1.653 1.922-.012 3.802.643 5.479 1.587V33.628c-1.677.944-3.557 1.6-5.479 1.587-1.923-.011-3.796-.69-5.463-1.653-1.668-.962-3.156-2.202-4.636-3.434-1.48-1.233-2.971-2.471-4.642-3.428-1.67-.957-3.546-1.627-5.47-1.627-1.923 0-3.8.67-5.47 1.627s-3.161 2.195-4.641 3.428c-1.48 1.232-2.97 2.472-4.637 3.434-1.667.963-3.54 1.641-5.463 1.653-1.922.012-3.802-.643-5.478-1.587zM45.647-6.943c-1.677.944-3.557 1.6-5.479 1.587-1.923-.011-3.796-.69-5.463-1.653-1.668-.962-3.156-2.202-4.636-3.434-1.48-1.233-2.971-2.471-4.642-3.428-1.67-.957-3.546-1.627-5.47-1.627-1.923 0-3.8.67-5.47 1.627s-3.161 2.195-4.641 3.428c-1.48 1.232-2.97 2.472-4.637 3.434-1.667.963-3.54 1.642-5.463 1.653-1.922.012-3.802-.643-5.478-1.587V6.372c1.676-.944 3.556-1.6 5.478-1.587 1.924.012 3.796.69 5.463 1.653C6.877 7.4 8.365 8.64 9.846 9.872c1.48 1.233 2.97 2.471 4.641 3.428 1.67.957 3.547 1.627 5.47 1.627 1.924 0 3.8-.67 5.47-1.627s3.161-2.195 4.642-3.428c1.48-1.232 2.968-2.472 4.636-3.434 1.667-.963 3.54-1.642 5.463-1.653 1.922-.012 3.802.643 5.479 1.587z' stroke-width='1' stroke='white' fill='none'/></svg>"
|
"<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><path d='M46.231 19.999a5.937 7.48 0 01-5.937 7.48A5.937 7.48 0 0134.357 20a5.937 7.48 0 015.937-7.48 5.937 7.48 0 015.937 7.48zm-40.421 0a5.937 7.48 0 01-5.937 7.48A5.937 7.48 0 01-6.064 20a5.937 7.48 0 015.937-7.48 5.937 7.48 0 015.937 7.48zm20.21 20.285a5.937 7.48 0 01-5.937 7.48 5.937 7.48 0 01-5.936-7.48 5.937 7.48 0 015.936-7.48 5.937 7.48 0 015.937 7.48zm0-40.57a5.937 7.48 0 01-5.937 7.48 5.937 7.48 0 01-5.936-7.48 5.937 7.48 0 015.936-7.48 5.937 7.48 0 015.937 7.48zM-5.732 46.942c1.676-.944 3.556-1.6 5.478-1.587 1.924.011 3.796.69 5.463 1.653 1.668.962 3.156 2.202 4.637 3.434 1.48 1.233 2.97 2.471 4.641 3.428 1.67.957 3.547 1.627 5.47 1.627 1.924 0 3.8-.67 5.47-1.627s3.161-2.195 4.642-3.428c1.48-1.232 2.968-2.472 4.636-3.434 1.667-.963 3.54-1.642 5.463-1.653 1.922-.012 3.802.643 5.479 1.587V33.628c-1.677.944-3.557 1.6-5.479 1.587-1.923-.011-3.796-.69-5.463-1.653-1.668-.962-3.156-2.202-4.636-3.434-1.48-1.233-2.971-2.471-4.642-3.428-1.67-.957-3.546-1.627-5.47-1.627-1.923 0-3.8.67-5.47 1.627s-3.161 2.195-4.641 3.428c-1.48 1.232-2.97 2.472-4.637 3.434-1.667.963-3.54 1.641-5.463 1.653-1.922.012-3.802-.643-5.478-1.587zM45.647-6.943c-1.677.944-3.557 1.6-5.479 1.587-1.923-.011-3.796-.69-5.463-1.653-1.668-.962-3.156-2.202-4.636-3.434-1.48-1.233-2.971-2.471-4.642-3.428-1.67-.957-3.546-1.627-5.47-1.627-1.923 0-3.8.67-5.47 1.627s-3.161 2.195-4.641 3.428c-1.48 1.232-2.97 2.472-4.637 3.434-1.667.963-3.54 1.642-5.463 1.653-1.922.012-3.802-.643-5.478-1.587V6.372c1.676-.944 3.556-1.6 5.478-1.587 1.924.012 3.796.69 5.463 1.653C6.877 7.4 8.365 8.64 9.846 9.872c1.48 1.233 2.97 2.471 4.641 3.428 1.67.957 3.547 1.627 5.47 1.627 1.924 0 3.8-.67 5.47-1.627s3.161-2.195 4.642-3.428c1.48-1.232 2.968-2.472 4.636-3.434 1.667-.963 3.54-1.642 5.463-1.653 1.922-.012 3.802.643 5.479 1.587z' stroke-width='1' stroke='white' fill='none'/></svg>"
|
||||||
]
|
]
|
||||||
|
|
5028
src/game.ts
5028
src/game.ts
File diff suppressed because it is too large
Load diff
|
@ -835,4 +835,4 @@
|
||||||
"bricks": "_W__W_WW__WW____________WW__WW_W__W_",
|
"bricks": "_W__W_WW__WW____________WW__WW_W__W_",
|
||||||
"svg": null
|
"svg": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,14 +4,13 @@ import _rawLevelsList from "./levels.json";
|
||||||
import _appVersion from "./version.json";
|
import _appVersion from "./version.json";
|
||||||
import { rawUpgrades } from "./rawUpgrades";
|
import { rawUpgrades } from "./rawUpgrades";
|
||||||
import _backgrounds from "./backgrounds.json";
|
import _backgrounds from "./backgrounds.json";
|
||||||
const backgrounds = _backgrounds as string[]
|
const backgrounds = _backgrounds as string[];
|
||||||
const palette = _palette as Palette;
|
const palette = _palette as Palette;
|
||||||
|
|
||||||
const rawLevelsList = _rawLevelsList as RawLevel[];
|
const rawLevelsList = _rawLevelsList as RawLevel[];
|
||||||
|
|
||||||
export const appVersion = _appVersion as string;
|
export const appVersion = _appVersion as string;
|
||||||
|
|
||||||
|
|
||||||
let levelIconHTMLCanvas = document.createElement("canvas");
|
let levelIconHTMLCanvas = document.createElement("canvas");
|
||||||
const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", {
|
const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", {
|
||||||
antialias: false,
|
antialias: false,
|
||||||
|
@ -65,7 +64,7 @@ export const allLevels = rawLevelsList
|
||||||
.slice(0, level.size * level.size);
|
.slice(0, level.size * level.size);
|
||||||
const icon = levelIconHTML(bricks, level.size, level.name, level.color);
|
const icon = levelIconHTML(bricks, level.size, level.name, level.color);
|
||||||
icons[level.name] = icon;
|
icons[level.name] = icon;
|
||||||
let svg = level.svg!==null && backgrounds[level.svg]
|
let svg = level.svg !== null && backgrounds[level.svg];
|
||||||
|
|
||||||
if (!level.color && !svg) {
|
if (!level.color && !svg) {
|
||||||
svg = backgrounds[hashCode(level.name) % backgrounds.length];
|
svg = backgrounds[hashCode(level.name) % backgrounds.length];
|
||||||
|
@ -94,13 +93,12 @@ export const upgrades = rawUpgrades.map((u) => ({
|
||||||
icon: icons["icon:" + u.id],
|
icon: icons["icon:" + u.id],
|
||||||
})) as Upgrade[];
|
})) as Upgrade[];
|
||||||
|
|
||||||
|
function hashCode(string: string) {
|
||||||
function hashCode(string:string){
|
let hash = 0;
|
||||||
let hash = 0;
|
for (let i = 0; i < string.length; i++) {
|
||||||
for (let i = 0; i < string.length; i++) {
|
let code = string.charCodeAt(i);
|
||||||
let code = string.charCodeAt(i);
|
hash = (hash << 5) - hash + code;
|
||||||
hash = ((hash<<5)-hash)+code;
|
hash = hash & hash; // Convert to 32bit integer
|
||||||
hash = hash & hash; // Convert to 32bit integer
|
}
|
||||||
}
|
return Math.abs(hash);
|
||||||
return Math.abs(hash);
|
|
||||||
}
|
}
|
||||||
|
|
342
src/sounds.ts
342
src/sounds.ts
|
@ -1,223 +1,235 @@
|
||||||
import {gameZoneWidthRoundedUp, isSettingOn, offsetX, offsetXRoundedDown} from "./game";
|
import {
|
||||||
|
gameZoneWidthRoundedUp,
|
||||||
|
isSettingOn,
|
||||||
|
offsetX,
|
||||||
|
offsetXRoundedDown,
|
||||||
|
} from "./game";
|
||||||
|
|
||||||
export const sounds = {
|
export const sounds = {
|
||||||
wallBeep: (pan: number) => {
|
wallBeep: (pan: number) => {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
createSingleBounceSound(800, pixelsToPan(pan));
|
createSingleBounceSound(800, pixelsToPan(pan));
|
||||||
},
|
},
|
||||||
|
|
||||||
comboIncreaseMaybe: (combo: number, x: number, volume: number) => {
|
comboIncreaseMaybe: (combo: number, x: number, volume: number) => {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
let delta = 0;
|
let delta = 0;
|
||||||
if (!isNaN(lastComboPlayed)) {
|
if (!isNaN(lastComboPlayed)) {
|
||||||
if (lastComboPlayed < combo) delta = 1;
|
if (lastComboPlayed < combo) delta = 1;
|
||||||
if (lastComboPlayed > combo) delta = -1;
|
if (lastComboPlayed > combo) delta = -1;
|
||||||
}
|
}
|
||||||
playShepard(delta, pixelsToPan(x), volume);
|
playShepard(delta, pixelsToPan(x), volume);
|
||||||
lastComboPlayed = combo;
|
lastComboPlayed = combo;
|
||||||
},
|
},
|
||||||
|
|
||||||
comboDecrease() {
|
comboDecrease() {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
playShepard(-1, 0.5, 0.5);
|
playShepard(-1, 0.5, 0.5);
|
||||||
},
|
},
|
||||||
coinBounce: (pan: number, volume: number) => {
|
coinBounce: (pan: number, volume: number) => {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
||||||
},
|
},
|
||||||
explode: (pan: number) => {
|
explode: (pan: number) => {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
createExplosionSound(pixelsToPan(pan));
|
createExplosionSound(pixelsToPan(pan));
|
||||||
},
|
},
|
||||||
lifeLost(pan:number){
|
lifeLost(pan: number) {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
createShatteredGlassSound(pixelsToPan(pan))
|
createShatteredGlassSound(pixelsToPan(pan));
|
||||||
},
|
},
|
||||||
|
|
||||||
coinCatch(pan: number) {
|
coinCatch(pan: number) {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// How to play the code on the leftconst context = new window.AudioContext();
|
// How to play the code on the leftconst context = new window.AudioContext();
|
||||||
let audioContext: AudioContext, audioRecordingTrack: MediaStreamAudioDestinationNode;
|
let audioContext: AudioContext,
|
||||||
|
audioRecordingTrack: MediaStreamAudioDestinationNode;
|
||||||
|
|
||||||
export function getAudioContext() {
|
export function getAudioContext() {
|
||||||
if (!audioContext) {
|
if (!audioContext) {
|
||||||
if (!isSettingOn('sound')) return null
|
if (!isSettingOn("sound")) return null;
|
||||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
audioRecordingTrack = audioContext.createMediaStreamDestination();
|
audioRecordingTrack = audioContext.createMediaStreamDestination();
|
||||||
}
|
}
|
||||||
return audioContext;
|
return audioContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAudioRecordingTrack() {
|
export function getAudioRecordingTrack() {
|
||||||
getAudioContext()
|
getAudioContext();
|
||||||
return audioRecordingTrack
|
return audioRecordingTrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSingleBounceSound(
|
function createSingleBounceSound(
|
||||||
baseFreq = 800,
|
baseFreq = 800,
|
||||||
pan = 0.5,
|
pan = 0.5,
|
||||||
volume = 1,
|
volume = 1,
|
||||||
duration = 0.1,
|
duration = 0.1,
|
||||||
type: OscillatorType = "sine",
|
type: OscillatorType = "sine",
|
||||||
) {
|
) {
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
if (!context) return
|
if (!context) return;
|
||||||
const oscillator = createOscillator(context, baseFreq, type);
|
const oscillator = createOscillator(context, baseFreq, type);
|
||||||
|
|
||||||
// Create a gain node to control the volume
|
// Create a gain node to control the volume
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
oscillator.connect(gainNode);
|
oscillator.connect(gainNode);
|
||||||
|
|
||||||
// Create a stereo panner node for left-right panning
|
// Create a stereo panner node for left-right panning
|
||||||
const panner = context.createStereoPanner();
|
const panner = context.createStereoPanner();
|
||||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
||||||
gainNode.connect(panner);
|
gainNode.connect(panner);
|
||||||
panner.connect(context.destination);
|
panner.connect(context.destination);
|
||||||
panner.connect(audioRecordingTrack);
|
panner.connect(audioRecordingTrack);
|
||||||
|
|
||||||
// Set up the gain envelope to simulate the impact and quick decay
|
// Set up the gain envelope to simulate the impact and quick decay
|
||||||
gainNode.gain.setValueAtTime(0.8 * volume, context.currentTime); // Initial impact
|
gainNode.gain.setValueAtTime(0.8 * volume, context.currentTime); // Initial impact
|
||||||
gainNode.gain.exponentialRampToValueAtTime(
|
gainNode.gain.exponentialRampToValueAtTime(
|
||||||
0.001,
|
0.001,
|
||||||
context.currentTime + duration,
|
context.currentTime + duration,
|
||||||
); // Quick decay
|
); // Quick decay
|
||||||
|
|
||||||
// Start the oscillator
|
// Start the oscillator
|
||||||
oscillator.start(context.currentTime);
|
oscillator.start(context.currentTime);
|
||||||
|
|
||||||
// Stop the oscillator after the decay
|
// Stop the oscillator after the decay
|
||||||
oscillator.stop(context.currentTime + duration);
|
oscillator.stop(context.currentTime + duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
let noiseBuffer: AudioBuffer;
|
let noiseBuffer: AudioBuffer;
|
||||||
|
|
||||||
function getNoiseBuffer(context:AudioContext) {
|
function getNoiseBuffer(context: AudioContext) {
|
||||||
|
if (!noiseBuffer) {
|
||||||
|
const bufferSize = context.sampleRate * 2; // 2 seconds
|
||||||
|
noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate);
|
||||||
|
const output = noiseBuffer.getChannelData(0);
|
||||||
|
|
||||||
if (!noiseBuffer) {
|
// Fill the buffer with random noise
|
||||||
const bufferSize = context.sampleRate * 2; // 2 seconds
|
for (let i = 0; i < bufferSize; i++) {
|
||||||
noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate);
|
output[i] = Math.random() * 2 - 1;
|
||||||
const output = noiseBuffer.getChannelData(0);
|
|
||||||
|
|
||||||
// Fill the buffer with random noise
|
|
||||||
for (let i = 0; i < bufferSize; i++) {
|
|
||||||
output[i] = Math.random() * 2 - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return noiseBuffer
|
}
|
||||||
|
return noiseBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createExplosionSound(pan = 0.5) {
|
function createExplosionSound(pan = 0.5) {
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
if (!context) return
|
if (!context) return;
|
||||||
// Create an audio buffer
|
// Create an audio buffer
|
||||||
|
|
||||||
|
// Create a noise source
|
||||||
|
const noiseSource = context.createBufferSource();
|
||||||
|
noiseSource.buffer = getNoiseBuffer(context);
|
||||||
|
|
||||||
// Create a noise source
|
// Create a gain node to control the volume
|
||||||
const noiseSource = context.createBufferSource();
|
const gainNode = context.createGain();
|
||||||
noiseSource.buffer = getNoiseBuffer(context);
|
noiseSource.connect(gainNode);
|
||||||
|
|
||||||
// Create a gain node to control the volume
|
// Create a filter to shape the explosion sound
|
||||||
const gainNode = context.createGain();
|
const filter = context.createBiquadFilter();
|
||||||
noiseSource.connect(gainNode);
|
filter.type = "lowpass";
|
||||||
|
filter.frequency.setValueAtTime(1000, context.currentTime); // Set the initial frequency
|
||||||
|
gainNode.connect(filter);
|
||||||
|
|
||||||
// Create a filter to shape the explosion sound
|
// Create a stereo panner node for left-right panning
|
||||||
const filter = context.createBiquadFilter();
|
const panner = context.createStereoPanner();
|
||||||
filter.type = "lowpass";
|
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime); // pan 0 to 1 maps to -1 to 1
|
||||||
filter.frequency.setValueAtTime(1000, context.currentTime); // Set the initial frequency
|
|
||||||
gainNode.connect(filter);
|
|
||||||
|
|
||||||
// Create a stereo panner node for left-right panning
|
// Connect filter to panner and then to the destination (speakers)
|
||||||
const panner = context.createStereoPanner();
|
filter.connect(panner);
|
||||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime); // pan 0 to 1 maps to -1 to 1
|
panner.connect(context.destination);
|
||||||
|
panner.connect(audioRecordingTrack);
|
||||||
|
|
||||||
// Connect filter to panner and then to the destination (speakers)
|
// Ramp down the gain to simulate the explosion's fade-out
|
||||||
filter.connect(panner);
|
gainNode.gain.setValueAtTime(1, context.currentTime);
|
||||||
panner.connect(context.destination);
|
gainNode.gain.exponentialRampToValueAtTime(0.01, context.currentTime + 1);
|
||||||
panner.connect(audioRecordingTrack);
|
|
||||||
|
|
||||||
// Ramp down the gain to simulate the explosion's fade-out
|
// Lower the filter frequency over time to create the "explosive" effect
|
||||||
gainNode.gain.setValueAtTime(1, context.currentTime);
|
filter.frequency.exponentialRampToValueAtTime(60, context.currentTime + 1);
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.01, context.currentTime + 1);
|
|
||||||
|
|
||||||
// Lower the filter frequency over time to create the "explosive" effect
|
// Start the noise source
|
||||||
filter.frequency.exponentialRampToValueAtTime(60, context.currentTime + 1);
|
noiseSource.start(context.currentTime);
|
||||||
|
|
||||||
// Start the noise source
|
// Stop the noise source after the sound has played
|
||||||
noiseSource.start(context.currentTime);
|
noiseSource.stop(context.currentTime + 1);
|
||||||
|
|
||||||
// Stop the noise source after the sound has played
|
|
||||||
noiseSource.stop(context.currentTime + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pixelsToPan(pan: number) {
|
function pixelsToPan(pan: number) {
|
||||||
return Math.max(0, Math.min(1, (pan - offsetXRoundedDown) / gameZoneWidthRoundedUp));
|
return Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(1, (pan - offsetXRoundedDown) / gameZoneWidthRoundedUp),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastComboPlayed = NaN,
|
let lastComboPlayed = NaN,
|
||||||
shepard = 6;
|
shepard = 6;
|
||||||
|
|
||||||
function playShepard(delta: number, pan: number, volume: number) {
|
function playShepard(delta: number, pan: number, volume: number) {
|
||||||
const shepardMax = 11,
|
const shepardMax = 11,
|
||||||
factor = 1.05945594920268,
|
factor = 1.05945594920268,
|
||||||
baseNote = 392;
|
baseNote = 392;
|
||||||
shepard += delta;
|
shepard += delta;
|
||||||
if (shepard > shepardMax) shepard = 0;
|
if (shepard > shepardMax) shepard = 0;
|
||||||
if (shepard < 0) shepard = shepardMax;
|
if (shepard < 0) shepard = shepardMax;
|
||||||
|
|
||||||
const play = (note: number) => {
|
const play = (note: number) => {
|
||||||
const freq = baseNote * Math.pow(factor, note);
|
const freq = baseNote * Math.pow(factor, note);
|
||||||
const diff = Math.abs(note - shepardMax * 0.5);
|
const diff = Math.abs(note - shepardMax * 0.5);
|
||||||
const maxDistanceToIdeal = 1.5 * shepardMax;
|
const maxDistanceToIdeal = 1.5 * shepardMax;
|
||||||
const vol = Math.max(0, volume * (1 - diff / maxDistanceToIdeal));
|
const vol = Math.max(0, volume * (1 - diff / maxDistanceToIdeal));
|
||||||
createSingleBounceSound(freq, pan, vol);
|
createSingleBounceSound(freq, pan, vol);
|
||||||
return freq.toFixed(2) + " at " + Math.floor(vol * 100) + "% diff " + diff;
|
return freq.toFixed(2) + " at " + Math.floor(vol * 100) + "% diff " + diff;
|
||||||
};
|
};
|
||||||
|
|
||||||
play(1 + shepardMax + shepard);
|
play(1 + shepardMax + shepard);
|
||||||
play(shepard);
|
play(shepard);
|
||||||
play(-1 - shepardMax + shepard);
|
play(-1 - shepardMax + shepard);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createShatteredGlassSound(pan:number) {
|
function createShatteredGlassSound(pan: number) {
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
if (!context) return
|
if (!context) return;
|
||||||
const oscillators = [
|
const oscillators = [
|
||||||
createOscillator(context, 3000, 'square'),
|
createOscillator(context, 3000, "square"),
|
||||||
createOscillator(context, 4500, 'square'),
|
createOscillator(context, 4500, "square"),
|
||||||
createOscillator(context, 6000, 'square')
|
createOscillator(context, 6000, "square"),
|
||||||
];
|
];
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
const noiseSource = context.createBufferSource();
|
const noiseSource = context.createBufferSource();
|
||||||
noiseSource.buffer = getNoiseBuffer(context);
|
noiseSource.buffer = getNoiseBuffer(context);
|
||||||
|
|
||||||
oscillators.forEach(oscillator => oscillator.connect(gainNode));
|
oscillators.forEach((oscillator) => oscillator.connect(gainNode));
|
||||||
noiseSource.connect(gainNode);
|
noiseSource.connect(gainNode);
|
||||||
gainNode.gain.setValueAtTime(0.2, context.currentTime);
|
gainNode.gain.setValueAtTime(0.2, context.currentTime);
|
||||||
oscillators.forEach(oscillator => oscillator.start());
|
oscillators.forEach((oscillator) => oscillator.start());
|
||||||
noiseSource.start();
|
noiseSource.start();
|
||||||
oscillators.forEach(oscillator => oscillator.stop(context.currentTime + 0.2));
|
oscillators.forEach((oscillator) =>
|
||||||
noiseSource.stop(context.currentTime + 0.2);
|
oscillator.stop(context.currentTime + 0.2),
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.2);
|
);
|
||||||
|
noiseSource.stop(context.currentTime + 0.2);
|
||||||
|
gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.2);
|
||||||
|
|
||||||
|
// Create a stereo panner node for left-right panning
|
||||||
|
const panner = context.createStereoPanner();
|
||||||
|
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
||||||
|
gainNode.connect(panner);
|
||||||
|
panner.connect(context.destination);
|
||||||
|
panner.connect(audioRecordingTrack);
|
||||||
|
|
||||||
// Create a stereo panner node for left-right panning
|
gainNode.connect(panner);
|
||||||
const panner = context.createStereoPanner();
|
|
||||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
|
||||||
gainNode.connect(panner);
|
|
||||||
panner.connect(context.destination);
|
|
||||||
panner.connect(audioRecordingTrack);
|
|
||||||
|
|
||||||
gainNode.connect(panner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to create an oscillator with a specific frequency
|
// Helper function to create an oscillator with a specific frequency
|
||||||
function createOscillator(context:AudioContext, frequency:number, type:OscillatorType) {
|
function createOscillator(
|
||||||
const oscillator = context.createOscillator();
|
context: AudioContext,
|
||||||
oscillator.type =type
|
frequency: number,
|
||||||
oscillator.frequency.setValueAtTime(frequency, context.currentTime);
|
type: OscillatorType,
|
||||||
return oscillator;
|
) {
|
||||||
}
|
const oscillator = context.createOscillator();
|
||||||
|
oscillator.type = type;
|
||||||
|
oscillator.frequency.setValueAtTime(frequency, context.currentTime);
|
||||||
|
return oscillator;
|
||||||
|
}
|
||||||
|
|
2
src/types.d.ts
vendored
2
src/types.d.ts
vendored
|
@ -6,7 +6,7 @@ export type RawLevel = {
|
||||||
name: string;
|
name: string;
|
||||||
size: number;
|
size: number;
|
||||||
bricks: string;
|
bricks: string;
|
||||||
svg: number|null;
|
svg: number | null;
|
||||||
color: string;
|
color: string;
|
||||||
};
|
};
|
||||||
export type Level = {
|
export type Level = {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29028296"
|
"29030872"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue