Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53da1e48f8 | ||
|
|
019c3110f9 | ||
|
|
17a4a01f6d | ||
|
|
fab64bb718 | ||
|
|
877b29a6e3 | ||
|
|
acc437a33c |
@@ -143,6 +143,9 @@ deploy: ## Pubblica l'ultimo commit: test, immagine costruita e provata qui, spe
|
|||||||
scp -q $(DEPLOY_TMP)/docker-compose.homeserver.yml $(DEPLOY_HOST):$(DEPLOY_DIR)/docker-compose.yml
|
scp -q $(DEPLOY_TMP)/docker-compose.homeserver.yml $(DEPLOY_HOST):$(DEPLOY_DIR)/docker-compose.yml
|
||||||
docker save $(IMAGE):latest | gzip | ssh $(DEPLOY_HOST) 'gunzip | docker load -q && cd $(DEPLOY_DIR) && docker compose up -d && docker image prune -f >/dev/null'
|
docker save $(IMAGE):latest | gzip | ssh $(DEPLOY_HOST) 'gunzip | docker load -q && cd $(DEPLOY_DIR) && docker compose up -d && docker image prune -f >/dev/null'
|
||||||
rm -rf $(DEPLOY_TMP)
|
rm -rf $(DEPLOY_TMP)
|
||||||
|
@# Sul server il prune toglie l'immagine vecchia; qui restano solo latest e quella appena pubblicata.
|
||||||
|
@docker image ls $(IMAGE) --format '{{.Tag}}' | grep -v -x -e latest -e $$(git rev-parse --short HEAD) | \
|
||||||
|
xargs -r -I{} docker image rm -f $(IMAGE):{} >/dev/null
|
||||||
@echo "→ $(DEPLOY_URL) ($$(git log -1 --format='%h %s'))"
|
@echo "→ $(DEPLOY_URL) ($$(git log -1 --format='%h %s'))"
|
||||||
|
|
||||||
deploy-logs: ## Log del container sul server di deploy
|
deploy-logs: ## Log del container sul server di deploy
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"image": "arcu.png",
|
||||||
|
"height": 120,
|
||||||
|
"frames": {
|
||||||
|
"stand": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 42,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.9,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"blink": {
|
||||||
|
"x": 44,
|
||||||
|
"y": 0,
|
||||||
|
"w": 42,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.3,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"talk": {
|
||||||
|
"x": 88,
|
||||||
|
"y": 0,
|
||||||
|
"w": 42,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.9,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"explain": {
|
||||||
|
"x": 132,
|
||||||
|
"y": 0,
|
||||||
|
"w": 66,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 24.3,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"laugh": {
|
||||||
|
"x": 200,
|
||||||
|
"y": 0,
|
||||||
|
"w": 46,
|
||||||
|
"h": 121,
|
||||||
|
"ax": 17.8,
|
||||||
|
"ay": 121
|
||||||
|
},
|
||||||
|
"point": {
|
||||||
|
"x": 248,
|
||||||
|
"y": 0,
|
||||||
|
"w": 65,
|
||||||
|
"h": 121,
|
||||||
|
"ax": 24.9,
|
||||||
|
"ay": 121
|
||||||
|
},
|
||||||
|
"shrug": {
|
||||||
|
"x": 315,
|
||||||
|
"y": 0,
|
||||||
|
"w": 78,
|
||||||
|
"h": 121,
|
||||||
|
"ax": 36.9,
|
||||||
|
"ay": 121
|
||||||
|
},
|
||||||
|
"arms_crossed": {
|
||||||
|
"x": 395,
|
||||||
|
"y": 0,
|
||||||
|
"w": 43,
|
||||||
|
"h": 121,
|
||||||
|
"ax": 19.4,
|
||||||
|
"ay": 121
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"image": "barondeduke.png",
|
||||||
|
"height": 120,
|
||||||
|
"frames": {
|
||||||
|
"stand": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 47,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 21.7,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"blink": {
|
||||||
|
"x": 49,
|
||||||
|
"y": 0,
|
||||||
|
"w": 47,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 21.5,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"talk": {
|
||||||
|
"x": 98,
|
||||||
|
"y": 0,
|
||||||
|
"w": 48,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 21.8,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"explain": {
|
||||||
|
"x": 148,
|
||||||
|
"y": 0,
|
||||||
|
"w": 61,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 23.9,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"laugh": {
|
||||||
|
"x": 211,
|
||||||
|
"y": 0,
|
||||||
|
"w": 53,
|
||||||
|
"h": 117,
|
||||||
|
"ax": 26.6,
|
||||||
|
"ay": 117
|
||||||
|
},
|
||||||
|
"cards": {
|
||||||
|
"x": 266,
|
||||||
|
"y": 0,
|
||||||
|
"w": 56,
|
||||||
|
"h": 118,
|
||||||
|
"ax": 24.1,
|
||||||
|
"ay": 118
|
||||||
|
},
|
||||||
|
"shrug": {
|
||||||
|
"x": 324,
|
||||||
|
"y": 0,
|
||||||
|
"w": 73,
|
||||||
|
"h": 117,
|
||||||
|
"ax": 35.7,
|
||||||
|
"ay": 117
|
||||||
|
},
|
||||||
|
"facepalm": {
|
||||||
|
"x": 399,
|
||||||
|
"y": 0,
|
||||||
|
"w": 53,
|
||||||
|
"h": 117,
|
||||||
|
"ax": 27.3,
|
||||||
|
"ay": 117
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"image": "tozzino.png",
|
||||||
|
"height": 120,
|
||||||
|
"frames": {
|
||||||
|
"stand": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 40,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.6,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"blink": {
|
||||||
|
"x": 42,
|
||||||
|
"y": 0,
|
||||||
|
"w": 41,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.5,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"talk": {
|
||||||
|
"x": 85,
|
||||||
|
"y": 0,
|
||||||
|
"w": 41,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.6,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"explain": {
|
||||||
|
"x": 128,
|
||||||
|
"y": 0,
|
||||||
|
"w": 65,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 24.4,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"laugh": {
|
||||||
|
"x": 195,
|
||||||
|
"y": 0,
|
||||||
|
"w": 40,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 20.1,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"x": 237,
|
||||||
|
"y": 0,
|
||||||
|
"w": 51,
|
||||||
|
"h": 119,
|
||||||
|
"ax": 25.5,
|
||||||
|
"ay": 119
|
||||||
|
},
|
||||||
|
"look_far": {
|
||||||
|
"x": 290,
|
||||||
|
"y": 0,
|
||||||
|
"w": 56,
|
||||||
|
"h": 120,
|
||||||
|
"ax": 27.9,
|
||||||
|
"ay": 120
|
||||||
|
},
|
||||||
|
"bounce": {
|
||||||
|
"x": 348,
|
||||||
|
"y": 0,
|
||||||
|
"w": 67,
|
||||||
|
"h": 117,
|
||||||
|
"ax": 21.1,
|
||||||
|
"ay": 117
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -623,6 +623,38 @@
|
|||||||
"file": "andrea-e47b3cebb5.mp3",
|
"file": "andrea-e47b3cebb5.mp3",
|
||||||
"sec": 4.87
|
"sec": 4.87
|
||||||
},
|
},
|
||||||
|
"andrea|Il BaronDeDuke, col cappello da cowboy. Ha l'aria di uno che aspetta qualcuno, e che spera non lo veda nessuno.": {
|
||||||
|
"file": "andrea-0bd1b0f32e.mp3",
|
||||||
|
"sec": 8.7
|
||||||
|
},
|
||||||
|
"andrea|Baron! Che ci fai qui?": {
|
||||||
|
"file": "andrea-1b59141c98.mp3",
|
||||||
|
"sec": 2.59
|
||||||
|
},
|
||||||
|
"barondeduke|Aspetto uno che mi deve riportare le mutande.": {
|
||||||
|
"file": "barondeduke-3ea60b7083.mp3",
|
||||||
|
"sec": 4.12
|
||||||
|
},
|
||||||
|
"andrea|Le... mutande?": {
|
||||||
|
"file": "andrea-f83ef038f8.mp3",
|
||||||
|
"sec": 3.94
|
||||||
|
},
|
||||||
|
"barondeduke|Le ho perse a poker, ieri sera.": {
|
||||||
|
"file": "barondeduke-5542a06624.mp3",
|
||||||
|
"sec": 1.65
|
||||||
|
},
|
||||||
|
"barondeduke|In mano avevo full. E ho detto: «Male male si divide».": {
|
||||||
|
"file": "barondeduke-944c3e57dc.mp3",
|
||||||
|
"sec": 5.03
|
||||||
|
},
|
||||||
|
"andrea|E invece?": {
|
||||||
|
"file": "andrea-435306c242.mp3",
|
||||||
|
"sec": 0.67
|
||||||
|
},
|
||||||
|
"barondeduke|L'altro aveva colore.": {
|
||||||
|
"file": "barondeduke-238f525535.mp3",
|
||||||
|
"sec": 1.65
|
||||||
|
},
|
||||||
"andrea|La tribuna bianca e rossa. La domenica qui c'è più tifo che al Palio. Quasi.": {
|
"andrea|La tribuna bianca e rossa. La domenica qui c'è più tifo che al Palio. Quasi.": {
|
||||||
"file": "andrea-a50071085e.mp3",
|
"file": "andrea-a50071085e.mp3",
|
||||||
"sec": 6.84
|
"sec": 6.84
|
||||||
@@ -767,6 +799,18 @@
|
|||||||
"file": "andrea-bb70dea2a6.mp3",
|
"file": "andrea-bb70dea2a6.mp3",
|
||||||
"sec": 2.15
|
"sec": 2.15
|
||||||
},
|
},
|
||||||
|
"andrea|L'Arcu, il mio amico di sempre. Davanti al circolino, come se ci fosse nato.": {
|
||||||
|
"file": "andrea-8ddab2d024.mp3",
|
||||||
|
"sec": 5.79
|
||||||
|
},
|
||||||
|
"andrea|Arcu! Ma che è sempre là, Borgo?": {
|
||||||
|
"file": "andrea-aaeb40d873.mp3",
|
||||||
|
"sec": 3.42
|
||||||
|
},
|
||||||
|
"arcu|E chi lo sposta???": {
|
||||||
|
"file": "arcu-64735a5925.mp3",
|
||||||
|
"sec": 0.97
|
||||||
|
},
|
||||||
"andrea|Il ponte vecchio, coi suoi due archi. Chissà quante piene ha visto passare: io al primo temporale cerco riparo.": {
|
"andrea|Il ponte vecchio, coi suoi due archi. Chissà quante piene ha visto passare: io al primo temporale cerco riparo.": {
|
||||||
"file": "andrea-01ec1d03ec.mp3",
|
"file": "andrea-01ec1d03ec.mp3",
|
||||||
"sec": 7.67
|
"sec": 7.67
|
||||||
@@ -935,6 +979,30 @@
|
|||||||
"file": "andrea-f5d55187e8.mp3",
|
"file": "andrea-f5d55187e8.mp3",
|
||||||
"sec": 5.11
|
"sec": 5.11
|
||||||
},
|
},
|
||||||
|
"andrea|Il Tozzino, vestito di bianco da capo a piedi, con la racchetta. Guarda l'orologio ogni dieci secondi.": {
|
||||||
|
"file": "andrea-3c32888a15.mp3",
|
||||||
|
"sec": 8.1
|
||||||
|
},
|
||||||
|
"andrea|Tozzino! Che fai lì davanti al cancello?": {
|
||||||
|
"file": "andrea-1fe1ee6236.mp3",
|
||||||
|
"sec": 3.1
|
||||||
|
},
|
||||||
|
"tozzino|Aspetto Federer. Oggi si fa una partita.": {
|
||||||
|
"file": "tozzino-a069d2c5e2.mp3",
|
||||||
|
"sec": 2.85
|
||||||
|
},
|
||||||
|
"andrea|Federer? Roger Federer?": {
|
||||||
|
"file": "andrea-70f150bdec.mp3",
|
||||||
|
"sec": 2.67
|
||||||
|
},
|
||||||
|
"tozzino|E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.": {
|
||||||
|
"file": "tozzino-5072201408.mp3",
|
||||||
|
"sec": 4.3
|
||||||
|
},
|
||||||
|
"tozzino|Se non arriva, la vinco a tavolino.": {
|
||||||
|
"file": "tozzino-c1736e2d62.mp3",
|
||||||
|
"sec": 1.42
|
||||||
|
},
|
||||||
"andrea|La Carza. A maggio c'è poca acqua: d'estate si scendeva a fare le dighe coi sassi.": {
|
"andrea|La Carza. A maggio c'è poca acqua: d'estate si scendeva a fare le dighe coi sassi.": {
|
||||||
"file": "andrea-91be1de49b.mp3",
|
"file": "andrea-91be1de49b.mp3",
|
||||||
"sec": 6.99
|
"sec": 6.99
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -35,6 +35,7 @@
|
|||||||
<input id="load-file" type="file" accept=".json,application/json" hidden>
|
<input id="load-file" type="file" accept=".json,application/json" hidden>
|
||||||
<p id="load-error" class="load-error" hidden role="alert"></p>
|
<p id="load-error" class="load-error" hidden role="alert"></p>
|
||||||
<p class="dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
<p class="dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
||||||
|
<p class="version"></p>
|
||||||
</section>
|
</section>
|
||||||
<section id="rione" class="overlay" hidden aria-label="Scegli il rione">
|
<section id="rione" class="overlay" hidden aria-label="Scegli il rione">
|
||||||
<h2>Per chi corri quest'anno?</h2>
|
<h2>Per chi corri quest'anno?</h2>
|
||||||
@@ -79,6 +80,7 @@
|
|||||||
<button id="to-title" class="secondary">Torna al titolo</button>
|
<button id="to-title" class="secondary">Torna al titolo</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="hint">La partita è salvata: dal titolo si riprende con «Continua». Con «Salva su file» la porti su un altro dispositivo e la apri con «Carica».</p>
|
<p class="hint">La partita è salvata: dal titolo si riprende con «Continua». Con «Salva su file» la porti su un altro dispositivo e la apri con «Carica».</p>
|
||||||
|
<p class="version"></p>
|
||||||
</section>
|
</section>
|
||||||
<section id="credits" class="overlay" hidden aria-label="Ringraziamenti">
|
<section id="credits" class="overlay" hidden aria-label="Ringraziamenti">
|
||||||
<h2>Ringraziamenti</h2>
|
<h2>Ringraziamenti</h2>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "leggenda-del-regolo",
|
"name": "leggenda-del-regolo",
|
||||||
"version": "0.1.0",
|
"version": "0.1.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+5
-4
@@ -6,7 +6,7 @@ import { render, loadAssets, hasBackground, WIDTH, HEIGHT } from './engine/rende
|
|||||||
import { readSave, writeSave, clearSave, readAudio, writeAudio, saveFile, saveFileName, readSaveFile } from './engine/storage.js';
|
import { readSave, writeSave, clearSave, readAudio, writeAudio, saveFile, saveFileName, readSaveFile } from './engine/storage.js';
|
||||||
import { Music, trackFor } from './engine/music.js';
|
import { Music, trackFor } from './engine/music.js';
|
||||||
import { Voices } from './engine/voices.js';
|
import { Voices } from './engine/voices.js';
|
||||||
import { versioned } from './version.js';
|
import { VERSION, versioned } from './version.js';
|
||||||
|
|
||||||
const $ = id => document.getElementById(id);
|
const $ = id => document.getElementById(id);
|
||||||
const canvas = $('scene'), ctx = canvas.getContext('2d');
|
const canvas = $('scene'), ctx = canvas.getContext('2d');
|
||||||
@@ -582,12 +582,12 @@ $('restart').addEventListener('click', () => {
|
|||||||
|
|
||||||
// Dietro il titolo si vede già la piazza.
|
// Dietro il titolo si vede già la piazza.
|
||||||
// --- Cartello d'apertura «Manzolo (Poca) Art Presents»: 5 secondi (un clic o un tasto lo salta), poi il titolo.
|
// --- Cartello d'apertura «Manzolo (Poca) Art Presents»: 5 secondi (un clic o un tasto lo salta), poi il titolo.
|
||||||
// Il titolo compare sotto il cartello quando questo comincia a sfumare (style.css, 4,3 s): dissolvenza incrociata,
|
// Il titolo compare sotto il cartello quando questo comincia a sfumare (#splash.out in style.css): dissolvenza
|
||||||
// senza intravedere la piazza nel mezzo.
|
// incrociata, senza intravedere la piazza nel mezzo. I tempi partono da qui, non dal primo disegno della pagina.
|
||||||
const SPLASH_FADE = 4300, SPLASH_END = 5000;
|
const SPLASH_FADE = 4300, SPLASH_END = 5000;
|
||||||
function showSplash() {
|
function showSplash() {
|
||||||
let done = false, revealed = false;
|
let done = false, revealed = false;
|
||||||
const reveal = () => { if (!revealed) { revealed = true; showTitle(); } };
|
const reveal = () => { if (!revealed) { revealed = true; showTitle(); $('splash').classList.add('out'); } };
|
||||||
const end = () => {
|
const end = () => {
|
||||||
if (done) return;
|
if (done) return;
|
||||||
done = true;
|
done = true;
|
||||||
@@ -608,6 +608,7 @@ function showSplash() {
|
|||||||
addEventListener('keydown', end, { once: true });
|
addEventListener('keydown', end, { once: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const el of document.querySelectorAll('.version')) el.textContent = `v${VERSION}`;
|
||||||
game = new Game(story);
|
game = new Game(story);
|
||||||
command = new Command(game);
|
command = new Command(game);
|
||||||
showSplash();
|
showSplash();
|
||||||
|
|||||||
@@ -112,6 +112,9 @@ export const story = {
|
|||||||
leone: { name: 'Il leone', color: '#f0a070' },
|
leone: { name: 'Il leone', color: '#f0a070' },
|
||||||
san_pietro: { name: 'San Pietro', color: '#e8e0c8' },
|
san_pietro: { name: 'San Pietro', color: '#e8e0c8' },
|
||||||
tosca: { name: 'La Tosca', color: '#ffb0d0' },
|
tosca: { name: 'La Tosca', color: '#ffb0d0' },
|
||||||
|
arcu: { name: 'L\'Arcu', color: '#7fb2ff', sprite: 'assets/characters/arcu.json' },
|
||||||
|
tozzino: { name: 'Il Tozzino', color: '#c8f5b0', sprite: 'assets/characters/tozzino.json' },
|
||||||
|
barondeduke: { name: 'Il BaronDeDuke', color: '#e0c090', sprite: 'assets/characters/barondeduke.json' },
|
||||||
},
|
},
|
||||||
items: {
|
items: {
|
||||||
squama: {
|
squama: {
|
||||||
@@ -974,6 +977,9 @@ export const story = {
|
|||||||
walk: [[0, 360], [0, 330], [300, 262], [430, 222], [600, 210], [640, 212], [640, 360]],
|
walk: [[0, 360], [0, 330], [300, 262], [430, 222], [600, 210], [640, 212], [640, 360]],
|
||||||
depth: [[210, 0.4], [360, 1.15]],
|
depth: [[210, 0.4], [360, 1.15]],
|
||||||
entry: [100, 340],
|
entry: [100, 340],
|
||||||
|
// Il BaronDeDuke nella discesa verso la polisportiva: aspetta chi gli riporta le mutande perse a poker.
|
||||||
|
speakers: { barondeduke: [230, 243] },
|
||||||
|
people: [{ who: 'barondeduke', at: [230, 300], facing: -1, idle: 'stand', talk: ['talk', 'explain'], blink: 'blink', every: 4.6 }],
|
||||||
hotspots: [
|
hotspots: [
|
||||||
{
|
{
|
||||||
id: 'campo', name: 'campo secondario', box: [140, 160, 240, 60], at: [330, 254], face: 'up',
|
id: 'campo', name: 'campo secondario', box: [140, 160, 240, 60], at: [330, 254], face: 'up',
|
||||||
@@ -1007,6 +1013,21 @@ export const story = {
|
|||||||
{
|
{
|
||||||
id: 'al_principale', name: 'indietro, verso il campo principale', box: [0, 330, 640, 30], at: [100, 354], exit: { scene: 'polisportiva_principale', at: [620, 330], face: 'left' },
|
id: 'al_principale', name: 'indietro, verso il campo principale', box: [0, 330, 640, 30], at: [100, 354], exit: { scene: 'polisportiva_principale', at: [620, 330], face: 'left' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'barondeduke', name: 'il BaronDeDuke', box: [212, 245, 36, 55], at: [190, 316], face: 'right', default: 'talk',
|
||||||
|
actions: {
|
||||||
|
look: [{ say: 'Il BaronDeDuke, col cappello da cowboy. Ha l\'aria di uno che aspetta qualcuno, e che spera non lo veda nessuno.' }],
|
||||||
|
talk: [
|
||||||
|
{ say: 'Baron! Che ci fai qui?' },
|
||||||
|
{ say: 'Aspetto uno che mi deve riportare le mutande.', who: 'barondeduke' },
|
||||||
|
{ say: 'Le... mutande?' },
|
||||||
|
{ say: 'Le ho perse a poker, ieri sera.', who: 'barondeduke', pose: 'facepalm' },
|
||||||
|
{ say: 'In mano avevo full. E ho detto: «Male male si divide».', who: 'barondeduke', pose: 'cards' },
|
||||||
|
{ say: 'E invece?' },
|
||||||
|
{ say: 'L\'altro aveva colore.', who: 'barondeduke', pose: 'shrug' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
polisportiva_principale: {
|
polisportiva_principale: {
|
||||||
@@ -1248,6 +1269,9 @@ export const story = {
|
|||||||
walk: [[0, 360], [0, 335], [60, 300], [400, 280], [640, 250], [640, 360]],
|
walk: [[0, 360], [0, 335], [60, 300], [400, 280], [640, 250], [640, 360]],
|
||||||
depth: [[250, 1.0], [360, 1.5]],
|
depth: [[250, 1.0], [360, 1.5]],
|
||||||
entry: [320, 330],
|
entry: [320, 330],
|
||||||
|
// L'Arcu davanti al circolino, accanto alla fontanella (sprite di Codex, 25 ottobre).
|
||||||
|
speakers: { arcu: [418, 214] },
|
||||||
|
people: [{ who: 'arcu', at: [418, 292], facing: -1, idle: 'stand', talk: ['talk', 'explain'], blink: 'blink', every: 4.2 }],
|
||||||
hotspots: [
|
hotspots: [
|
||||||
{
|
{
|
||||||
id: 'circolo', name: 'il circolino', box: [100, 0, 380, 205], at: [300, 290], face: 'up',
|
id: 'circolo', name: 'il circolino', box: [100, 0, 380, 205], at: [300, 290], face: 'up',
|
||||||
@@ -1293,6 +1317,13 @@ export const story = {
|
|||||||
look: [{ say: 'La strada va avanti verso Tagliaferro.' }],
|
look: [{ say: 'La strada va avanti verso Tagliaferro.' }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'arcu', name: 'l\'Arcu', box: [400, 216, 38, 76], at: [362, 300], face: 'right', default: 'talk',
|
||||||
|
actions: {
|
||||||
|
look: [{ say: 'L\'Arcu, il mio amico di sempre. Davanti al circolino, come se ci fosse nato.' }],
|
||||||
|
talk: [{ say: 'Arcu! Ma che è sempre là, Borgo?' }, { say: 'E chi lo sposta???', who: 'arcu', pose: 'shrug' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
campomigliaio_ponte: {
|
campomigliaio_ponte: {
|
||||||
@@ -1557,6 +1588,9 @@ export const story = {
|
|||||||
walk: [[60, 360], [250, 262], [300, 218], [350, 218], [420, 262], [600, 360]],
|
walk: [[60, 360], [250, 262], [300, 218], [350, 218], [420, 262], [600, 360]],
|
||||||
depth: [[218, 0.55], [360, 1.65]],
|
depth: [[218, 0.55], [360, 1.65]],
|
||||||
entry: [300, 350],
|
entry: [300, 350],
|
||||||
|
// Il Tozzino davanti al cancello del tennis, in tenuta, che aspetta Federer.
|
||||||
|
speakers: { tozzino: [440, 222] },
|
||||||
|
people: [{ who: 'tozzino', at: [440, 300], facing: -1, idle: 'stand', talk: ['talk', 'explain'], blink: 'blink', every: 3.9 }],
|
||||||
hotspots: [
|
hotspots: [
|
||||||
{
|
{
|
||||||
id: 'muro', name: 'casa dell\'ing. Tozzi', box: [0, 120, 200, 140], at: [190, 300], face: 'left',
|
id: 'muro', name: 'casa dell\'ing. Tozzi', box: [0, 120, 200, 140], at: [190, 300], face: 'left',
|
||||||
@@ -1576,6 +1610,19 @@ export const story = {
|
|||||||
{
|
{
|
||||||
id: 'alla_pieve', name: 'su verso la Pieve', box: [0, 330, 640, 30], at: [300, 354], exit: { scene: 'pieve', at: [95, 250], face: 'right' },
|
id: 'alla_pieve', name: 'su verso la Pieve', box: [0, 330, 640, 30], at: [300, 354], exit: { scene: 'pieve', at: [95, 250], face: 'right' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'tozzino', name: 'il Tozzino', box: [422, 224, 36, 76], at: [392, 312], face: 'right', default: 'talk',
|
||||||
|
actions: {
|
||||||
|
look: [{ say: 'Il Tozzino, vestito di bianco da capo a piedi, con la racchetta. Guarda l\'orologio ogni dieci secondi.' }],
|
||||||
|
talk: [
|
||||||
|
{ say: 'Tozzino! Che fai lì davanti al cancello?' },
|
||||||
|
{ say: 'Aspetto Federer. Oggi si fa una partita.', who: 'tozzino', pose: 'explain' },
|
||||||
|
{ say: 'Federer? Roger Federer?' },
|
||||||
|
{ say: 'E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.', who: 'tozzino', pose: 'watch' },
|
||||||
|
{ say: 'Se non arriva, la vinco a tavolino.', who: 'tozzino', pose: 'look_far' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
ponticino: {
|
ponticino: {
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
|
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
|
||||||
export const VERSION = '0.1.0';
|
export const VERSION = '0.1.2';
|
||||||
|
|
||||||
// Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica,
|
// Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica,
|
||||||
// mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf).
|
// mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf).
|
||||||
|
|||||||
@@ -68,12 +68,15 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
.overlay[hidden] { display: none; }
|
.overlay[hidden] { display: none; }
|
||||||
/* Titolo e introduzione: le illustrazioni a pixel netti, con una velatura per leggere il testo. */
|
/* Titolo e introduzione: le illustrazioni a pixel netti, con una velatura per leggere il testo. */
|
||||||
#title { justify-content: flex-start; padding-top: 6%; image-rendering: pixelated;
|
#title { justify-content: flex-start; padding-top: 6%; image-rendering: pixelated;
|
||||||
background: none; }
|
background: #0d0910; } /* fondo pieno: finché l'illustrazione non arriva, sotto non si vede il gioco */
|
||||||
#title .buttons { margin-top: auto; }
|
#title .buttons { margin-top: auto; }
|
||||||
#title .dedication { margin-bottom: 2%; text-shadow: 2px 2px 0 #000; }
|
#title .dedication { margin-bottom: 2%; text-shadow: 2px 2px 0 #000; }
|
||||||
|
/* La versione (src/version.js), piccola: nell'angolo del titolo e in fondo alla pausa. */
|
||||||
|
.version { margin: 0; font-size: 9px; color: var(--dim); opacity: .75; }
|
||||||
|
#title .version { position: absolute; right: 8px; bottom: 6px; text-shadow: 1px 1px 0 #000; }
|
||||||
#title .subtitle { color: var(--ink); text-shadow: 2px 2px 0 #000; }
|
#title .subtitle { color: var(--ink); text-shadow: 2px 2px 0 #000; }
|
||||||
#intro { justify-content: flex-start; padding-top: 7%; cursor: pointer; image-rendering: pixelated;
|
#intro { justify-content: flex-start; padding-top: 7%; cursor: pointer; image-rendering: pixelated;
|
||||||
background: none; }
|
background: #0d0910; } /* fondo pieno: finché l'illustrazione non arriva, sotto non si vede il gioco */
|
||||||
#intro-text { min-height: 4.2em; max-width: 30em; font-size: clamp(11.52px, 1.87vw, 21.6px); font-weight: bold; line-height: 1.3; color: var(--ink);
|
#intro-text { min-height: 4.2em; max-width: 30em; font-size: clamp(11.52px, 1.87vw, 21.6px); font-weight: bold; line-height: 1.3; color: var(--ink);
|
||||||
text-shadow: 2px 0 #000, -2px 0 #000, 0 2px #000, 0 -2px #000; animation: appear .8s ease-out; }
|
text-shadow: 2px 0 #000, -2px 0 #000, 0 2px #000, 0 -2px #000; animation: appear .8s ease-out; }
|
||||||
#intro .hint { margin-top: auto; margin-bottom: 40px; color: var(--dim); font-size: clamp(8.64px, 1.08vw, 11.52px); text-shadow: 1px 1px 0 #000; }
|
#intro .hint { margin-top: auto; margin-bottom: 40px; color: var(--dim); font-size: clamp(8.64px, 1.08vw, 11.52px); text-shadow: 1px 1px 0 #000; }
|
||||||
@@ -110,8 +113,10 @@ body.full #sound { position: fixed; z-index: 13; top: max(8px, env(safe-area-ins
|
|||||||
#title .dedication { font-size: max(9px, calc(var(--u) * 1.5)); }
|
#title .dedication { font-size: max(9px, calc(var(--u) * 1.5)); }
|
||||||
#intro-text { font-size: max(11px, calc(var(--u) * 2)); }
|
#intro-text { font-size: max(11px, calc(var(--u) * 2)); }
|
||||||
#title .buttons button { font-size: max(11px, calc(var(--u) * 1.9)); }
|
#title .buttons button { font-size: max(11px, calc(var(--u) * 1.9)); }
|
||||||
#splash { z-index: 11; gap: .15em; cursor: pointer; background: radial-gradient(circle at 50% 45%, #2a2030, #0d0910 70%);
|
#splash { z-index: 11; gap: .15em; cursor: pointer; background: radial-gradient(circle at 50% 45%, #2a2030, #0d0910 70%); }
|
||||||
animation: splash-out .7s ease-in 4.3s forwards; }
|
/* La dissolvenza la avvia main.js insieme al titolo: il CSS arriva prima del codice, e con un orologio suo il cartello
|
||||||
|
sparirebbe prima che il titolo ci sia. */
|
||||||
|
#splash.out { animation: splash-out .7s ease-in forwards; }
|
||||||
#splash p { margin: 0; max-width: none; font-weight: bold; text-shadow: 3px 3px 0 #000; opacity: 0; }
|
#splash p { margin: 0; max-width: none; font-weight: bold; text-shadow: 3px 3px 0 #000; opacity: 0; }
|
||||||
#splash .splash-name { font-size: clamp(24.48px, 5.76vw, 63.36px); letter-spacing: .14em; text-transform: uppercase; color: var(--ink);
|
#splash .splash-name { font-size: clamp(24.48px, 5.76vw, 63.36px); letter-spacing: .14em; text-transform: uppercase; color: var(--ink);
|
||||||
animation: splash-in .9s ease-out .2s forwards; }
|
animation: splash-in .9s ease-out .2s forwards; }
|
||||||
|
|||||||
@@ -62,6 +62,17 @@ try {
|
|||||||
await page.screenshot({ path: `${OUT}/00b-dissolvenza.png` });
|
await page.screenshot({ path: `${OUT}/00b-dissolvenza.png` });
|
||||||
await page.waitForSelector('#splash', { state: 'hidden', timeout: 3000 });
|
await page.waitForSelector('#splash', { state: 'hidden', timeout: 3000 });
|
||||||
await page.screenshot({ path: `${OUT}/01-titolo.png` });
|
await page.screenshot({ path: `${OUT}/01-titolo.png` });
|
||||||
|
assert.match(await page.textContent('#title .version'), /^v\d+\.\d+\.\d+$/, 'la versione nell\'angolo del titolo');
|
||||||
|
// Col codice lento ad arrivare (rete vera) il cartello aspetta il titolo: non sfuma prima per conto suo.
|
||||||
|
{
|
||||||
|
const slow = await browser.newPage({ viewport: { width: 1280, height: 860 } });
|
||||||
|
await slow.route('**/src/main.js', async route => { await new Promise(r => setTimeout(r, 2000)); await route.continue(); });
|
||||||
|
await slow.goto(`http://127.0.0.1:${PORT}/`);
|
||||||
|
await slow.waitForSelector('#title:not([hidden])', { timeout: 12000 });
|
||||||
|
const opacity = await slow.evaluate(() => Number(getComputedStyle(document.getElementById('splash')).opacity));
|
||||||
|
assert.ok(opacity > 0.9, `il cartello era già sfumato (${opacity}) quando è comparso il titolo`);
|
||||||
|
await slow.close();
|
||||||
|
}
|
||||||
// I crediti dal titolo: si aprono, mostrano i nomi, Esc li chiude.
|
// I crediti dal titolo: si aprono, mostrano i nomi, Esc li chiude.
|
||||||
await page.click('#title .open-credits');
|
await page.click('#title .open-credits');
|
||||||
assert.match(await page.textContent('#credits'), /Ringraziamenti\s*Al Lele/, 'la dedica al Lele viene per prima');
|
assert.match(await page.textContent('#credits'), /Ringraziamenti\s*Al Lele/, 'la dedica al Lele viene per prima');
|
||||||
|
|||||||
@@ -470,3 +470,14 @@ test('i quattro rioni: ognuno ha la sua riga nell\'introduzione, e le battute su
|
|||||||
assert.doesNotMatch(look('pieve', 'piazza', 'colonna'), /noi rossi/);
|
assert.doesNotMatch(look('pieve', 'piazza', 'colonna'), /noi rossi/);
|
||||||
assert.match(look(null, 'pieve', 'chiesa'), /quelli in bianco/, 'un salvataggio di prima dei rioni funziona');
|
assert.match(look(null, 'pieve', 'chiesa'), /quelli in bianco/, 'un salvataggio di prima dei rioni funziona');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('gli amici in giro: l\'Arcu al circolino, il Tozzino al cancello del tennis, il BaronDeDuke alla polisportiva', () => {
|
||||||
|
const g = new Game(story);
|
||||||
|
settle(g);
|
||||||
|
const talk = (scene, who) => { g.go(scene); settle(g); g.act('talk', who); return settle(g).map(s => `${s.who ?? 'andrea'}: ${s.text}`); };
|
||||||
|
assert.deepEqual(talk('campomigliaio_circolo', 'arcu'), ['andrea: Arcu! Ma che è sempre là, Borgo?', 'arcu: E chi lo sposta???']);
|
||||||
|
assert.ok(talk('carza', 'tozzino').includes('tozzino: E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.'));
|
||||||
|
const baron = talk('polisportiva', 'barondeduke');
|
||||||
|
assert.ok(baron.includes('barondeduke: In mano avevo full. E ho detto: «Male male si divide».'));
|
||||||
|
assert.equal(baron.at(-1), 'barondeduke: L\'altro aveva colore.');
|
||||||
|
});
|
||||||
|
|||||||
+4
-1
@@ -6,5 +6,8 @@
|
|||||||
"castello": { "speaker": "Damien Black", "filtro": "asetrate=24000*0.9,aresample=24000,atempo=0.95,aecho=0.8:0.7:90|180:0.25|0.15" },
|
"castello": { "speaker": "Damien Black", "filtro": "asetrate=24000*0.9,aresample=24000,atempo=0.95,aecho=0.8:0.7:90|180:0.25|0.15" },
|
||||||
"leone": { "speaker": "Baldur Sanjin", "filtro": "asetrate=24000*0.84,aresample=24000,atempo=1.08" },
|
"leone": { "speaker": "Baldur Sanjin", "filtro": "asetrate=24000*0.84,aresample=24000,atempo=1.08" },
|
||||||
"san_pietro": { "speaker": "Wulf Carlevaro", "filtro": "asetrate=24000*0.92,aresample=24000,atempo=0.95,aecho=0.8:0.6:60:0.2" },
|
"san_pietro": { "speaker": "Wulf Carlevaro", "filtro": "asetrate=24000*0.92,aresample=24000,atempo=0.95,aecho=0.8:0.6:60:0.2" },
|
||||||
"tosca": { "speaker": "Gitta Nikolina" }
|
"tosca": { "speaker": "Gitta Nikolina" },
|
||||||
|
"arcu": { "speaker": "Luis Moray" },
|
||||||
|
"tozzino": { "speaker": "Dionisio Schuyler" },
|
||||||
|
"barondeduke": { "speaker": "Craig Gutsy" }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user