Fixed enderman level background and level picker in unlock

This commit is contained in:
Renan LE CARO 2025-03-13 08:52:20 +01:00
parent f28ce15495
commit e14e958686
6 changed files with 94 additions and 55 deletions

21
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,7 @@ const paletteEl = document.getElementById('palette');
Object.entries(palette).forEach(([code, color]) => { Object.entries(palette).forEach(([code, color]) => {
const btn = document.createElement('button') const btn = document.createElement('button')
Object.assign(btn.style, { Object.assign(btn.style, {
background: color ||'linear-gradient(45deg,black,white)', background: color || 'linear-gradient(45deg,black,white)',
display: 'inline-block', display: 'inline-block',
width: '40px', width: '40px',
height: '40px', height: '40px',
@ -26,12 +26,11 @@ Object.entries(palette).forEach(([code, color]) => {
function renderAllLevels() { function renderAllLevels() {
allLevels.forEach((level, levelIndex) => { allLevels.forEach((level, levelIndex) => {
addLevelEditorToList(level, levelIndex) addLevelEditorToList(level, levelIndex)
}) })
} }
function addLevelEditorToList(level, levelIndex) { function addLevelEditorToList(level, levelIndex) {
const {name, bricks, size, svg,color} = level const {name, bricks, size, svg, color} = level
let div = document.createElement('div') let div = document.createElement('div')
@ -46,7 +45,9 @@ function addLevelEditorToList(level, levelIndex) {
<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}">U</button>
<button data-offset-x="0" data-offset-y="1" data-level="${levelIndex}">D</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}" />
<button data-level="${levelIndex}" data-set-bg-svg="true" >${svg?'replace':'set'}</button> <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> </div>
@ -54,6 +55,8 @@ function addLevelEditorToList(level, levelIndex) {
<div class="level-bricks-preview" id="bricks-of-${levelIndex}" > <div class="level-bricks-preview" id="bricks-of-${levelIndex}" >
</div> </div>
`; `;
document.getElementById('levels').appendChild(div) document.getElementById('levels').appendChild(div)
renderLevelBricks(levelIndex) renderLevelBricks(levelIndex)
@ -61,13 +64,23 @@ function addLevelEditorToList(level, levelIndex) {
} }
function updateLevelBackground(levelIndex){ function updateLevelBackground(levelIndex) {
const div=document.getElementById("bricks-of-"+levelIndex) const div = document.getElementById("bricks-of-" + levelIndex)
const {svg, color}= allLevels[levelIndex] const level = allLevels[levelIndex]
Object.assign(div.style, svg ? const {svg, color} = level
{backgroundImage:`url('data:image/svg+xml,${encodeURIComponent(svg)}')`, backgroundColor:'transparent'} : if (color) {
{backgroundImage:'none', backgroundColor:color||'#111'} 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)
Object.assign(div.style, {
backgroundImage: `url("data:image/svg+xml;UTF8,${encodeURIComponent(svgSource)}")`,
backgroundColor: 'transparent'
})
}
} }
function renderLevelBricks(levelIndex) { function renderLevelBricks(levelIndex) {
@ -90,21 +103,20 @@ function renderLevelBricks(levelIndex) {
} }
document.getElementById('levels').addEventListener('change', e => { document.getElementById('levels').addEventListener('change', e => {
const levelIndexStr = e.target.getAttribute('data-level') const levelIndexStr = e.target.getAttribute('data-level')
if ( levelIndexStr) { if (levelIndexStr) {
const levelIndex = parseInt(levelIndexStr) const levelIndex = parseInt(levelIndexStr)
const level = allLevels[levelIndex] const level = allLevels[levelIndex]
if( e.target.getAttribute('type') === 'color'){ if (e.target.getAttribute('type') === 'color') {
level.color = e.target.value level.color = e.target.value
level.svg = '' level.svg = ''
updateLevelBackground(levelIndex) updateLevelBackground(levelIndex)
}else if( e.target.getAttribute('type') === 'checkbox' && e.target.hasAttribute('data-field')){ } else if (e.target.getAttribute('type') === 'checkbox' && e.target.hasAttribute('data-field')) {
const field=e.target.getAttribute('data-field') const field = e.target.getAttribute('data-field')
if(field==='focus'){ if (field === 'focus') {
allLevels.forEach(l=>l.focus=false) allLevels.forEach(l => l.focus = false)
} }
level[field] = !!e.target.checked level[field] = !!e.target.checked
@ -120,7 +132,7 @@ document.getElementById('levels').addEventListener('click', e => {
const moveY = e.target.getAttribute('data-offset-y') const moveY = e.target.getAttribute('data-offset-y')
const levelIndexStr = e.target.getAttribute('data-level') const levelIndexStr = e.target.getAttribute('data-level')
if (!levelIndexStr) return if (!levelIndexStr) return
if (e.target.tagName!=='BUTTON') return if (e.target.tagName !== 'BUTTON') return
const levelIndex = parseInt(levelIndexStr) const levelIndex = parseInt(levelIndexStr)
const level = allLevels[levelIndex] const level = allLevels[levelIndex]
@ -128,39 +140,39 @@ document.getElementById('levels').addEventListener('click', e => {
if (resize) { if (resize) {
const newSize = size + parseInt(resize) const newSize = size + parseInt(resize)
const newBricks = new Array(newSize*newSize).fill('_') const newBricks = new Array(newSize * newSize).fill('_')
for (let x = 0; x < Math.min(size, newSize); x++) { for (let x = 0; x < Math.min(size, newSize); x++) {
for (let y = 0; y < Math.min(size, newSize); y++) { for (let y = 0; y < Math.min(size, newSize); y++) {
newBricks[y * newSize + x] = bricks.split('')[y * size + x] || '_' newBricks[y * newSize + x] = bricks.split('')[y * size + x] || '_'
} }
} }
level.size = newSize; level.size = newSize;
level.bricks = newBricks.map(b=>b||'_').join(''); level.bricks = newBricks.map(b => b || '_').join('');
} else if (moveX && moveY) { } else if (moveX && moveY) {
const dx = parseInt(moveX), dy = parseInt(moveY) const dx = parseInt(moveX), dy = parseInt(moveY)
const newBricks = new Array(size*size).fill('_') const newBricks = new Array(size * size).fill('_')
for (let x = 0; x < size; x++) { for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) { for (let y = 0; y < size; y++) {
newBricks[(y + dy) * size + (x + dx)] = bricks.split('')[y * size + x]|| '_' newBricks[(y + dy) * size + (x + dx)] = bricks.split('')[y * size + x] || '_'
} }
} }
level.bricks = newBricks.map(b=>b||'_').join(''); level.bricks = newBricks.map(b => b || '_').join('');
} else if (e.target.getAttribute('data-rename')) { } else if (e.target.getAttribute('data-rename')) {
const newName = prompt('Name ? ', level.name) const newName = prompt('Name ? ', level.name)
if (newName) { if (newName) {
level.name = newName level.name = newName
e.target.textContent = newName e.target.textContent = newName
} }
}else if (e.target.getAttribute('data-delete')) { } else if (e.target.getAttribute('data-delete')) {
if (confirm('Delete level')) { if (confirm('Delete level')) {
allLevels=allLevels.filter((l,i)=>i!==levelIndex) allLevels = allLevels.filter((l, i) => i !== levelIndex)
save().then(()=>window.location.reload()) save().then(() => window.location.reload())
} }
}else if(e.target.getAttribute('data-set-bg-svg')){ } else if (e.target.getAttribute('data-set-bg-svg')) {
const newBg = prompt('New svg code',level.svg||'') const newBg = prompt('New svg code', level.svg || '')
if(newBg){ if (newBg) {
level.svg=newBg level.svg = newBg
level.color = '' level.color = ''
} }
@ -175,24 +187,26 @@ document.getElementById('levels').addEventListener('click', e => {
let applying = '' let applying = ''
function colorPixel(e) { function colorPixel(e) {
if ( applying === '') return if (applying === '') return
console.log('colorPixel',applying) console.log('colorPixel', applying)
const index = e.target.getAttribute('data-set-color-of') const index = e.target.getAttribute('data-set-color-of')
const level = e.target.getAttribute('data-level') const level = e.target.getAttribute('data-level')
if (index && level) { if (index && level) {
const levelIndex = parseInt(level) const levelIndex = parseInt(level)
e.target.style.background = palette[applying]||'transparent' e.target.style.background = palette[applying] || 'transparent'
setBrick(levelIndex,parseInt(index),applying) setBrick(levelIndex, parseInt(index), applying)
} }
} }
function setBrick(levelIndex,index,chr) {
const bricks=allLevels[levelIndex].bricks function setBrick(levelIndex, index, chr) {
allLevels[levelIndex].bricks = bricks.substring(0,index) + chr + bricks.substring(index+1); const bricks = allLevels[levelIndex].bricks
allLevels[levelIndex].bricks = bricks.substring(0, index) + chr + bricks.substring(index + 1);
} }
document.getElementById('levels').addEventListener('mousedown', e => { document.getElementById('levels').addEventListener('mousedown', e => {
const index = parseInt(e.target.getAttribute('data-set-color-of')) const index = parseInt(e.target.getAttribute('data-set-color-of'))
const level = e.target.getAttribute('data-level') const level = e.target.getAttribute('data-level')
if (typeof index !=="undefined" && level) { if (typeof index !== "undefined" && level) {
const before = allLevels[parseInt(level)].bricks[index] || '' const before = allLevels[parseInt(level)].bricks[index] || ''
applying = before === currentCode ? '_' : currentCode applying = before === currentCode ? '_' : currentCode
console.log({before, applying, currentCode}) console.log({before, applying, currentCode})
@ -238,3 +252,13 @@ function save() {
body: JSON.stringify(allLevels, null, 2) body: JSON.stringify(allLevels, null, 2)
}) })
} }
function hashCode(string) {
var hash = 0;
for (var i = 0; i < string.length; i++) {
var code = string.charCodeAt(i);
hash = ((hash << 5) - hash) + code;
hash = hash & hash; // Convert to 32bit integer
}
return Math.abs(hash);
}

View file

@ -34,6 +34,7 @@ ${fs.readFileSync('./editclient.css').toString()}
<script> <script>
let allLevels = ${fs.readFileSync(srcPath).toString()}; let allLevels = ${fs.readFileSync(srcPath).toString()};
let palette = ${fs.readFileSync('src/palette.json').toString()}; let palette = ${fs.readFileSync('src/palette.json').toString()};
let backgrounds = ${fs.readFileSync('src/backgrounds.json').toString()};
${fs.readFileSync('./editclient.js').toString()} ${fs.readFileSync('./editclient.js').toString()}
</script> </script>
</body> </body>

View file

@ -495,13 +495,13 @@ function getPossibleUpgrades() {
function shuffleLevels(nameToAvoid: string | null = null) { function shuffleLevels(nameToAvoid: string | null = null) {
const target = nextRunOverrides?.level; const target = nextRunOverrides?.level;
delete nextRunOverrides.level; delete nextRunOverrides.level;
const firstLevel = nextRunOverrides?.level const firstLevel = target
? allLevels.filter((l) => l.name === target) ? allLevels.filter((l) => l.name === target)
: []; : [];
const restInRandomOrder = allLevels const restInRandomOrder = allLevels
.filter((l) => totalScoreAtRunStart >= l.threshold) .filter((l) => totalScoreAtRunStart >= l.threshold)
.filter((l) => l.name !== nextRunOverrides?.level) .filter((l) => l.name !== target)
.filter((l) => l.name !== nameToAvoid || allLevels.length === 1) .filter((l) => l.name !== nameToAvoid || allLevels.length === 1)
.sort(() => Math.random() - 0.5); .sort(() => Math.random() - 0.5);

View file

@ -151,8 +151,8 @@
"name": "Enderman", "name": "Enderman",
"size": 10, "size": 10,
"bricks": "___________gggggggg__gggggggg__gggggggg__gggggggg__vvvggvvv__gggggggg__gggggggg__gggggggg_____________________", "bricks": "___________gggggggg__gggggggg__gggggggg__gggggggg__vvvggvvv__gggggggg__gggggggg__gggggggg_____________________",
"svg": null, "svg": "",
"color": "#ffffff" "color": "#26a269"
}, },
{ {
"name": "Mushroom", "name": "Mushroom",

View file

@ -11,7 +11,6 @@ const rawLevelsList = _rawLevelsList as RawLevel[];
export const appVersion = _appVersion as string; export const appVersion = _appVersion as string;
let attributed = 0;
let levelIconHTMLCanvas = document.createElement("canvas"); let levelIconHTMLCanvas = document.createElement("canvas");
const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", { const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", {
@ -69,8 +68,7 @@ export const allLevels = rawLevelsList
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[attributed % backgrounds.length]; svg = backgrounds[hashCode(level.name) % backgrounds.length];
attributed++;
} }
return { return {
...level, ...level,
@ -95,3 +93,14 @@ export const upgrades = rawUpgrades.map((u) => ({
...u, ...u,
icon: icons["icon:" + u.id], icon: icons["icon:" + u.id],
})) as Upgrade[]; })) 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);
}