Ombre delle fronde al Bosco ai Frati, bandiere del campeggio al vento, fascio di luce nella Pieve; nel viale semi e foglioline verdi invece delle foglie d'autunno
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
+43
-1
@@ -411,6 +411,48 @@ export const EFFECTS = {
|
||||
lc.globalCompositeOperation = 'source-over';
|
||||
ctx.drawImage(layer, 0, 0);
|
||||
},
|
||||
// Le ombre delle fronde sul terreno: macchie scure e chiare che ondeggiano piano col vento, come sotto un albero.
|
||||
leafshadow(ctx, e, time) {
|
||||
const [ax, ay, aw, ah] = e.area, t = time / 1000;
|
||||
for (let i = 0; i < (e.count ?? 14); i++) {
|
||||
const bx = ax + hash(i * 7) * aw, by = ay + hash(i * 13) * ah, r = 3 + hash(i * 3) * (e.size ?? 6);
|
||||
const x = bx + Math.sin(t * 0.9 + i) * 2 + Math.sin(t * 0.37 + i * 2) * 2, y = by + Math.sin(t * 0.7 + i * 3) * 1;
|
||||
ctx.fillStyle = i % 3 ? 'rgba(30, 20, 45, 0.24)' : 'rgba(255, 235, 170, 0.18)';
|
||||
for (let dy = -r; dy <= r; dy += 1) {
|
||||
const half = Math.round(Math.sqrt(r * r - dy * dy) * 1.6);
|
||||
ctx.fillRect(Math.round(x - half), Math.round(y + dy / 2), half * 2, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
// Una bandiera dipinta nello sfondo che sventola: a strisce verticali che salgono e scendono, ferme dalla parte
|
||||
// dell'asta (`pole`: 'left' o 'right') e sempre più mosse verso il lembo libero.
|
||||
cloth(ctx, e, time, game) {
|
||||
const bg = backgrounds.get(game.scene.background);
|
||||
if (!bg) return;
|
||||
const k = bg.width / WIDTH;
|
||||
for (const [i, [x, y, w, h]] of e.rects.entries()) {
|
||||
for (let c = 0; c < w; c++) {
|
||||
const free = e.pole === 'left' ? c / w : 1 - c / w;
|
||||
const dy = Math.sin(time / 260 - free * 5 + i) * free * (e.amount ?? 2.2);
|
||||
ctx.drawImage(bg, (x + c) * k, y * k, k, h * k, x + c, y + dy, 1, h);
|
||||
}
|
||||
}
|
||||
},
|
||||
// Un fascio di luce da una finestra: un cono chiaro che sfuma fino al pavimento, appena pulsante.
|
||||
beam(ctx, e, time) {
|
||||
const [[x1, y1], [x2, y2], [x3, y3], [x4, y4]] = e.poly, pulse = 0.85 + 0.15 * Math.sin(time / 2300);
|
||||
const g = ctx.createLinearGradient(x1, y1, (x3 + x4) / 2, (y3 + y4) / 2);
|
||||
g.addColorStop(0, `rgba(255, 236, 180, ${0.42 * pulse})`);
|
||||
g.addColorStop(1, 'rgba(255, 236, 180, 0)');
|
||||
ctx.save();
|
||||
ctx.globalCompositeOperation = 'lighter';
|
||||
ctx.fillStyle = g;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.lineTo(x3, y3); ctx.lineTo(x4, y4);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
},
|
||||
// Lampioni: un alone caldo che si accende (di solito solo di sera, con `phase`).
|
||||
lamps(ctx, e, time) {
|
||||
ctx.save();
|
||||
@@ -426,7 +468,7 @@ export const EFFECTS = {
|
||||
ctx.restore();
|
||||
},
|
||||
};
|
||||
const BACKGROUND_EFFECTS = new Set(['sway', 'clouds']);
|
||||
const BACKGROUND_EFFECTS = new Set(['sway', 'clouds', 'cloth', 'leafshadow']);
|
||||
function drawEffects(ctx, game, time, background = false) {
|
||||
for (const e of game.scene.effects ?? [])
|
||||
if (BACKGROUND_EFFECTS.has(e.type) === background && onNow(e, game)) EFFECTS[e.type]?.(ctx, e, time, game);
|
||||
|
||||
Reference in New Issue
Block a user