This commit is contained in:
33333-33333 2026-06-19 20:52:40 +09:00
commit 8eb66f2e66
12 changed files with 2715 additions and 522 deletions

View file

@ -468,16 +468,58 @@ function drawAtmosphericLighting(ctx, w, h, lighting) {
function drawRain(ctx, w, h, t) {
if (world.weather !== "light_rain") return;
ctx.save();
ctx.globalAlpha = 0.28;
ctx.strokeStyle = "rgba(197, 220, 230, 0.70)";
ctx.lineWidth = 1;
for (let i = 0; i < 34; i++) {
const x = (randSeed(18000 + i, 0, w) + t * 26) % w;
const y = (randSeed(18400 + i, 0, h) + t * 72) % h;
const perf = world.performanceLevel ? world.performanceLevel() : 0;
const count = perf >= 2 ? 58 : 118;
ctx.lineCap = "round";
for (let i = 0; i < count; i++) {
const speed = randSeed(18100 + i, 132, 230);
const cycle = h + 320;
const len = randSeed(18500 + i, 13, 26);
const tilt = randSeed(18600 + i, 5, 12);
const fall = randSeed(18400 + i, -220, cycle) + t * speed;
const y = ((fall % cycle) + cycle) % cycle - 140;
// The droplet's movement vector matches the visible diagonal stroke.
const driftPerY = -tilt / Math.max(1, len);
const xCycle = w + 220;
const rawX = randSeed(18000 + i, -70, w + 120) + fall * driftPerY + Math.sin(t * 0.9 + i * 0.43) * 4;
const x = ((rawX % xCycle) + xCycle) % xCycle - 90;
const alpha = y < 110 ? clamp((y + 68) / 178, 0, 1) : 1;
ctx.globalAlpha = 0.34 + 0.30 * alpha;
ctx.strokeStyle = "rgba(198, 226, 240, 0.92)";
ctx.lineWidth = randSeed(18700 + i, 1.0, 1.8);
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x - 4, y + 10);
ctx.lineTo(x - tilt, y + len);
ctx.stroke();
if (perf < 3 && i % 2 === 0) {
ctx.globalAlpha = 0.18 + 0.18 * alpha;
ctx.fillStyle = "rgba(215, 237, 246, 0.92)";
ctx.beginPath();
ctx.ellipse(x - tilt * 0.9, y + len + 2, 1.8, 3.0, -0.28, 0, Math.PI * 2);
ctx.fill();
}
}
if (perf < 3) {
const dripCount = perf >= 2 ? 10 : 18;
for (let i = 0; i < dripCount; i++) {
const phase = (t * randSeed(18800 + i, 0.55, 1.15) + randSeed(18900 + i, 0, 100)) % 1;
const x = randSeed(19000 + i, 12, w - 12);
const topY = -22 + phase * (h + 58);
const bottomY = topY + randSeed(19100 + i, 14, 30);
const lean = randSeed(19200 + i, -6, -2);
ctx.globalAlpha = 0.44;
ctx.strokeStyle = "rgba(206, 233, 247, 0.98)";
ctx.lineWidth = randSeed(19300 + i, 1.2, 2.2);
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x + lean, bottomY);
ctx.stroke();
ctx.globalAlpha = 0.26;
ctx.beginPath();
ctx.ellipse(x + lean, bottomY + 2, 2.1, 3.5, -0.18, 0, Math.PI * 2);
ctx.fillStyle = "rgba(220, 241, 248, 0.98)";
ctx.fill();
}
}
ctx.restore();
}
@ -486,6 +528,22 @@ function weatherLabel(weather) {
return { sunny: "\u6674\u308c", cloudy: "\u66c7\u308a", light_rain: "\u5c0f\u96e8" }[weather] || "\u6674\u308c";
}
function fillScreenFallback(ctx, w, h, lighting) {
const light = lighting?.light ?? 0.7;
ctx.save();
const bg = ctx.createLinearGradient(0, 0, 0, Math.max(1, h));
if (light > 0.42) {
bg.addColorStop(0, "#cfe3d3");
bg.addColorStop(1, "#d9d0ad");
} else {
bg.addColorStop(0, "#24355f");
bg.addColorStop(1, "#4f5d71");
}
ctx.fillStyle = bg;
ctx.fillRect(0, 0, w, h);
ctx.restore();
}
function render() {
activeCtx = ctx;
const sceneW = world.w, sceneH = world.h;
@ -495,9 +553,9 @@ function render() {
const cameraX = world.cameraX || 0;
const cameraY = world.cameraY || 0;
const viewScale = world.viewScale ? world.viewScale() : 1;
ctx.clearRect(0, 0, screenW, screenH);
const lighting = getLightingState(world);
fillScreenFallback(ctx, screenW, screenH, lighting);
const light = lighting.light;
const cachedBackground = ensureBackgroundCache(sceneW, sceneH, lighting);
@ -523,7 +581,13 @@ function render() {
beginFieldTransform();
for (const it of world.items) {
if (it.type !== "zunchi") it.draw(ctx, world.time, lighting);
if (it.type === "trace" || it.type === "splat") it.draw(ctx, world.time, lighting);
}
for (const ef of world.effects) {
if (ef.type === "bleed") ef.draw(ctx);
}
for (const it of world.items) {
if (it.type !== "zunchi" && it.type !== "trace" && it.type !== "splat") it.draw(ctx, world.time, lighting);
}
for (const it of world.items) {
if (it.type === "zunchi") it.draw(ctx, world.time, lighting);
@ -546,7 +610,9 @@ function render() {
const sorted = world.sortedDrawList ? world.sortedDrawList() : world.tarinai;
for (const t of sorted) t.draw(ctx, world.time, lighting);
for (const ef of world.effects) ef.draw(ctx);
for (const ef of world.effects) {
if (ef.type !== "bleed") ef.draw(ctx);
}
ctx.restore();
// Light affecting the whole visible scene, including characters and ground.
@ -649,4 +715,4 @@ function roundedRect(ctx, x, y, w, h, r) {
}
window.TarinaiRender = { randSeed, roundedBlob, getLightingState, projectedShadowParams, imageVisibleBottomFromTop, drawImageProjectedShadow, drawProjectedShadow, drawRadialGlow, drawItemGlow, drawCreatureGlow, drawDawnRimLight, drawGardenBackdrop, drawGardenBed, drawLightRays, drawAtmosphericLighting, drawRain, drawSelectedCard, render, roundedRect };
window.TarinaiRender = { randSeed, roundedBlob, getLightingState, projectedShadowParams, imageVisibleBottomFromTop, drawImageProjectedShadow, drawProjectedShadow, drawRadialGlow, drawItemGlow, drawCreatureGlow, drawDawnRimLight, drawGardenBackdrop, drawGardenBed, drawLightRays, drawAtmosphericLighting, drawRain, fillScreenFallback, drawSelectedCard, render, roundedRect };