diff options
| author | LLLL Colonq <llll@colonq> | 2026-08-29 04:06:51 -0400 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2026-08-29 04:06:51 -0400 |
| commit | 761a3172bf4c15aed3836e4d1cd6f815b651b0e0 (patch) | |
| tree | cc90491529e83349d84d42a8e9982e5f0f38338e /2026/games_submissions/the0x539/main.js | |
| parent | 0d2d8cd897e94bd94e0b3ae7c6ce9aa580a44a0a (diff) | |
Fix
Diffstat (limited to '2026/games_submissions/the0x539/main.js')
| -rw-r--r-- | 2026/games_submissions/the0x539/main.js | 197 |
1 files changed, 0 insertions, 197 deletions
diff --git a/2026/games_submissions/the0x539/main.js b/2026/games_submissions/the0x539/main.js deleted file mode 100644 index 14a2b45..0000000 --- a/2026/games_submissions/the0x539/main.js +++ /dev/null @@ -1,197 +0,0 @@ -import { recipes, amounts } from './data.js'; -import { - createItem, - mouseDown, - mouseEnter, - mouseUp, - craftClick, - consumeClock, - resetInventory, -} from './interaction.js'; -import { scenarios } from './difficulty.js'; - -const followCursor = document.querySelector('follow-cursor'); -const tooltip = document.querySelector('item-tooltip'); -const craftingGrid = document.querySelector('crafting-grid'); -const inventoryGrid = document.querySelector('inventory-grid'); -const craftingOutput = document.querySelector('crafting-output'); -const todoList = document.getElementById('todo-list'); - -const desiredCrafts = new Set(); - -const playSound = { - playImpl(id, volume = 1.0, pitch = 1.0) { - const audio = document.getElementById(id); - - audio.currentTime = 0; - - const p = new Promise(resolve => { - const f = (event) => { - audio.removeEventListener('ended', f); - resolve(event); - }; - audio.addEventListener('ended', f); - }); - - audio.volume = volume; - audio.playbackRate = pitch; - audio.preservesPitch = false; - - audio.play(); - return p; - }, - - smallDing() { - return this.playImpl('small-ding', 0.1, 0.55 + 0.7 * Math.random()); - }, - - bigDing() { - return this.playImpl('big-ding', 0.75); - }, - - oof() { - return this.playImpl('oof', 0.75); - }, -}; - -function onCraft(event) { - const item = event.item; - if (desiredCrafts.has(item)) { - desiredCrafts.delete(item); - - document.querySelector(`#todo-list > li:has([data-item="${item}"])`)?.remove(); - - if (desiredCrafts.size > 0) { - playSound.smallDing(); - } else { - endGame(true); - } - } -} - -function handleMessage(msg) { - if (msg.op === 'start') { - startGame(msg.difficulty); - } -} - -function giveItem(item, count) { - const emptySlots = document.querySelectorAll('inventory-grid > inventory-cell:empty'); - const index = Math.floor(Math.random() * emptySlots.length); - emptySlots[index].appendChild(createItem(item, count)); -} - -let timerInterval = null; - -function timer() { - if (!document.querySelector('item-stack[data-item="clock"]:not(crafting-output item-stack)')) { - // time's up! - endGame(false); - } else { - consumeClock(); - } -} - -function startGame(difficulty) { - document.body.classList.remove('failed'); - - resetInventory(); - - const scenario = scenarios.toReversed().find(s => difficulty >= s.level); - - desiredCrafts.clear(); - for (const item of scenario.goal) { - desiredCrafts.add(item); - } - - todoList.replaceChildren(); - for (const item of desiredCrafts) { - const listItem = document.createElement('li'); - - const stack = document.createElement('item-stack'); - stack.setAttribute('data-item', item); - listItem.append(stack); - - todoList.append(listItem); - } - - for (const [item, amount] of Object.entries(scenario.items)) { - giveItem(item, amount); - } - giveItem('clock', scenario.time(difficulty - scenario.level)); - - document.addEventListener('mousemove', onMouseMove); - timerInterval = setInterval(timer, 1000); - window.parent.postMessage({ op: 'started', verb: 'craft!' }); -} - -async function endGame(win) { - clearInterval(timerInterval); - timerInterval = null; - if (win) { - await playSound.bigDing(); - } else { - document.body.classList.add('failed'); - await playSound.oof(); - } - await new Promise(resolve => setTimeout(resolve, 500)); - document.removeEventListener('mousemove', onMouseMove); - window.parent.postMessage({ op: 'done', win }); -} - -function createCell() { - const elem = document.createElement('inventory-cell'); - elem.addEventListener('mousedown', mouseDown); - elem.addEventListener('mouseenter', mouseEnter); - return elem; -} - -function onMouseMove(event) { - followCursor.setAttribute('style', `left: ${event.clientX}px; top: ${event.clientY}px`); - - const hoverItem = document.querySelector('item-stack:hover'); - if (hoverItem !== null) { - const name = hoverItem.getAttribute('data-item'); - tooltip.textContent = name; - } else { - tooltip.textContent = ''; - } -} - -document.addEventListener('contextmenu', e => e.preventDefault()); - -const allItems = new Set(); -for (const [output, shape] of Object.entries(recipes)) { - allItems.add(output); - for (const item of shape.flat()) { - if (item) { - allItems.add(item); - } - } -} - -const stylesheet = document.styleSheets[0]; - -for (const item of allItems) { - stylesheet.insertRule(` - item-stack[data-item="${item}"]::before { - background-image: url("./items/${item}.png"); - } - `); -} - -for (let i = 0; i < 3 * 3; i++) { - craftingGrid.appendChild(createCell()); -} - -for (let i = 0; i < 12 * 3; i++) { - inventoryGrid.appendChild(createCell()); -} - -document.addEventListener('mouseup', mouseUp); -document.addEventListener('craft', onCraft); - -craftingOutput.addEventListener('click', craftClick); - -window.addEventListener('message', m => handleMessage(m.data)); -window.parent.postMessage({ op: 'ready' }); |
