Icone a pixel per gli oggetti dell'inventario: squama, libro e chiave
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017egeN2amL84ErjfgQFtEDn
This commit is contained in:
@@ -7,6 +7,7 @@ COPY src /usr/share/nginx/html/src
|
|||||||
COPY assets/scenes /usr/share/nginx/html/assets/scenes
|
COPY assets/scenes /usr/share/nginx/html/assets/scenes
|
||||||
COPY assets/characters /usr/share/nginx/html/assets/characters
|
COPY assets/characters /usr/share/nginx/html/assets/characters
|
||||||
COPY assets/audio /usr/share/nginx/html/assets/audio
|
COPY assets/audio /usr/share/nginx/html/assets/audio
|
||||||
|
COPY assets/icons /usr/share/nginx/html/assets/icons
|
||||||
COPY assets/voices /usr/share/nginx/html/assets/voices
|
COPY assets/voices /usr/share/nginx/html/assets/voices
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" shape-rendering="crispEdges"><rect x="2" y="3" width="1" height="1" fill="#6b4f12"/><rect x="3" y="3" width="1" height="1" fill="#6b4f12"/><rect x="4" y="3" width="1" height="1" fill="#6b4f12"/><rect x="5" y="3" width="1" height="1" fill="#6b4f12"/><rect x="1" y="4" width="1" height="1" fill="#6b4f12"/><rect x="2" y="4" width="1" height="1" fill="#d9b54a"/><rect x="3" y="4" width="1" height="1" fill="#fff0a8"/><rect x="4" y="4" width="1" height="1" fill="#d9b54a"/><rect x="5" y="4" width="1" height="1" fill="#d9b54a"/><rect x="6" y="4" width="1" height="1" fill="#6b4f12"/><rect x="0" y="5" width="1" height="1" fill="#6b4f12"/><rect x="1" y="5" width="1" height="1" fill="#d9b54a"/><rect x="2" y="5" width="1" height="1" fill="#d9b54a"/><rect x="3" y="5" width="1" height="1" fill="#6b4f12"/><rect x="4" y="5" width="1" height="1" fill="#6b4f12"/><rect x="5" y="5" width="1" height="1" fill="#d9b54a"/><rect x="6" y="5" width="1" height="1" fill="#6b4f12"/><rect x="0" y="6" width="1" height="1" fill="#6b4f12"/><rect x="1" y="6" width="1" height="1" fill="#d9b54a"/><rect x="2" y="6" width="1" height="1" fill="#6b4f12"/><rect x="5" y="6" width="1" height="1" fill="#6b4f12"/><rect x="6" y="6" width="1" height="1" fill="#d9b54a"/><rect x="7" y="6" width="1" height="1" fill="#6b4f12"/><rect x="8" y="6" width="1" height="1" fill="#6b4f12"/><rect x="9" y="6" width="1" height="1" fill="#6b4f12"/><rect x="10" y="6" width="1" height="1" fill="#6b4f12"/><rect x="11" y="6" width="1" height="1" fill="#6b4f12"/><rect x="12" y="6" width="1" height="1" fill="#6b4f12"/><rect x="13" y="6" width="1" height="1" fill="#6b4f12"/><rect x="14" y="6" width="1" height="1" fill="#6b4f12"/><rect x="0" y="7" width="1" height="1" fill="#6b4f12"/><rect x="1" y="7" width="1" height="1" fill="#d9b54a"/><rect x="2" y="7" width="1" height="1" fill="#6b4f12"/><rect x="5" y="7" width="1" height="1" fill="#6b4f12"/><rect x="6" y="7" width="1" height="1" fill="#d9b54a"/><rect x="7" y="7" width="1" height="1" fill="#d9b54a"/><rect x="8" y="7" width="1" height="1" fill="#d9b54a"/><rect x="9" y="7" width="1" height="1" fill="#d9b54a"/><rect x="10" y="7" width="1" height="1" fill="#d9b54a"/><rect x="11" y="7" width="1" height="1" fill="#d9b54a"/><rect x="12" y="7" width="1" height="1" fill="#d9b54a"/><rect x="13" y="7" width="1" height="1" fill="#d9b54a"/><rect x="14" y="7" width="1" height="1" fill="#6b4f12"/><rect x="0" y="8" width="1" height="1" fill="#6b4f12"/><rect x="1" y="8" width="1" height="1" fill="#d9b54a"/><rect x="2" y="8" width="1" height="1" fill="#d9b54a"/><rect x="3" y="8" width="1" height="1" fill="#6b4f12"/><rect x="4" y="8" width="1" height="1" fill="#6b4f12"/><rect x="5" y="8" width="1" height="1" fill="#d9b54a"/><rect x="6" y="8" width="1" height="1" fill="#6b4f12"/><rect x="7" y="8" width="1" height="1" fill="#6b4f12"/><rect x="8" y="8" width="1" height="1" fill="#6b4f12"/><rect x="9" y="8" width="1" height="1" fill="#6b4f12"/><rect x="10" y="8" width="1" height="1" fill="#d9b54a"/><rect x="11" y="8" width="1" height="1" fill="#d9b54a"/><rect x="12" y="8" width="1" height="1" fill="#6b4f12"/><rect x="13" y="8" width="1" height="1" fill="#d9b54a"/><rect x="14" y="8" width="1" height="1" fill="#6b4f12"/><rect x="1" y="9" width="1" height="1" fill="#6b4f12"/><rect x="2" y="9" width="1" height="1" fill="#d9b54a"/><rect x="3" y="9" width="1" height="1" fill="#d9b54a"/><rect x="4" y="9" width="1" height="1" fill="#d9b54a"/><rect x="5" y="9" width="1" height="1" fill="#d9b54a"/><rect x="6" y="9" width="1" height="1" fill="#6b4f12"/><rect x="10" y="9" width="1" height="1" fill="#6b4f12"/><rect x="11" y="9" width="1" height="1" fill="#d9b54a"/><rect x="12" y="9" width="1" height="1" fill="#6b4f12"/><rect x="13" y="9" width="1" height="1" fill="#6b4f12"/><rect x="14" y="9" width="1" height="1" fill="#d9b54a"/><rect x="2" y="10" width="1" height="1" fill="#6b4f12"/><rect x="3" y="10" width="1" height="1" fill="#6b4f12"/><rect x="4" y="10" width="1" height="1" fill="#6b4f12"/><rect x="5" y="10" width="1" height="1" fill="#6b4f12"/><rect x="10" y="10" width="1" height="1" fill="#6b4f12"/><rect x="11" y="10" width="1" height="1" fill="#6b4f12"/><rect x="13" y="10" width="1" height="1" fill="#6b4f12"/><rect x="14" y="10" width="1" height="1" fill="#6b4f12"/></svg>
|
||||||
|
After Width: | Height: | Size: 4.3 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.4 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 4.9 KiB |
+12
-3
@@ -177,12 +177,21 @@ function updateInventory() {
|
|||||||
inventoryKey = key;
|
inventoryKey = key;
|
||||||
const box = $('inventory');
|
const box = $('inventory');
|
||||||
box.replaceChildren(...game.state.inventory.map(id => {
|
box.replaceChildren(...game.state.inventory.map(id => {
|
||||||
const b = document.createElement('button'), item = story.items[id], dot = document.createElement('i');
|
const b = document.createElement('button'), item = story.items[id];
|
||||||
b.type = 'button';
|
b.type = 'button';
|
||||||
b.dataset.item = id;
|
b.dataset.item = id;
|
||||||
b.setAttribute('aria-pressed', String(command.item === id));
|
b.setAttribute('aria-pressed', String(command.item === id));
|
||||||
dot.style.background = item.icon?.fill ?? '#ccc';
|
// L'icona a pixel dell'oggetto (assets/icons); senza, un pallino del suo colore.
|
||||||
b.append(dot, item.name);
|
let icon;
|
||||||
|
if (item.icon?.src) {
|
||||||
|
icon = document.createElement('img');
|
||||||
|
icon.src = item.icon.src;
|
||||||
|
icon.alt = '';
|
||||||
|
} else {
|
||||||
|
icon = document.createElement('i');
|
||||||
|
icon.style.background = item.icon?.fill ?? '#ccc';
|
||||||
|
}
|
||||||
|
b.append(icon, item.name);
|
||||||
let timer = null, long = false;
|
let timer = null, long = false;
|
||||||
b.addEventListener('pointerdown', () => { long = false; timer = setTimeout(() => { long = true; command.clickItem(id, { look: true }); }, LONG_PRESS); });
|
b.addEventListener('pointerdown', () => { long = false; timer = setTimeout(() => { long = true; command.clickItem(id, { look: true }); }, LONG_PRESS); });
|
||||||
b.addEventListener('pointerup', () => clearTimeout(timer));
|
b.addEventListener('pointerup', () => clearTimeout(timer));
|
||||||
|
|||||||
+3
-3
@@ -38,7 +38,7 @@ export const story = {
|
|||||||
items: {
|
items: {
|
||||||
squama: {
|
squama: {
|
||||||
name: 'squama',
|
name: 'squama',
|
||||||
icon: { fill: '#4fae5e', shape: 'scale' },
|
icon: { src: 'assets/icons/squama.svg', fill: '#4fae5e' },
|
||||||
actions: {
|
actions: {
|
||||||
look: [{ say: 'Una squama verde, grande come una moneta da due euro. Puzza di cantina.' }],
|
look: [{ say: 'Una squama verde, grande come una moneta da due euro. Puzza di cantina.' }],
|
||||||
use: [{ say: 'Potrei usarla come plettro. Ma prima scopro di chi è.' }],
|
use: [{ say: 'Potrei usarla come plettro. Ma prima scopro di chi è.' }],
|
||||||
@@ -47,7 +47,7 @@ export const story = {
|
|||||||
// Lo scherzo del libro (idea di Andrea, 2026-10-23): «La storia infinita» ha una pagina sola.
|
// Lo scherzo del libro (idea di Andrea, 2026-10-23): «La storia infinita» ha una pagina sola.
|
||||||
libro: {
|
libro: {
|
||||||
name: 'libro',
|
name: 'libro',
|
||||||
icon: { fill: '#c46a3a', shape: 'book' },
|
icon: { src: 'assets/icons/libro.svg', fill: '#c46a3a' },
|
||||||
droppable: true, // non serve alla storia: si può buttare
|
droppable: true, // non serve alla storia: si può buttare
|
||||||
actions: {
|
actions: {
|
||||||
drop: [{ say: 'Una pagina sola, e pure con la fine. Lo lascio qui per il prossimo lettore.' }, { drop: 'libro' }],
|
drop: [{ say: 'Una pagina sola, e pure con la fine. Lo lascio qui per il prossimo lettore.' }, { drop: 'libro' }],
|
||||||
@@ -63,7 +63,7 @@ export const story = {
|
|||||||
// La chiave dell'oratorio: la dà San Pietro a chi risolve il suo indovinello. Indispensabile: non si butta.
|
// La chiave dell'oratorio: la dà San Pietro a chi risolve il suo indovinello. Indispensabile: non si butta.
|
||||||
chiave_oratorio: {
|
chiave_oratorio: {
|
||||||
name: 'chiave dell\'oratorio',
|
name: 'chiave dell\'oratorio',
|
||||||
icon: { fill: '#d9b54a', shape: 'key' },
|
icon: { src: 'assets/icons/chiave.svg', fill: '#d9b54a' },
|
||||||
actions: {
|
actions: {
|
||||||
look: [{ say: 'Una chiave grossa e antica. Quella dell\'oratorio, parola di San Pietro.' }],
|
look: [{ say: 'Una chiave grossa e antica. Quella dell\'oratorio, parola di San Pietro.' }],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
#inventory button { display: flex; align-items: center; gap: .35em; justify-content: center; color: var(--ink); }
|
#inventory button { display: flex; align-items: center; gap: .35em; justify-content: center; color: var(--ink); }
|
||||||
#inventory button[aria-pressed="true"] { border-color: var(--accent); }
|
#inventory button[aria-pressed="true"] { border-color: var(--accent); }
|
||||||
#inventory i { width: .8em; height: .8em; border-radius: 50% 50% 50% 0; flex: none; }
|
#inventory i { width: .8em; height: .8em; border-radius: 50% 50% 50% 0; flex: none; }
|
||||||
|
#inventory img { width: 1.9em; height: 1.9em; flex: none; image-rendering: pixelated; }
|
||||||
|
|
||||||
#choices { margin: 0; padding: 10px 14px 12px 2.4em; background: var(--panel); min-height: 9.5em; }
|
#choices { margin: 0; padding: 10px 14px 12px 2.4em; background: var(--panel); min-height: 9.5em; }
|
||||||
#choices li { padding: .25em 0; font-size: clamp(15px, 2vw, 22px); font-weight: bold; color: var(--dim); cursor: pointer; }
|
#choices li { padding: .25em 0; font-size: clamp(15px, 2vw, 22px); font-weight: bold; color: var(--dim); cursor: pointer; }
|
||||||
|
|||||||
@@ -212,3 +212,11 @@ test('si buttano solo gli oggetti che non servono', () => {
|
|||||||
for (const [id, item] of Object.entries(story.items))
|
for (const [id, item] of Object.entries(story.items))
|
||||||
if (id !== 'libro') assert.ok(!item.droppable, `${id} serve alla storia: non deve potersi buttare`);
|
if (id !== 'libro') assert.ok(!item.droppable, `${id} serve alla storia: non deve potersi buttare`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ogni oggetto ha la sua icona a pixel', () => {
|
||||||
|
for (const [id, item] of Object.entries(story.items)) {
|
||||||
|
assert.ok(item.icon?.src, `${id}: manca l'icona`);
|
||||||
|
const svg = readFileSync(new URL('../' + item.icon.src, import.meta.url), 'utf8');
|
||||||
|
assert.match(svg, /viewBox="0 0 16 16"/, `${id}: l'icona deve essere 16x16`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user