mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-23 21:46:15 -04:00
wip
This commit is contained in:
parent
d848ad511e
commit
78c8e154c6
17 changed files with 372 additions and 1521 deletions
26
src/game.ts
26
src/game.ts
|
@ -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
24
src/getLevelBackground.ts
Normal 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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
]
|
||||
]
|
|
@ -28,6 +28,9 @@ body {
|
|||
.level-bricks-preview {
|
||||
position: relative;
|
||||
}
|
||||
input[type="number"]{
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
& > div {
|
||||
display: grid;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue