This commit is contained in:
Renan LE CARO 2025-03-13 14:14:00 +01:00
parent d848ad511e
commit 78c8e154c6
17 changed files with 372 additions and 1521 deletions

View file

@ -117,7 +117,9 @@ let running = false,
function play() {
if (running) return;
running = true;
getAudioContext()?.resume().then();
startRecordingGame();
getAudioContext()?.resume();
resumeRecording();
document.body.className = running ? " running " : " paused ";
}
@ -132,7 +134,7 @@ function pause(playerAskedForPause: boolean) {
needsRender = true;
setTimeout(() => {
if (!running) getAudioContext()?.suspend().then();
if (!running) getAudioContext()?.suspend();
}, 1000);
pauseRecording();
@ -446,9 +448,10 @@ async function openUpgradesPicker() {
}
function setLevel(l: number) {
stopRecording();
pause(false);
if (l > 0) {
openUpgradesPicker().then();
openUpgradesPicker();
}
currentLevel = l;
@ -476,8 +479,6 @@ function setLevel(l: number) {
// This caused problems with accented characters like the ô of côte d'ivoire for odd reasons
// background.src = 'data:image/svg+xml;base64,' + btoa(lvl.svg)
background.src = "data:image/svg+xml;UTF8," + lvl.svg;
stopRecording();
startRecordingGame();
}
function currentLevelInfo() {
@ -625,7 +626,7 @@ gameCanvas.addEventListener("mouseup", (e) => {
} else {
play();
if (isSettingOn("pointerLock")) {
gameCanvas.requestPointerLock().then();
gameCanvas.requestPointerLock();
}
}
});
@ -2516,7 +2517,7 @@ export function toggleSetting(key: OptionId) {
scoreDisplay.addEventListener("click", (e) => {
e.preventDefault();
openScorePanel().then();
openScorePanel();
});
async function openScorePanel() {
@ -2551,7 +2552,7 @@ async function openScorePanel() {
document.getElementById("menu")?.addEventListener("click", (e) => {
e.preventDefault();
openSettingsPanel().then();
openSettingsPanel();
});
async function openSettingsPanel() {
@ -2941,6 +2942,7 @@ function startRecordingGame() {
if (!isSettingOn("record")) {
return;
}
if(mediaRecorder) return;
if (!recordCanvas) {
// Smaller canvas with fewer details
recordCanvas = document.createElement("canvas");
@ -3058,14 +3060,14 @@ function toggleFullScreen() {
try {
if (document.fullscreenElement !== null) {
if (document.exitFullscreen) {
document.exitFullscreen().then();
document.exitFullscreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
} else {
const docel = document.documentElement;
if (docel.requestFullscreen) {
docel.requestFullscreen().then();
docel.requestFullscreen();
} else if (docel.webkitRequestFullscreen) {
docel.webkitRequestFullscreen();
}
@ -3127,9 +3129,9 @@ document.addEventListener("keyup", (e) => {
} else if (e.key === "Escape" && running) {
pause(true);
} else if (e.key.toLowerCase() === "m" && !alertsOpen) {
openSettingsPanel().then();
openSettingsPanel();
} else if (e.key.toLowerCase() === "s" && !alertsOpen) {
openScorePanel().then();
openScorePanel();
} else {
return;
}

24
src/getLevelBackground.ts Normal file
View file

@ -0,0 +1,24 @@
import {RawLevel} from "./types";
export function hashCode(string: string) {
let hash = 0;
for (let i = 0; i < string.length; i++) {
let code = string.charCodeAt(i);
hash = (hash << 5) - hash + code;
hash = hash & hash; // Convert to 32bit integer
}
return Math.abs(hash);
}
import _backgrounds from "./backgrounds.json";
const backgrounds = _backgrounds as string[];
export function getLevelBackground(level:RawLevel){
let svg = level.svg !== null && backgrounds[level.svg % backgrounds.length];
if (!level.color && !svg) {
svg = backgrounds[hashCode(level.name) % backgrounds.length];
}
return svg
}

View file

@ -116,7 +116,7 @@
"name": "We come in peace",
"size": 13,
"bricks": "________________a_____a_______a___a_______aaaaaaa_____aaBaaaBaa___aaaaaaaaaaa__aaaaaaaaaaa__a_aaaaaaa_a__a_a_____a_a_____aa_aa_____________________________",
"svg": 24,
"svg": 29,
"color": ""
},
{
@ -151,8 +151,8 @@
"name": "Enderman",
"size": 10,
"bricks": "___________gggggggg__gggggggg__gggggggg__gggggggg__vvvggvvv__gggggggg__gggggggg__gggggggg_____________________",
"svg": "",
"color": "#26a269"
"svg": null,
"color": "#154b07"
},
{
"name": "Mushroom",
@ -165,7 +165,7 @@
"name": "Tulip",
"size": 11,
"bricks": "______________R_R_R______RRRRR______RRRRR______RRRRR_______RRR_________k________k_k_k______k_k_k_______kkk_________k________________",
"svg": 29,
"svg": 17,
"color": ""
},
{
@ -179,7 +179,7 @@
"name": "Marion",
"size": 9,
"bricks": "rr_____rr_rr___rr__rrr_rrr__rrrrrrr__rr_r_rr__rr___rr__rr___rr__rr___rr_rrr___rrr",
"svg": null,
"svg": 27,
"color": ""
},
{
@ -835,4 +835,4 @@
"bricks": "_W__W_WW__WW____________WW__WW_W__W_",
"svg": null
}
]
]

View file

@ -28,6 +28,9 @@ body {
.level-bricks-preview {
position: relative;
}
input[type="number"]{
width: 50px;
}
& > div {
display: grid;

View file

@ -1,11 +1,14 @@
import {Palette, RawLevel} from "./types";
import _backgrounds from './backgrounds.json'
const backgrounds=_backgrounds as string[];
import _palette from './palette.json'
const palette=_palette as Palette;
import _allLevels from './levels.json'
let allLevels = _allLevels as RawLevel[];
import _backgrounds from './backgrounds.json'
const backgrounds = _backgrounds as string[];
import _palette from './palette.json'
const palette = _palette as Palette;
import _allLevels from './levels.json'
import {getLevelBackground, hashCode} from "./getLevelBackground";
let allLevels = _allLevels as RawLevel[];
let currentCode = '_'
@ -38,14 +41,16 @@ function renderAllLevels() {
addLevelEditorToList(level, levelIndex)
})
}
const levelsListEl = document?.getElementById('levels') as HTMLDivElement
function addLevelEditorToList(level:RawLevel, levelIndex:number) {
function addLevelEditorToList(level: RawLevel, levelIndex: number) {
const {name, bricks, size, svg, color} = level
let div = document.createElement('div')
div.innerHTML = `
<button data-level="${levelIndex}" data-rename="yep">${name}</button>
<input type="text" value="${level.name || ''}" data-level="${levelIndex}" data-text-val="name" />
<div>
<button data-level="${levelIndex}" data-delete="yep">Delete</button>
<button data-offset-level-size="-1" data-level="${levelIndex}">-</button>
@ -54,10 +59,9 @@ function addLevelEditorToList(level:RawLevel, levelIndex:number) {
<button data-offset-x="1" data-offset-y="0" data-level="${levelIndex}">R</button>
<button data-offset-x="0" data-offset-y="-1" data-level="${levelIndex}">U</button>
<button data-offset-x="0" data-offset-y="1" data-level="${levelIndex}">D</button>
<input type="color" value="${level.color || ''}" data-level="${levelIndex}" />
<input type="color" value="${level.color || ''}" data-level="${levelIndex}" data-text-val="color" />
<input type="number" value="${level.svg || (hashCode(level.name) % backgrounds.length)}" data-level="${levelIndex}" data-num-val="svg" />
<button data-level="${levelIndex}" data-set-bg-svg="true" >${svg ? 'replace' : 'set'}</button>
</div>
@ -74,17 +78,16 @@ function addLevelEditorToList(level:RawLevel, levelIndex:number) {
}
function updateLevelBackground(levelIndex:number) {
function updateLevelBackground(levelIndex: number) {
const div = document.getElementById("bricks-of-" + levelIndex) as HTMLDivElement
const level = allLevels[levelIndex]
const {svg, color} = level
if (color) {
Object.assign(div.style, {backgroundImage: 'none', backgroundColor: color})
} else {
const index = svg || (hashCode(level.name) % backgrounds.length)
const svgSource=backgrounds[index]
console.log(index)
div.setAttribute('data-svg',svgSource)
const svgSource = getLevelBackground(level) as string
div.setAttribute('data-svg', svgSource)
Object.assign(div.style, {
backgroundImage: `url("data:image/svg+xml;UTF8,${encodeURIComponent(svgSource)}")`,
backgroundColor: 'transparent'
@ -93,7 +96,7 @@ function updateLevelBackground(levelIndex:number) {
}
function renderLevelBricks(levelIndex:number) {
function renderLevelBricks(levelIndex: number) {
const {size, bricks} = allLevels[levelIndex]
const buttons = []
@ -114,22 +117,30 @@ function renderLevelBricks(levelIndex:number) {
levelsListEl.addEventListener('change', e => {
const target= e.target as HTMLInputElement
const levelIndexStr = target.getAttribute('data-level')
if (levelIndexStr) {
const levelIndex = parseInt(levelIndexStr)
const level = allLevels[levelIndex]
if (target.getAttribute('type') === 'color') {
level.color = target.value
level.svg = null
updateLevelBackground(levelIndex)
}
save()
}
const target = e.target as HTMLInputElement
const levelIndexStr = target.getAttribute('data-level')
if (!levelIndexStr) return
const levelIndex = parseInt(levelIndexStr)
const level = allLevels[levelIndex]
if (target.getAttribute('data-text-val') == 'name') {
level.name = target.value
}
if (target.getAttribute('data-text-val') == 'color') {
level.color = target.value
level.svg = null
}
if (target.getAttribute('data-num-val') == 'svg') {
level.color = ''
level.svg = parseFloat(target.value)
}
updateLevelBackground(levelIndex)
save()
})
levelsListEl.addEventListener('click', e => {
const target= e.target as HTMLButtonElement
const target = e.target as HTMLButtonElement
if (target.tagName !== 'BUTTON') return
const resize = target.getAttribute('data-offset-level-size')
@ -181,8 +192,8 @@ levelsListEl.addEventListener('click', e => {
let applying = ''
function colorPixel(e:Event) {
const target= e.target as HTMLButtonElement
function colorPixel(e: Event) {
const target = e.target as HTMLButtonElement
if (applying === '') return
console.log('colorPixel', applying)
const index = target.getAttribute('data-set-color-of')
@ -194,18 +205,18 @@ function colorPixel(e:Event) {
}
}
function setBrick(levelIndex:number, index:number, chr:string) {
function setBrick(levelIndex: number, index: number, chr: string) {
const bricks = allLevels[levelIndex].bricks
allLevels[levelIndex].bricks = bricks.substring(0, index) + chr + bricks.substring(index + 1);
}
let changed=0
let changed = 0
levelsListEl.addEventListener('mousedown', e => {
const target= e.target as HTMLButtonElement
const index = target.getAttribute('data-set-color-of')
const target = e.target as HTMLButtonElement
const index = target.getAttribute('data-set-color-of')
const level = target.getAttribute('data-level')
if ( index && level) {
changed=0
if (index && level) {
changed = 0
const before = allLevels[parseInt(level)].bricks[parseInt(index)] || ''
applying = before === currentCode ? '_' : currentCode
console.log({before, applying, currentCode})
@ -220,15 +231,16 @@ levelsListEl.addEventListener('mouseenter', e => {
}
}, true);
document.addEventListener('mouseup', (e:Event) => {
document.addEventListener('mouseup', (e: Event) => {
applying = '';
if(changed) {
if (changed) {
save()
};
}
;
});
(document.getElementById('new-level') as HTMLButtonElement).addEventListener('click', (e:Event) => {
(document.getElementById('new-level') as HTMLButtonElement).addEventListener('click', (e: Event) => {
const name = prompt("Name ? ")
if (!name) return;
@ -238,7 +250,7 @@ document.addEventListener('mouseup', (e:Event) => {
size: 8,
bricks: '________________________________________________________________',
svg: null,
color:''
color: ''
})
const levelIndex = allLevels.length - 1
addLevelEditorToList(allLevels[levelIndex], levelIndex)
@ -256,13 +268,3 @@ function save() {
body: JSON.stringify(allLevels, null, 2)
})
}
function hashCode(string:string) {
let hash = 0;
for (let i = 0; i < string.length; i++) {
let code = string.charCodeAt(i);
hash = ((hash << 5) - hash) + code;
hash = hash & hash; // Convert to 32bit integer
}
return Math.abs(hash);
}

View file

@ -3,8 +3,7 @@ import _palette from "./palette.json";
import _rawLevelsList from "./levels.json";
import _appVersion from "./version.json";
import { rawUpgrades } from "./rawUpgrades";
import _backgrounds from "./backgrounds.json";
const backgrounds = _backgrounds as string[];
import {getLevelBackground} from "./getLevelBackground";
const palette = _palette as Palette;
const rawLevelsList = _rawLevelsList as RawLevel[];
@ -50,7 +49,7 @@ function levelIconHTML(
}
}
}
// I don't think many blind people will benefit for this but it's nice to have something to put in "alt"
// I don't think many blind people will benefit for this, but it's nice to have something to put in "alt"
return `<img alt="${levelName}" width="${size}" height="${size}" src="${c.toDataURL()}"/>`;
}
@ -64,16 +63,11 @@ export const allLevels = rawLevelsList
.slice(0, level.size * level.size);
const icon = levelIconHTML(bricks, level.size, level.name, level.color);
icons[level.name] = icon;
let svg = level.svg !== null && backgrounds[level.svg];
if (!level.color && !svg) {
svg = backgrounds[hashCode(level.name) % backgrounds.length];
}
return {
...level,
bricks,
icon,
svg,
svg:getLevelBackground(level),
};
})
.filter((l) => !l.name.startsWith("icon:"))
@ -92,13 +86,3 @@ export const upgrades = rawUpgrades.map((u) => ({
...u,
icon: icons["icon:" + u.id],
})) as Upgrade[];
function hashCode(string: string) {
let hash = 0;
for (let i = 0; i < string.length; i++) {
let code = string.charCodeAt(i);
hash = (hash << 5) - hash + code;
hash = hash & hash; // Convert to 32bit integer
}
return Math.abs(hash);
}