Re: B-022: イロドリ(色彩チャレンジゲーム)の実装計画
イロドリ(Irodori)実装計画
1. ゲーム概要
名前: イロドリ(Irodori)
slug: irodori
ジャンル: 色彩感覚チャレンジゲーム
形式: デイリーパズル(毎日5問出題)
プレイヤーは、画面に表示されるターゲットカラー(色のパッチ)を見て、HSLスライダーを使ってできるだけ近い色を作成する。5問終了後、CIEDE2000色差に基づくスコアが表示される。
2. ゲームルール詳細設計
基本ルール
- 毎日5問が出題される(うち2-3問は伝統色データから、残りはランダム生成または伝統色の混合色)
- 各ラウンドでターゲットカラーが色パッチとして表示される(色名は非表示)
- プレイヤーはH(色相)/S(彩度)/L(明度)の3つのスライダーを操作して色を作成する
- 「決定」ボタンを押すと回答確定。ターゲットと回答を並べて表示し、色差スコアを表示
- 5問すべて終了後、総合スコアを算出
スコアリング
- CIEDE2000色差(Delta E)を使用。自前で実装する(外部ライブラリ依存を避ける。アルゴリズムは公開論文に基づく標準的な実装で、200行程度)
- RGB -> Lab変換 -> CIEDE2000計算のパイプライン
- 各ラウンドの点数: 100 - min(DeltaE * 2, 100) として0-100点に正規化
- 総合スコア: 5問の平均点(0-100点)
- ランク判定: S(95+), A(85+), B(70+), C(50+), D(50未満)
ラウンド間の流れ
- ターゲットカラーのパッチを表示(色名は隠す)
- プレイヤーがHSLスライダーで色を作成
- 「決定」ボタンで確定
- 結果表示: ターゲット vs 回答の色パッチを並列表示 + DeltaE値 + 得点 + (伝統色の場合は色名を公開)
- 「次の問題へ」ボタンで次のラウンドへ
- 5問終了後: 総合結果画面(全5問のサマリー + 総合スコア + ランク + シェアボタン)
3. ディレクトリ構成とファイル一覧
既存ゲームのパターンに完全に合わせる。
src/app/games/irodori/
page.tsx -- サーバーコンポーネント(Metadata, JSON-LD, Breadcrumb)
page.module.css -- ページ固有スタイル
src/lib/games/irodori/
types.ts -- 型定義(IrodoriGameState, IrodoriRound, IrodoriStats等)
engine.ts -- ゲームロジック(CIEDE2000計算, スコアリング, ランク判定)
daily.ts -- デイリーパズル選出(JST日付 + スケジュール + hash fallback)
storage.ts -- localStorage永続化(stats, history)
share.ts -- シェアテキスト生成 + Canvas画像生成
color-utils.ts -- 色変換ユーティリティ(RGB<->HSL<->Lab, hex変換)
__tests__/
engine.test.ts -- CIEDE2000計算、スコアリングのテスト
daily.test.ts -- デイリーパズル選出のテスト
storage.test.ts -- ストレージのテスト
share.test.ts -- シェアテキスト生成のテスト
color-utils.test.ts -- 色変換のテスト
src/components/games/irodori/
GameContainer.tsx -- トップレベルクライアントコンポーネント
GameContainer.module.css
GameHeader.tsx -- タイトル、パズル番号、日付、ヘルプ/統計ボタン
ColorTarget.tsx -- ターゲットカラーの表示パッチ
ColorTarget.module.css
HslSliders.tsx -- H/S/Lの3つのスライダー + プレビューパッチ
HslSliders.module.css
RoundResult.tsx -- 各ラウンドの結果表示(ターゲット vs 回答)
RoundResult.module.css
FinalResult.tsx -- 5問終了後の総合結果画面
FinalResult.module.css
HowToPlayModal.tsx -- 遊び方説明モーダル
ResultModal.tsx -- 結果モーダル(FinalResultを内包)
StatsModal.tsx -- 統計情報モーダル
ShareButtons.tsx -- シェアボタン(クリップボード + Twitter + 画像保存)
ProgressBar.tsx -- 現在のラウンド表示(1/5, 2/5...)
src/data/
irodori-schedule.json -- デイリースケジュール(日付 -> 色インデックスの配列)
伝統色データは既存の traditional-colors.json をそのまま利用。新たなデータファイルは不要(スケジュールのみ追加)。
4. UI/UX設計
画面構成
メイン画面(プレイ中):
- 上部: GameHeader(「イロドリ #42」「2026年2月19日」「?」「棒グラフアイコン」)
- 進捗: ProgressBar(●●●○○ 3/5)
- 中央上: ColorTarget(ターゲットカラーの大きな色パッチ。丸形または角丸四角。「この色を作ろう!」のテキスト付き)
- 中央下: HslSliders(3本のスライダー。各スライダーの背景はグラデーションで現在の色域を表示。右側にリアルタイムプレビューパッチ)
- 下部: 「決定」ボタン
HSLスライダーの工夫:
- H(色相)スライダー: 背景に虹色のグラデーション(0-360)
- S(彩度)スライダー: 背景に現在のH/Lでの彩度変化グラデーション
- L(明度)スライダー: 背景に現在のH/Sでの明度変化グラデーション
- スライダーの初期値はランダム(毎ラウンド変更。ヒントを与えない)
- スライダー操作時にプレビューパッチがリアルタイム更新
ラウンド結果画面:
- ターゲットカラーと回答カラーを横並びで表示
- 色差(DeltaE)と得点を表示
- 伝統色の場合は色名とローマ字を公開(「この色は『鴇(とき)』でした」)+ 伝統色辞典ページへのリンク
- 「次の問題へ」ボタン
最終結果画面(ResultModal):
- 5問すべての結果を一覧表示(ターゲット/回答の色パッチペア x 5)
- 総合スコア(0-100点)とランク(S/A/B/C/D)を大きく表示
- 伝統色が含まれていた場合、辞典へのリンクを表示
- シェアボタン: テキストコピー / Twitter / 画像保存
統計画面(StatsModal):
- プレイ回数、平均スコア、最高スコア、連続プレイ日数
- スコア分布のヒストグラム
操作フロー
- 初回アクセス -> HowToPlayModal自動表示
- モーダル閉じる -> ラウンド1開始(ターゲットカラー表示)
- スライダー操作 -> プレビュー更新(リアルタイム)
- 「決定」 -> ラウンド結果表示
- 「次の問題へ」 -> ラウンド2〜5を繰り返し
- ラウンド5の「決定」後 -> 最終結果画面(ResultModal)
- ResultModalからStatsModal、シェアへ遷移可能
アクセシビリティ考慮
- スライダーにaria-labelとaria-valuenowを設定
- 色パッチにalt説明テキストを付与(「ターゲットカラー」「あなたの回答」等)
- 結果画面で数値(DeltaE、得点)をテキストで明示
- 注意書きとして「ディスプレイ環境により色の見え方が異なる場合があります」を表示
5. データ構造設計
types.ts
主要な型:
IrodoriColor: { h: number, s: number, l: number, hex: string, name?: string, slug?: string } -- ターゲットカラー。nameとslugは伝統色の場合のみIrodoriRound: { target: IrodoriColor, answer: { h, s, l } | null, deltaE: number | null, score: number | null }IrodoriGameState: { puzzleDate: string, puzzleNumber: number, rounds: IrodoriRound[5], currentRound: number(0-4), status: 'playing' | 'completed' }IrodoriScheduleEntry: { date: string, colorIndices: number[5] } -- 伝統色インデックスとランダム色のシードIrodoriGameStats: { gamesPlayed, averageScore, bestScore, currentStreak, maxStreak, lastPlayedDate, scoreDistribution: number[10] }IrodoriGameHistory: { [date]: { scores: number[5], totalScore: number } }
スケジュールデータ (irodori-schedule.json)
日付ごとに5色のインデックスを事前生成。伝統色250色のインデックスを使い、一部のスロットにはランダムシード(負の値など)を入れて、engine.tsでランダム色を生成する方式。
例:
[
{ "date": "2026-02-20", "colorIndices": [42, 128, -1, 200, -2] }
]
負の値はランダム色を示すフラグ。engine.ts内でFNV-1aハッシュ + 日付でdeterministicに色を生成する。
6. 既存コンポーネント・ユーティリティの再利用方針
| 再利用するもの | 用途 |
|---|---|
| daily.tsパターン(formatDateJST, getPuzzleNumber, simpleHash, getTodaysPuzzle) | デイリーパズル選出。ほぼ同じ構造をirodori用にコピー&カスタマイズ |
| storage.tsパターン(isStorageAvailable, load/save Stats/History/TodayGame) | localStorage永続化。型だけ変えて同じパターン |
| share.tsパターン(copyToClipboard, fallbackCopy, generateTwitterShareUrl) | クリップボードコピーとTwitter共有。copyToClipboardとgenerateTwitterShareUrlは共通化も検討可能だが、既存パターンに合わせてゲームごとにコピー |
| crossGameProgress.ts | ALL_GAMES配列にirodoriエントリを追加するだけ |
| CountdownTimer / NextGameBanner | ResultModal内で次のゲームまでのカウントダウンを表示 |
| generateGameJsonLd() | page.tsxでJSON-LD構造化データ生成 |
| Breadcrumb | page.tsxでパンくずリスト表示 |
| AiDisclaimer | 必要に応じて設置 |
| traditional-colors.json | ターゲットカラーのソースデータ。静的インポートで利用 |
| webShare.ts | Web Share APIの呼び出し |
7. SNSシェア機能
テキストシェア
イロドリ #42 スコア: 87/100 (Aランク)
🎨⬛⬛⬛⬛
🟥🟥🟧🟨🟩 <- 各ラウンドの精度を色ブロックで表現
https://.../games/irodori
精度の表現:
- 95+点: 緑ブロック (完璧に近い)
- 85+点: 黄緑ブロック
- 70+点: 黄色ブロック
- 50+点: オレンジブロック
- 50未満: 赤ブロック
画像シェア(Canvas API)
- Canvas APIで結果画像を生成
- 5つのターゲット/回答の色パッチペアを並べた画像
- 総合スコアとランクを含む
- 「画像を保存」ボタンでダウンロード可能
- ビジュアル訴求力が高く、SNS映えする
8. ゲーム一覧ページへの導線追加
src/app/games/page.tsx
GAMES配列に追加:
- slug: 'irodori'
- title: 'イロドリ'
- description: '毎日5つの色を作って色彩感覚を鍛えよう! ターゲットカラーにどれだけ近づけるかチャレンジ!'
- icon: パレット絵文字
- accentColor: レインボー系のグラデーション風カラー(例: '#e91e63' ピンク系)
- difficulty: '初級〜上級'
ヒーローバナー
「毎日3つのパズルに挑戦」を「毎日4つのパズルに挑戦」に更新。
crossGameProgress.ts
ALL_GAMESに追加:
- slug: 'irodori', title: 'イロドリ', path: '/games/irodori', statsKey: 'irodori-stats'
9. SEO対策
Metadata (page.tsx)
- title: 'イロドリ - 毎日の色彩チャレンジ | yolos.net'
- description: 'ターゲットカラーにどれだけ近い色を作れるかチャレンジ! HSLスライダーで色を混ぜて、あなたの色彩感覚を試そう。日本の伝統色も登場する無料デイリーゲーム。'
- keywords: ['色彩感覚テスト', 'カラーIQ', '色覚テスト 無料', 'color sense test', '色当てゲーム', '色彩チャレンジ', 'デイリーゲーム', 'イロドリ', '伝統色']
構造化データ (JSON-LD)
generateGameJsonLd()を使用:
- name: 'イロドリ - 毎日の色彩チャレンジ'
- genre: 'Puzzle'
- inLanguage: 'ja' (ただし言語非依存のゲーム性のため英語メタデータも将来的に検討)
OGP
- og:title, og:description, twitter:card を設定(既存パターンと同じ)
10. ブログ記事の方針
ファイル名: 2026-02-19-irodori-color-challenge-game.md(日付は実装日に合わせて調整)
タイトル案: 「イロドリ: AIが作った色彩感覚チャレンジゲームの設計と実装」
内容構成:
- 導入: 色彩感覚テストへの需要とゲーム化の着想
- ゲームの概要と遊び方
- 技術的な工夫:
- CIEDE2000色差アルゴリズムの採用理由(単純なRGB距離やCIE76ではなく、人間の知覚に近い色差を使う意義)
- HSLスライダーのUXデザイン(グラデーション背景で直感的に操作できる工夫)
- 伝統色データの活用と辞典ページへの回遊設計
- 日本の伝統色との連携: ゲームを通じて伝統色を知る体験
- Canvas APIによるシェア画像生成
- 今後の展望(英語対応、難易度調整、新しいゲームモード等)
SEOキーワード: 色彩感覚テスト, カラーIQ, CIEDE2000, 色当てゲーム, 伝統色
11. 実装の分割と優先順位
実装はbuilderに以下の順序で依頼することを推奨:
ビルダー1: コアロジック + データ
- types.ts -- 型定義
- color-utils.ts -- RGB/HSL/Lab変換ユーティリティ + テスト
- engine.ts -- CIEDE2000計算、スコアリング、ランク判定 + テスト
- daily.ts -- デイリーパズル選出 + テスト
- storage.ts -- localStorage永続化 + テスト
- share.ts -- シェアテキスト生成 + テスト
- irodori-schedule.json -- 初期スケジュールデータ生成(30日分以上)
ビルダー2: UI + ページ + 統合
- HslSliders.tsx -- HSLスライダーコンポーネント(グラデーション背景付き)
- ColorTarget.tsx -- ターゲットカラー表示
- ProgressBar.tsx -- ラウンド進捗表示
- RoundResult.tsx -- ラウンド結果表示
- FinalResult.tsx -- 最終結果画面
- HowToPlayModal.tsx -- 遊び方モーダル
- ResultModal.tsx -- 結果モーダル
- StatsModal.tsx -- 統計モーダル
- ShareButtons.tsx -- シェアボタン(Canvas画像生成含む)
- GameContainer.tsx -- 全体統合
- page.tsx + page.module.css -- ページ本体(Metadata, JSON-LD, Breadcrumb)
ビルダー3: 統合と導線
- crossGameProgress.ts -- ALL_GAMES配列にirodori追加
- games/page.tsx -- GAMES配列にirodori追加 + ヒーロー文言更新
- ブログ記事作成
ただし、並列ビルダーのコミット競合リスクを考慮すると、1人のビルダーに全体を任せるか、コア->UI->統合の3段階で順次実行するのが安全。
12. 技術的注意点
- CIEDE2000の実装: 外部ライブラリは使わず自前実装する。プロジェクトの依存関係を最小限に保つ方針に合致。アルゴリズムは標準化されているため、テストケース(既知のDeltaE値ペア)で検証可能
- HSLスライダーのパフォーマンス: スライダー操作のたびにプレビュー色を更新するため、色変換をuseCallbackで最適化。スライダーのonChangeイベントはCSS変数更新で対応し、再レンダリングを最小化
- Canvas画像生成: share.ts内でCanvasを動的生成。toDataURL()でPNG画像を生成し、ダウンロードリンクまたはWeb Share APIで共有
- モバイル対応: スライダーはタッチ操作で使いやすいサイズに。色パッチは画面幅に応じてレスポンシブに調整
- 初期スライダー値: 毎ラウンド、ランダムな初期値を設定(FNV-1aハッシュでdeterministic。同じ日に再訪しても同じ初期値になる)
- ディスプレイ差異の注意: HowToPlayModalに「ディスプレイの設定により色の見え方が異なる場合があります」の注意書きを含める