diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-03 14:56:41 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-03 14:56:41 +0900 |
| commit | c6d1df09c66bcfe8388651866d26ed5d05b4d2d2 (patch) | |
| tree | 8f55d24a31ec22c1c904157e41ba13cdd88ab420 /public/bluebey-studio/src/faceArt.js | |
| parent | 27483644d7ba9e819dbb5f64844270dd499f45ff (diff) | |
public/bluebey-studio: 鼻ちょうちんの追従とひげを修正
鼻ちょうちんの位置が、カメラ移動やポーズ変更のあとに飛ぶ問題を修正。位置はボーン局所座標で持ち、スライダーのオフセットは体の向きに追従させた。寝ている動きでは鼻ちょうちんを自動で表示する。
ひげは「猫」に左右の間隔スライダーを追加し、太さを変えずに大きくできるようにした。カイゼルは先をダリ風のカールにした。
Diffstat (limited to 'public/bluebey-studio/src/faceArt.js')
| -rw-r--r-- | public/bluebey-studio/src/faceArt.js | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/public/bluebey-studio/src/faceArt.js b/public/bluebey-studio/src/faceArt.js index a92482a..8d20cda 100644 --- a/public/bluebey-studio/src/faceArt.js +++ b/public/bluebey-studio/src/faceArt.js @@ -869,7 +869,7 @@ function drawBeard(ctx, spec, lineOnly = false) { const shape = spec?.shape ?? 'off'; if (shape === 'off' || shape === 'none') return; const size = clamp(spec.size ?? 1, 0.2, 3); - const cx = BEARD_LAYOUT.cx + clamp(spec.offsetX ?? 0, -600, 600); + const cx = BEARD_LAYOUT.cx; const cy = BEARD_LAYOUT.cy + clamp(spec.offsetY ?? 0, -600, 600); const w = BEARD_LAYOUT.width * size; const color = spec.color ?? '#3a2a4a'; @@ -895,8 +895,24 @@ function drawBeard(ctx, spec, lineOnly = false) { { x: cx + w * 0.28, y: cy + w * 0.07 }, { x: cx + w * 0.5, y: cy - w * 0.02 }, ], lw * 2.6); - stroke([{ x: cx - w * 0.5, y: cy - w * 0.02 }, { x: cx - w * 0.62, y: cy - w * 0.16 }], lw * 1.4); - stroke([{ x: cx + w * 0.5, y: cy - w * 0.02 }, { x: cx + w * 0.62, y: cy - w * 0.16 }], lw * 1.4); + const curlAt = (dir) => { + // A little inward-turning spiral at the tip: the Dalí curl. + const ex = cx + dir * w * 0.5; + const ey = cy - w * 0.02; + const r0 = lw * 0.5; + const r1 = w * 0.17; + const steps = 22; + const points = []; + for (let i = 0; i <= steps; i += 1) { + const t = i / steps; + const a = -Math.PI / 2 + dir * Math.PI * 2 * 1.4 * t; + const r = r0 + (r1 - r0) * t; + points.push({ x: ex + dir * Math.cos(a) * r, y: ey + Math.sin(a) * r }); + } + stroke(points, lw * 1.25); + }; + curlAt(-1); + curlAt(1); return; } if (shape === 'apron') { @@ -918,13 +934,19 @@ function drawBeard(ctx, spec, lineOnly = false) { } return; } - // ねこ: three whiskers fanned out on each side of the muzzle. + // ねこ: three whiskers a side, growing out of the cheeks with a gap left in the + // middle (like a cat's). The thickness is fixed, so `size` makes the whiskers + // longer and wider-spread without making them fatter, and `spacing` opens the + // gap between the left and right. + const whisker = 8; + const inner = w * 0.30 + clamp(spec.spacing ?? 0, 0, 800); + const outer = Math.max(inner + w * 0.2, w * 0.68); for (const dir of [-1, 1]) { for (let i = 0; i < 3; i += 1) { stroke([ - { x: cx + dir * w * 0.08, y: cy + w * 0.04 }, - { x: cx + dir * w * 0.62, y: cy + w * 0.04 + (i - 1) * w * 0.18 }, - ], lw * 0.9); + { x: cx + dir * inner, y: cy + (i - 1) * w * 0.16 }, + { x: cx + dir * outer, y: cy + (i - 1) * w * 0.24 }, + ], whisker); } } } |
