Al Trebbio parla lo spirito del castello: compare accanto alla torre, semitrasparente, con la lanterna

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
2026-10-24 22:33:24 +02:00
co-authored by Claude Opus 5.5
parent fd8150305e
commit 73a8be39c5
4 changed files with 38 additions and 2 deletions
+24
View File
@@ -160,6 +160,7 @@ export function render(ctx, game, { hover, spots, debug, time = performance.now(
if (sheet) queue.push({ y: p.at[1], draw: () => drawSprite(ctx, sheet, game.personPose(p), ...p.at, game.scaleAt(p.at[1]), p.facing ?? 1, p.size) });
}
for (const q of queue.sort((a, b) => a.y - b.y)) q.draw();
drawApparitions(ctx, game, time);
drawLights(ctx, scene, time);
for (const shape of art) if (shape.top) drawShape(ctx, shape);
if (spots) drawSpots(ctx, game);
@@ -172,6 +173,29 @@ export function render(ctx, game, { hover, spots, debug, time = performance.now(
}
}
// Le apparizioni (`apparitions`): uno spirito che compare solo mentre parla (un dialogo suo, o una sua battuta),
// semitrasparente, che ondeggia piano, con un alone freddo intorno e il caldo della lanterna.
function drawApparitions(ctx, game, time) {
for (const a of game.scene.apparitions ?? []) {
if (game.dialogue?.id !== a.who && game.speech?.who !== a.who) continue;
const img = backgrounds.get(a.src);
if (!img) { loadBackground(a.src); continue; }
const h = a.height, w = Math.round(img.width * h / img.height), bob = Math.round(Math.sin(time / 600) * 2);
const x = Math.round(a.at[0] - w / 2), y = a.at[1] - h + bob;
ctx.save();
const halo = ctx.createRadialGradient(a.at[0], y + h * 0.45, 0, a.at[0], y + h * 0.45, h * 0.7);
halo.addColorStop(0, 'rgba(180, 230, 255, 0.28)');
halo.addColorStop(1, 'rgba(180, 230, 255, 0)');
ctx.globalCompositeOperation = 'lighter';
ctx.fillStyle = halo;
ctx.fillRect(a.at[0] - h, y - h * 0.3, h * 2, h * 1.6);
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 0.82 + 0.08 * Math.sin(time / 380);
ctx.drawImage(img, x, y, w, h);
ctx.restore();
}
}
// Le scene buie (`shade`: il velo scuro sopra tutto, Andrea compreso) e le fiammelle (`lights`: candele accese).
// Ogni fiamma ha due disegni che si alternano a caso, e intorno un alone caldo che pulsa piano.
const FLAME_STEP = 140;
+4 -2
View File
@@ -99,7 +99,7 @@ export const story = {
andrea: { name: 'Andrea', color: '#ffffff', sprite: 'assets/characters/andrea.json' },
vecchietta: { name: 'Vecchietta', color: '#ffd27a', sprite: 'assets/characters/vecchietta.json' },
vecchietto: { name: 'Vecchietto', color: '#9fe3ff', sprite: 'assets/characters/vecchietto.json' },
castello: { name: 'Il Castello', color: '#c8f0a0' },
castello: { name: 'Lo spirito del Trebbio', color: '#c8f0ff' },
leone: { name: 'Il leone', color: '#f0a070' },
san_pietro: { name: 'San Pietro', color: '#e8e0c8' },
tosca: { name: 'La Tosca', color: '#ffb0d0' },
@@ -1736,7 +1736,9 @@ export const story = {
walk: [[86, 308], [300, 306], [356, 308], [470, 312], [500, 324], [486, 360], [88, 360], [80, 330]],
depth: [[306, 0.75], [360, 1.05]],
entry: [110, 345],
speakers: { castello: [389, 22] },
// Lo spirito del castello (disegnato da Codex, idea di Andrea del 24 ottobre): compare quando parla.
speakers: { castello: [446, 178] },
apparitions: [{ who: 'castello', src: 'assets/characters/spirito-trebbio.png', at: [446, 304], height: 120 }],
enter: [{ if: '!trebbio_visto', then: [{ set: 'trebbio_visto' }, { say: 'Il Trebbio. Quassù anche i pensieri vanno più piano.' }] }],
hotspots: [
{