public/lib/wardrobe.js
分割 1 / 7 · 元ファイル 1〜196行付近
/* ===== ショップの品を描く部品(絵は1枚も使わない) =====
ここに入っているのは3つの棚。
COSTUMES … 特別衣装 51種(1つ目は「そのまま」=何も描かない)
HATS … 帽子・頭装備 21種(1つ目は「なし」=何も描かない)
STONES … 石の見た目 10種(1つ目は今の石そのもの)
全部見た目だけ。強さ・当たり判定は一切変わらない。
衣装の描き方:
draw(g, x, shY, bot, r, col, dir)
x … 体の真ん中の横位置
shY … 肩の高さ / bot … 体の下端
r … 頭の半径(大きさは全部これ基準。r を変えれば丸ごと伸び縮みする)
col … その人の服の色 / dir … 向き(+1で右・-1で左)
人の胴は上が狭く下が広い台形。その上から描くので、台形が透けないよう必ず塗りつぶす。
裾は下へ r*0.9、横へ r*1.7 まで出してよい。
帽子の描き方:
draw(g, x, yHead, r, dir, hairCol)
髪はもう描かれているので、頭のてっぺんをきちんと隠す形にする。上へは r*2.2 まで。
石の描き方:
draw(g, r, rot) 原点(0,0)が石の真ん中。r*1.3 の外へはみ出さない。 */
(function () {
/* ---- 色を作る小道具(その人の服の色から明るい色・暗い色を作る) ---- */
function hx(c) {
c = String(c).replace('#', '');
if (c.length === 3) c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];
return [parseInt(c.slice(0, 2), 16), parseInt(c.slice(2, 4), 16), parseInt(c.slice(4, 6), 16)];
}
function rgb(a) { return 'rgb(' + (a[0] | 0) + ',' + (a[1] | 0) + ',' + (a[2] | 0) + ')'; }
function lite(c, f) { var a = hx(c); return rgb([a[0] + (255 - a[0]) * f, a[1] + (255 - a[1]) * f, a[2] + (255 - a[2]) * f]); }
function dark(c, f) { var a = hx(c); return rgb([a[0] * (1 - f), a[1] * (1 - f), a[2] * (1 - f)]); }
/* ---- 決め打ちの差し色(人ごとに変わらない) ---- */
var WH = '#f3f0e7', CR = '#e7e0cc', BK = '#2b2b31', GD = '#e0b24a', PK = '#e58aa8',
RD = '#c4443a', DN = '#4a6f9a', KH = '#8a8256', SV = '#b9bcc2', BR = '#8a6240', GR = '#5f8f63';
/* ---- 胴の形を測る小道具 ----
台形の上辺は幅 0.74r、下辺は 1.16r。t=0で肩、t=1で下端。 */
function T(shY, bot, t) { return shY + (bot - shY) * t; }
function HW(r, t) { return r * (0.74 + 0.42 * t); }
/* 胴をまるごと塗る(下の服を完全に隠す。どの衣装も最初にこれを呼ぶ) */
function base(g, x, shY, bot, r, col) {
g.fillStyle = col;
g.beginPath();
g.moveTo(x - r * 0.74, shY); g.lineTo(x + r * 0.74, shY);
g.lineTo(x + r * 1.16, bot); g.lineTo(x - r * 1.16, bot);
g.closePath(); g.fill();
}
/* 胴の横一段ぶんを別の色で塗る(胸の切り替え・帯・ベルトに使う) */
function panel(g, x, shY, bot, r, t0, t1, col) {
var y0 = T(shY, bot, t0), y1 = T(shY, bot, t1), w0 = HW(r, t0), w1 = HW(r, t1);
g.fillStyle = col;
g.beginPath(); g.moveTo(x - w0, y0); g.lineTo(x + w0, y0);
g.lineTo(x + w1, y1); g.lineTo(x - w1, y1); g.closePath(); g.fill();
}
/* 腰から下を広がるスカートにする(flare=下辺の広さ・drop=下端より下へ出す量) */
function skirt(g, x, shY, bot, r, t, col, flare, drop) {
var y0 = T(shY, bot, t), y1 = bot + r * (drop == null ? 0.5 : drop);
var w0 = HW(r, t), w1 = r * (flare == null ? 1.45 : flare);
g.fillStyle = col;
g.beginPath(); g.moveTo(x - w0, y0); g.lineTo(x + w0, y0);
g.lineTo(x + w1, y1); g.lineTo(x - w1, y1); g.closePath(); g.fill();
}
/* ふわふわの縁(丸を横に並べる) */
function frill(g, x, y, halfW, rad, col, n) {
g.fillStyle = col;
for (var i = 0; i < n; i++) {
g.beginPath(); g.arc(x - halfW + (i + 0.5) * (halfW * 2 / n), y, rad, 0, 7); g.fill();
}
}
/* たての筋(プリーツ) */
function pleat(g, x, y0, y1, hw0, hw1, n, col, w) {
g.strokeStyle = col; g.lineWidth = w || 0.9;
for (var i = 1; i < n; i++) {
var f = i / n * 2 - 1;
g.beginPath(); g.moveTo(x + hw0 * f, y0); g.lineTo(x + hw1 * f, y1); g.stroke();
}
}
/* よこの筋(編み目・ダウンの段) */
function rib(g, x, shY, bot, r, t0, t1, n, col, w) {
g.strokeStyle = col; g.lineWidth = w || 0.9;
for (var i = 0; i < n; i++) {
var t = t0 + (t1 - t0) * (i + 0.5) / n, y = T(shY, bot, t), hw = HW(r, t);
g.beginPath(); g.moveTo(x - hw, y); g.lineTo(x + hw, y); g.stroke();
}
}
/* リボン */
function bow(g, cx, cy, s, col) {
g.fillStyle = col;
g.beginPath(); g.moveTo(cx, cy); g.lineTo(cx - s, cy - s * 0.72); g.lineTo(cx - s, cy + s * 0.72); g.closePath(); g.fill();
g.beginPath(); g.moveTo(cx, cy); g.lineTo(cx + s, cy - s * 0.72); g.lineTo(cx + s, cy + s * 0.72); g.closePath(); g.fill();
g.beginPath(); g.arc(cx, cy, s * 0.36, 0, 7); g.fill();
}
/* Vに開いた胸元 */
function vneck(g, x, shY, r, col, dep) {
g.fillStyle = col;
g.beginPath(); g.moveTo(x - r * 0.42, shY); g.lineTo(x + r * 0.42, shY);
g.lineTo(x, shY + r * (dep || 0.62)); g.closePath(); g.fill();
}
/* 丸い襟 */
function rcollar(g, x, shY, r, col) {
g.fillStyle = col;
g.beginPath(); g.arc(x - r * 0.30, shY + r * 0.02, r * 0.30, 0, 7); g.fill();
g.beginPath(); g.arc(x + r * 0.30, shY + r * 0.02, r * 0.30, 0, 7); g.fill();
}
/* 合わせの襟(着物・道着) */
function xcollar(g, x, shY, bot, r, col) {
var yb = T(shY, bot, 0.42);
g.fillStyle = col;
g.beginPath(); g.moveTo(x - r * 0.66, shY); g.lineTo(x - r * 0.34, shY); g.lineTo(x + r * 0.16, yb); g.lineTo(x - r * 0.10, yb); g.closePath(); g.fill();
g.beginPath(); g.moveTo(x + r * 0.66, shY); g.lineTo(x + r * 0.34, shY); g.lineTo(x - r * 0.16, yb); g.lineTo(x + r * 0.10, yb); g.closePath(); g.fill();
}
/* 前を留めるボタン */
function buttons(g, x, shY, bot, r, col, n, t0, t1) {
g.fillStyle = col;
for (var i = 0; i < n; i++) {
var t = (t0 == null ? 0.28 : t0) + ((t1 == null ? 0.9 : t1) - (t0 == null ? 0.28 : t0)) * (n === 1 ? 0.5 : i / (n - 1));
g.beginPath(); g.arc(x, T(shY, bot, t), r * 0.075, 0, 7); g.fill();
}
}
/* ポケット */
function pocket(g, cx, cy, w, h, col) {
g.fillStyle = col; g.fillRect(cx - w / 2, cy, w, h);
}
/* パーカーのフード(首の後ろのふくらみ) */
function hood(g, x, shY, r, col) {
g.fillStyle = col;
g.beginPath(); g.ellipse(x, shY + r * 0.24, r * 1.00, r * 0.66, 0, Math.PI, Math.PI * 2); g.closePath(); g.fill();
g.fillStyle = dark(col, 0.18);
g.beginPath(); g.ellipse(x, shY + r * 0.26, r * 0.66, r * 0.44, 0, Math.PI, Math.PI * 2); g.closePath(); g.fill();
}
/* 肩から吊る紐(サロペット・キャミ) */
function straps(g, x, shY, bot, r, col, w) {
g.strokeStyle = col; g.lineWidth = w || r * 0.13;
g.beginPath(); g.moveTo(x - r * 0.55, shY); g.lineTo(x - r * 0.34, T(shY, bot, 0.36)); g.stroke();
g.beginPath(); g.moveTo(x + r * 0.55, shY); g.lineTo(x + r * 0.34, T(shY, bot, 0.36)); g.stroke();
}
/* 前を開けた上着(中が見える) */
function openFront(g, x, shY, bot, r, outer, inner) {
base(g, x, shY, bot, r, inner);
g.fillStyle = outer;
g.beginPath(); g.moveTo(x - r * 0.74, shY); g.lineTo(x - r * 0.14, shY);
g.lineTo(x - r * 0.30, bot); g.lineTo(x - r * 1.16, bot); g.closePath(); g.fill();
g.beginPath(); g.moveTo(x + r * 0.74, shY); g.lineTo(x + r * 0.14, shY);
g.lineTo(x + r * 0.30, bot); g.lineTo(x + r * 1.16, bot); g.closePath(); g.fill();
}
/* ================= 特別衣装 51種 ================= */
var COSTUMES = [
/* 何も着せない(買う前の姿) */
{ id: 'plain', nm: 'そのまま', price: 0, tone: 'neutral', draw: function () { } },
/* ---- かわいい・女性向け寄り(35種) ---- */
{ id: 'frill', nm: 'フリル', price: 180, tone: 'cute', draw: function (g, x, shY, bot, r, col) {
base(g, x, shY, bot, r, col);
skirt(g, x, shY, bot, r, 0.44, col, 1.42, 0.42);
var f = lite(col, 0.55);
/* 下半分に明るい布を重ね、その縁を丸く波打たせる */
g.fillStyle = f;
g.beginPath();
g.moveTo(x - r * 1.16, T(shY, bot, 0.74)); g.lineTo(x + r * 1.16, T(shY, bot, 0.74));
g.lineTo(x + r * 1.42, bot + r * 0.42); g.lineTo(x - r * 1.42, bot + r * 0.42); g.closePath(); g.fill();
frill(g, x, T(shY, bot, 0.74), r * 1.16, r * 0.15, f, 5);
frill(g, x, bot + r * 0.42, r * 1.42, r * 0.17, f, 7);
frill(g, x, T(shY, bot, 0.10), HW(r, 0.10), r * 0.11, lite(col, 0.78), 5);
} },
{ id: 'maid', nm: 'メイド服風', price: 320, tone: 'cute', draw: function (g, x, shY, bot, r, col) {
base(g, x, shY, bot, r, dark(col, 0.62));
skirt(g, x, shY, bot, r, 0.50, dark(col, 0.62), 1.48, 0.46);
/* 白いエプロン */
g.fillStyle = WH;
g.beginPath(); g.moveTo(x - r * 0.34, T(shY, bot, 0.16)); g.lineTo(x + r * 0.34, T(shY, bot, 0.16));
g.lineTo(x + r * 0.86, bot + r * 0.36); g.lineTo(x - r * 0.86, bot + r * 0.36); g.closePath(); g.fill();
rcollar(g, x, shY, r, WH);
frill(g, x, bot + r * 0.46, r * 1.44, r * 0.16, WH, 7);
panel(g, x, shY, bot, r, 0.50, 0.58, WH);
bow(g, x, T(shY, bot, 0.20), r * 0.26, PK);
} },
{ id: 'idol', nm: 'アイドル風', price: 360, tone: 'cute', draw: function (g, x, shY, bot, r, col) {
base(g, x, shY, bot, r, lite(col, 0.42));
skirt(g, x, shY, bot, r, 0.52, WH, 1.52, 0.30);
pleat(g, x, T(shY, bot, 0.52), bot + r * 0.30, HW(r, 0.52), r * 1.52, 6, '#c9c4b4', 1);
panel(g, x, shY, bot, r, 0.48, 0.56, GD);
/* 肩のふくらみ */
g.fillStyle = WH;
g.beginPath(); g.arc(x - r * 0.72, shY + r * 0.06, r * 0.24, 0, 7); g.fill();
g.beginPath(); g.arc(x + r * 0.72, shY + r * 0.06, r * 0.24, 0, 7); g.fill();
/* 胸の星 */
g.fillStyle = GD;
g.beginPath();
for (var i = 0; i < 10; i++) {
var a = -Math.PI / 2 + i * Math.PI / 5, rr = r * (i % 2 ? 0.10 : 0.24);
if (i === 0) g.moveTo(x + Math.cos(a) * rr, T(shY, bot, 0.26) + Math.sin(a) * rr);