🔬 AI発明ギャラリー kizu インコ育成ゲーム
🔒 サンドボックス内で実行中 ⛶ 全画面で遊ぶ
HTML / CSS / JS
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>マイ・リトル・インコ - インコそだてシミュレーション</title>
  <!-- Tailwind CSS -->
  <script src="https://cdn.tailwindcss.com"></script>
  <!-- FontAwesome Icons -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <!-- Google Fonts -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Kiwi+Maru:wght@300;400;500&family=Yusei+Magic&display=swap" rel="stylesheet">
  
  <style>
    body {
      font-family: 'Kiwi Maru', sans-serif;
      background: linear-gradient(135deg, #fef3c7 0%, #f9f5f0 100%);
    }
    .font-magic {
      font-family: 'Yusei Magic', sans-serif;
    }
    /* アニメーション */
    @keyframes bobbing {
      0%, 100% { transform: translateY(0); }
      50% { transform: translateY(-6px); }
    }
    @keyframes eating {
      0%, 100% { transform: rotate(0deg) translateY(0); }
      30% { transform: rotate(12deg) translateY(3px); }
      70% { transform: rotate(-3deg) translateY(1px); }
    }
    .bird-idle {
      animation: bobbing 3s ease-in-out infinite;
    }
    .bird-eating {
      animation: eating 0.4s ease-in-out 3;
    }
    /* ふきだしの三角 */
    .speech-bubble::after {
      content: '';
      position: absolute;
      bottom: -10px;
      left: 50%;
      transform: translateX(-50%);
      border-width: 10px 10px 0;
      border-style: solid;
      border-color: #ffffff transparent;
      display: block;
      width: 0;
    }
    /* エフェクトアニメーション */
    @keyframes float-up {
      0% { transform: translateY(0) scale(0.8); opacity: 1; }
      100% { transform: translateY(-40px) scale(1.2); opacity: 0; }
    }
    .effect-particle {
      position: absolute;
      animation: float-up 1s ease-out forwards;
      pointer-events: none;
    }
  </style>
</head>
<body class="min-h-screen flex flex-col items-center justify-center p-4">

  <div class="w-full max-w-2xl bg-white rounded-3xl shadow-2xl overflow-hidden border-4 border-amber-200">
    <!-- ヘッダー -->
    <header class="bg-amber-100 p-4 border-b-2 border-amber-200 text-center relative">
      <h1 class="text-2xl font-bold text-amber-800 font-magic flex items-center justify-center gap-2">
        <i class="fa-solid fa-feather-pointed text-amber-500"></i>
        マイ・リトル・インコ
      </h1>
      <p class="text-xs text-amber-600 mt-1">〜 とまり木から はじまる、小さな ともだちとの 日々 〜</p>
    </header>

    <!-- メイン -->
    <main class="p-6">
      
      <!-- STEP 1: ケージのじゅんび -->
      <section id="step-cage" class="space-y-6">
        <div class="text-center">
          <span class="bg-amber-400 text-amber-950 text-xs font-bold px-3 py-1 rounded-full">ステップ 1</span>
          <h2 class="text-xl font-bold text-gray-800 mt-2">インコのおうち(ケージ)を じゅんび しよう!</h2>
          <p class="text-sm text-gray-600 mt-1">インコが あんしんして くらせる おうちを つくります。</p>
        </div>

        <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
          <!-- ケージプレビュー -->
          <div class="bg-blue-50 rounded-2xl p-4 border-2 border-dashed border-blue-200 flex flex-col items-center justify-center min-h-[250px] relative">
            <span class="absolute top-2 left-3 text-xs text-blue-400 font-bold"><i class="fa-solid fa-eye mr-1"></i>おうちの ようす</span>
            
            <!-- ケージ外枠 -->
            <div id="preview-cage-frame" class="w-48 h-56 border-4 border-slate-300 rounded-t-full relative flex items-end justify-center pb-6 bg-white shadow-inner">
              <div class="absolute top-0 w-1 h-3 bg-slate-400 rounded-t-full -mt-3"></div>
              <!-- 縦の格子線 -->
              <div class="absolute inset-x-0 top-6 bottom-0 flex justify-around pointer-events-none opacity-20">
                <div class="w-0.5 bg-slate-500 h-full"></div>
                <div class="w-0.5 bg-slate-500 h-full"></div>
                <div class="w-0.5 bg-slate-500 h-full"></div>
                <div class="w-0.5 bg-slate-500 h-full"></div>
              </div>
              
              <!-- 止まり木 -->
              <div id="preview-perch" class="absolute bottom-16 w-36 h-3 bg-amber-700 rounded-full shadow-sm"></div>
              
              <!-- おもちゃ (ベル or ブランコ) -->
              <div id="preview-toy" class="absolute top-4 inset-x-0 mx-auto w-20 h-20 flex justify-center items-start hidden">
                <!-- ベル -->
                <span id="preview-toy-bell" class="text-2xl hidden">🔔</span>
                <!-- ブランコ (リアルSVG) -->
                <div id="preview-toy-swing" class="w-16 h-16 flex flex-col items-center hidden mt-1">
                  <svg width="40" height="50" viewBox="0 0 40 50">
                    <line x1="20" y1="0" x2="20" y2="10" stroke="#94a3b8" stroke-width="2"/>
                    <path d="M 8 42 A 12 12 0 0 1 32 42" fill="none" stroke="#b45309" stroke-width="2.5"/>
                    <rect x="4" y="40" width="32" height="4" rx="1" fill="#78350f"/>
                  </svg>
                </div>
              </div>
              
              <!-- エサ・水入れ -->
              <div class="absolute bottom-4 left-4 w-6 h-4 bg-yellow-500 rounded-b-md border border-yellow-600"></div>
              <div class="absolute bottom-4 right-4 w-6 h-4 bg-sky-400 rounded-b-md border border-sky-500"></div>
            </div>
          </div>

          <!-- えらぶ項目 -->
          <div class="space-y-4 flex flex-col justify-center">
            <div>
              <label class="block text-sm font-bold text-gray-700 mb-1"><i class="fa-solid fa-tree text-emerald-600 mr-1"></i>とまり木(そざい)</label>
              <div class="grid grid-cols-2 gap-2">
                <button onclick="selectPerch('natural')" id="btn-perch-natural" class="px-3 py-2 text-xs border-2 border-amber-500 bg-amber-50 rounded-xl text-amber-800 font-bold">
                  🌳 てんねんの木
                </button>
                <button onclick="selectPerch('straight')" id="btn-perch-straight" class="px-3 py-2 text-xs border border-gray-300 rounded-xl text-gray-600 hover:bg-gray-50">
                  🪵 まっすぐな丸太
                </button>
              </div>
            </div>

            <div>
              <label class="block text-sm font-bold text-gray-700 mb-1"><i class="fa-solid fa-icons text-purple-600 mr-1"></i>ケージの おもちゃ</label>
              <div class="grid grid-cols-3 gap-2">
                <button onclick="selectToy('none')" id="btn-toy-none" class="px-2 py-2 text-xs border-2 border-amber-500 bg-amber-50 rounded-xl text-amber-800 font-bold">
                  なし
                </button>
                <button onclick="selectToy('bell')" id="btn-toy-bell" class="px-2 py-2 text-xs border border-gray-300 rounded-xl text-gray-600 hover:bg-gray-50">
                  🔔 ベル
                </button>
                <button onclick="selectToy('swing')" id="btn-toy-swing" class="px-2 py-2 text-xs border border-gray-300 rounded-xl text-gray-600 hover:bg-gray-50">
                  🪵 ブランコ
                </button>
              </div>
            </div>

            <div>
              <label class="block text-sm font-bold text-gray-700 mb-1"><i class="fa-solid fa-palette text-rose-500 mr-1"></i>したに しく 紙の いろ</label>
              <div class="flex gap-3">
                <button onclick="selectPaper('#ffffff')" class="w-8 h-8 rounded-full border-2 border-gray-300 bg-white focus:ring-2 focus:ring-amber-400" title="白"></button>
                <button onclick="selectPaper('#fef3c7')" class="w-8 h-8 rounded-full border-2 border-gray-300 bg-amber-100 focus:ring-2 focus:ring-amber-400" title="きいろ"></button>
                <button onclick="selectPaper('#dcfce7')" class="w-8 h-8 rounded-full border-2 border-gray-300 bg-green-100 focus:ring-2 focus:ring-amber-400" title="みどり"></button>
              </div>
            </div>
          </div>
        </div>

        <div class="text-center pt-4">
          <button onclick="finishStepCage()" class="px-8 py-3 bg-gradient-to-r from-amber-500 to-yellow-500 text-white font-bold rounded-full shadow-lg hover:from-amber-600 hover:to-yellow-600 transition-all transform hover:scale-105">
            おうち かんせい!インコを えらびに行く <i class="fa-solid fa-arrow-right ml-1"></i>
          </button>
        </div>
      </section>

      <!-- STEP 2: インコえらび -->
      <section id="step-choose" class="space-y-6 hidden">
        <div class="text-center">
          <span class="bg-amber-400 text-amber-950 text-xs font-bold px-3 py-1 rounded-full">ステップ 2</span>
          <h2 class="text-xl font-bold text-gray-800 mt-2">いっしょに くらす インコを えらぼう!</h2>
          <p class="text-sm text-gray-600 mt-1">すきな インコを えらんで、なまえを つけてね。</p>
        </div>

        <!-- インコえらび -->
        <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
          
          <!-- セキセイインコ -->
          <div onclick="selectBirdType('sekisei')" id="card-sekisei" class="border-2 border-amber-400 bg-amber-50/50 rounded-2xl p-4 cursor-pointer hover:shadow-md transition-all text-center flex flex-col items-center justify-between">
            <div class="w-20 h-20 rounded-full bg-emerald-100 flex items-center justify-center text-3xl mb-2 relative">🟢</div>
            <div>
              <h3 class="font-bold text-gray-800">セキセイインコ</h3>
              <p class="text-[10px] text-gray-500 mt-1">おしゃべり大好き。カラフルな模様が特徴。</p>
            </div>
          </div>

          <!-- コザクラインコ -->
          <div onclick="selectBirdType('kozakura')" id="card-kozakura" class="border border-gray-200 rounded-2xl p-4 cursor-pointer hover:shadow-md transition-all text-center flex flex-col items-center justify-between">
            <div class="w-20 h-20 rounded-full bg-rose-100 flex items-center justify-center text-3xl mb-2 relative">🍑</div>
            <div>
              <h3 class="font-bold text-gray-800">コザクラインコ</h3>
              <p class="text-[10px] text-gray-500 mt-1">愛情深い、ラブバード。顔の赤がチャーム。</p>
            </div>
          </div>

          <!-- オカメインコ -->
          <div onclick="selectBirdType('okame')" id="card-okame" class="border border-gray-200 rounded-2xl p-4 cursor-pointer hover:shadow-md transition-all text-center flex flex-col items-center justify-between">
            <div class="w-20 h-20 rounded-full bg-yellow-100 flex items-center justify-center text-3xl mb-2 relative">🐤</div>
            <div>
              <h3 class="font-bold text-gray-800">オカメインコ</h3>
              <p class="text-[10px] text-gray-500 mt-1">ほっぺのチークが可愛い、歌うのが大好き。</p>
            </div>
          </div>

          <!-- マメルリハ -->
          <div onclick="selectBirdType('mameru')" id="card-mameru" class="border border-gray-200 rounded-2xl p-4 cursor-pointer hover:shadow-md transition-all text-center flex flex-col items-center justify-between">
            <div class="w-20 h-20 rounded-full bg-blue-100 flex items-center justify-center text-3xl mb-2 relative">💧</div>
            <div>
              <h3 class="font-bold text-gray-800">マメルリハ</h3>
              <p class="text-[10px] text-gray-500 mt-1">小さな体に秘めたパワー。好奇心旺盛!</p>
            </div>
          </div>

          <!-- ウロコインコ -->
          <div onclick="selectBirdType('uroko')" id="card-uroko" class="border border-gray-200 rounded-2xl p-4 cursor-pointer hover:shadow-md transition-all text-center flex flex-col items-center justify-between">
            <div class="w-20 h-20 rounded-full bg-amber-100 flex items-center justify-center text-3xl mb-2 relative">☀️</div>
            <div>
              <h3 class="font-bold text-gray-800">ウロコインコ</h3>
              <p class="text-[10px] text-gray-500 mt-1">懐っこい性格。お腹の鱗模様がとっても綺麗。</p>
            </div>
          </div>

          <!-- ボタンインコ -->
          <div onclick="selectBirdType('botan')" id="card-botan" class="border border-gray-200 rounded-2xl p-4 cursor-pointer hover:shadow-md transition-all text-center flex flex-col items-center justify-between">
            <div class="w-20 h-20 rounded-full bg-red-100 flex items-center justify-center text-3xl mb-2 relative">🏮</div>
            <div>
              <h3 class="font-bold text-gray-800">ボタンインコ</h3>
              <p class="text-[10px] text-gray-500 mt-1">鮮やかな羽色と、目の周りの白いリング。</p>
            </div>
          </div>

        </div>

        <!-- 名前入力 -->
        <div class="max-w-xs mx-auto text-center space-y-2 pt-4">
          <label class="block text-sm font-bold text-gray-700">インコの なまえ</label>
          <input type="text" id="input-bird-name" value="ピーちゃん" maxlength="10" class="w-full text-center px-4 py-2 border-2 border-amber-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 text-lg font-bold">
        </div>

        <div class="text-center">
          <button onclick="finishStepChoose()" class="px-8 py-3 bg-gradient-to-r from-emerald-500 to-teal-500 text-white font-bold rounded-full shadow-lg hover:from-emerald-600 hover:to-teal-600 transition-all transform hover:scale-105">
            おうちにお迎えする! <i class="fa-solid fa-home ml-1"></i>
          </button>
        </div>
      </section>

      <!-- STEP 3: メイン育成ゲーム画面 -->
      <section id="step-game" class="space-y-6 hidden">
        
        <!-- セーブロード・ステータスバー -->
        <div class="flex flex-col sm:flex-row justify-between items-center bg-amber-50 p-4 rounded-2xl border border-amber-100 gap-3">
          <div class="grid grid-cols-2 md:grid-cols-4 gap-2 text-center w-full sm:w-auto flex-1">
            <div>
              <span class="text-xs text-amber-600 block">なまえ</span>
              <span id="stat-name" class="font-bold text-gray-800 text-sm md:text-base">-</span>
            </div>
            <div>
              <span class="text-xs text-amber-600 block">日数</span>
              <span id="stat-days" class="font-bold text-gray-800 text-sm md:text-base">1日目</span>
            </div>
            <div>
              <span class="text-xs text-amber-600 block">おもさ(たいじゅう)</span>
              <span id="stat-weight" class="font-bold text-gray-800 text-sm md:text-base">-</span>
            </div>
            <div>
              <span class="text-xs text-amber-600 block">おぼえた ことば</span>
              <span id="stat-words" class="font-bold text-gray-800 text-sm md:text-base">0語</span>
            </div>
          </div>
          
          <!-- セーブ・ロードボタン -->
          <div class="flex gap-2 w-full sm:w-auto justify-center">
            <button onclick="saveGameData()" class="px-4 py-2 bg-emerald-500 hover:bg-emerald-600 text-white font-bold text-xs rounded-xl shadow transition-all flex items-center gap-1">
              <i class="fa-solid fa-floppy-disk"></i> セーブ
            </button>
            <button onclick="loadGameData()" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white font-bold text-xs rounded-xl shadow transition-all flex items-center gap-1">
              <i class="fa-solid fa-circle-arrow-down"></i> ロード
            </button>
          </div>
        </div>

        <!-- メインケージ・インコ表示エリア -->
        <div class="bg-sky-50 rounded-2xl p-6 border-2 border-sky-100 flex flex-col items-center justify-center min-h-[360px] relative overflow-hidden">
          
          <!-- ふきだし -->
          <div id="bird-speech" class="absolute top-4 bg-white px-4 py-2 rounded-2xl shadow-md border-2 border-amber-200 text-sm font-bold text-amber-800 speech-bubble transition-all duration-300 opacity-0 transform translate-y-2 z-10">
            ピピッ!
          </div>

          <!-- エフェクト -->
          <div id="effect-layer" class="absolute inset-0 pointer-events-none"></div>

          <!-- おうち -->
          <div id="game-cage-frame" class="w-64 h-80 border-4 border-slate-300 rounded-t-full relative flex items-end justify-center pb-8 bg-white/80 shadow-md">
            
            <!-- 天井フック -->
            <div class="absolute top-0 w-1 h-3 bg-slate-400 rounded-t-full -mt-3"></div>
            <!-- 格子 -->
            <div class="absolute inset-x-0 top-8 bottom-0 flex justify-around pointer-events-none opacity-10">
              <div class="w-0.5 bg-slate-500 h-full"></div>
              <div class="w-0.5 bg-slate-500 h-full"></div>
              <div class="w-0.5 bg-slate-500 h-full"></div>
              <div class="w-0.5 bg-slate-500 h-full"></div>
              <div class="w-0.5 bg-slate-500 h-full"></div>
            </div>

            <!-- おもちゃ (ベル or ブランコ) -->
            <div id="game-toy-area" class="absolute top-10 inset-x-0 mx-auto w-24 h-24 flex justify-center items-start">
              <span id="game-toy-bell" class="text-3xl hidden">🔔</span>
              
              <!-- リアルなブランコ(SVG) -->
              <div id="game-toy-swing" class="w-20 h-20 flex flex-col items-center hidden">
                <svg width="60" height="70" viewBox="0 0 60 70">
                  <!-- つり下げチェーン -->
                  <line x1="30" y1="0" x2="30" y2="15" stroke="#94a3b8" stroke-width="2"/>
                  <!-- ブランコのアーチ部分 -->
                  <path d="M 12 55 A 18 18 0 0 1 48 55" fill="none" stroke="#d97706" stroke-width="3"/>
                  <!-- ビーズの飾り -->
                  <circle cx="13" cy="45" r="4" fill="#ef4444"/>
                  <circle cx="47" cy="45" r="4" fill="#3b82f6"/>
                  <!-- 止まり木部分 -->
                  <rect x="6" y="52" width="48" height="6" rx="2" fill="#78350f"/>
                </svg>
              </div>
            </div>

            <!-- 止まり木 -->
            <div id="game-perch" class="absolute bottom-20 w-48 h-4 bg-amber-700 rounded-full shadow-md z-0"></div>

            <!-- 食器たち -->
            <div class="absolute bottom-6 left-6 flex flex-col items-center">
              <div id="food-level" class="w-5 h-2 bg-yellow-600 rounded-full absolute bottom-1 transition-all duration-300"></div>
              <div class="w-7 h-5 bg-amber-500 rounded-b-md border border-amber-600 z-10 opacity-80"></div>
            </div>
            <div class="absolute bottom-6 right-6 flex flex-col items-center">
              <div id="water-level" class="w-5 h-2 bg-sky-300 rounded-full absolute bottom-1 transition-all duration-300"></div>
              <div class="w-7 h-5 bg-sky-400 rounded-b-md border border-sky-500 z-10 opacity-80"></div>
            </div>

            <!-- リアルなインコ本体 -->
            <div id="bird-character" class="bird-idle absolute bottom-[88px] transition-all duration-500 flex flex-col items-center z-20 cursor-pointer" onclick="tapBird()">
              <span id="bird-emotion" class="absolute -top-10 text-xl transition-all duration-300 opacity-0">❤️</span>
              
              <!-- シンプルで可愛いインコSVG -->
              <svg id="bird-svg" width="90" height="95" viewBox="0 0 100 100" class="transition-all duration-300">
                <!-- 尾羽 -->
                <path id="svg-tail" d="M 40 70 L 50 95 L 60 70 Z" fill="#059669" />
                
                <!-- 体 -->
                <ellipse id="svg-body" cx="50" cy="65" rx="30" ry="35" fill="#10b981" />
                
                <!-- お腹 -->
                <ellipse id="svg-belly" cx="50" cy="70" rx="20" ry="25" fill="#a7f3d0" />
                
                <!-- 頭 -->
                <circle id="svg-head" cx="50" cy="35" r="25" fill="#10b981" />
                
                <!-- ほっぺ -->
                <circle id="svg-cheek-l" cx="35" cy="40" r="5" fill="#4f46e5" opacity="0.6" />
                <circle id="svg-cheek-r" cx="65" cy="40" r="5" fill="#4f46e5" opacity="0.6" />
                
                <!-- 目 -->
                <circle cx="40" cy="30" r="4" fill="#111827" />
                <circle cx="60" cy="30" r="4" fill="#111827" />
                
                <!-- ろう膜 -->
                <ellipse id="svg-cere" cx="50" cy="32" rx="6" ry="3" fill="#3b82f6" />
                
                <!-- くちばし -->
                <path d="M 45 35 L 55 35 L 50 45 Z" fill="#fbbf24" />
              </svg>
            </div>

          </div>

          <!-- エサ・水のじょうたい -->
          <div class="mt-4 flex gap-4 text-xs">
            <span id="msg-food-status" class="bg-yellow-100 text-yellow-800 px-3 py-1 rounded-full font-bold">🌾 エサ:満足</span>
            <span id="msg-water-status" class="bg-sky-100 text-sky-800 px-3 py-1 rounded-full font-bold">💧 お水:きれい</span>
          </div>
        </div>

        <!-- お世話ボタン -->
        <div class="grid grid-cols-2 md:grid-cols-4 gap-2">
          <button onclick="feedBird()" class="py-3 px-4 bg-yellow-100 hover:bg-yellow-200 text-yellow-800 font-bold rounded-2xl border-2 border-yellow-300 transition-all flex items-center justify-center gap-1">
            🌾 エサをあげる
          </button>
          <button onclick="giveWater()" class="py-3 px-4 bg-sky-100 hover:bg-sky-200 text-sky-800 font-bold rounded-2xl border-2 border-sky-300 transition-all flex items-center justify-center gap-1">
            💧 水をかえる
          </button>
          <button onclick="playWithBird()" class="py-3 px-4 bg-rose-100 hover:bg-rose-200 text-rose-800 font-bold rounded-2xl border-2 border-rose-300 transition-all flex items-center justify-center gap-1">
            🎈 なでて あそぶ
          </button>
          <button onclick="nextDay()" class="py-3 px-4 bg-emerald-600 hover:bg-emerald-700 text-white font-bold rounded-2xl transition-all flex items-center justify-center gap-1 shadow-md">
            🌙 1日 すすめる
          </button>
        </div>

        <!-- おしゃべりおべんきょう -->
        <div class="bg-purple-50 p-4 rounded-2xl border border-purple-100 space-y-3">
          <h3 class="font-bold text-purple-900 text-sm flex items-center gap-1">
            <i class="fa-solid fa-graduation-cap"></i> おしゃべり れんしゅう
          </h3>
          <p class="text-xs text-purple-700">インコに おしえたい ことばを 入力して、「おしえる」を おしてね!毎日すこしずつ おぼえます。</p>
          
          <div class="flex gap-2">
            <input type="text" id="input-teach-word" placeholder="こんにちは!" maxlength="8" class="flex-1 px-3 py-2 border-2 border-purple-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 text-sm">
            <button onclick="teachWord()" class="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white text-sm font-bold rounded-xl transition-all">
              おしえる
            </button>
          </div>

          <!-- おぼえた言葉 -->
          <div>
            <span class="text-xs font-bold text-purple-800 block mb-1">いま おぼえている ことば:</span>
            <div id="learned-words-container" class="flex flex-wrap gap-1">
              <span class="text-xs bg-white text-purple-600 px-2 py-1 rounded-md border border-purple-100">ピピッ!</span>
            </div>
          </div>
        </div>

        <!-- 日記ログ -->
        <div class="bg-gray-50 p-3 rounded-xl border border-gray-200">
          <span class="text-xs text-gray-400 font-bold block mb-1">そだて日記(にっき)</span>
          <div id="game-log" class="text-xs text-gray-600 h-16 overflow-y-auto space-y-1">
            <div class="text-emerald-600">おうちへ ようこそ!これから なかよく くらそうね。</div>
          </div>
        </div>

      </section>

    </main>
    
    <!-- フッター -->
    <footer class="bg-gray-50 p-3 text-center border-t border-gray-100">
      <p class="text-[10px] text-gray-400">© 2026 マイ・リトル・インコ シミュレーター</p>
    </footer>
  </div>

  <!-- トースト -->
  <div id="toast-message" class="fixed bottom-6 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-2 rounded-xl text-sm font-bold opacity-0 transition-opacity duration-300 pointer-events-none z-50">
    メッセージ
  </div>

  <!-- Firebase SDK Modules -->
  <script type="module">
    import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-app.js";
    import { getAuth, signInWithCustomToken, signInAnonymously, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-auth.js";
    import { getFirestore, doc, setDoc, getDoc } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js";

    // --- Firebase 初期化 (環境のグローバル変数を使用) ---
    const firebaseConfig = JSON.parse(__firebase_config);
    const app = initializeApp(firebaseConfig);
    const auth = getAuth(app);
    const db = getFirestore(app);
    const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id';

    let currentUser = null;

    // 認証プロセス (RULE 3)
    const initAuth = async () => {
      try {
        if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) {
          await signInWithCustomToken(auth, __initial_auth_token);
        } else {
          await signInAnonymously(auth);
        }
      } catch (error) {
        console.error("Authentication failed:", error);
      }
    };
    initAuth();

    onAuthStateChanged(auth, (user) => {
      currentUser = user;
      if (user) {
        console.log("Authenticated user:", user.uid);
        // 自動ロードの呼び出しも可能
        tryAutoLoad();
      }
    });

    // --- ゲームデータ保存 (セーブ) ---
    window.saveGameData = async function() {
      if (!currentUser) {
        window.showToast("セーブするには ネットに せつぞくしてね。");
        return;
      }
      try {
        // 保存するパス (RULE 1)
        const saveDocRef = doc(db, 'artifacts', appId, 'users', currentUser.uid, 'saves', 'current');
        
        // セーブデータ作成
        const saveData = {
          cage: window.gameState.cage,
          bird: window.gameState.bird,
          day: window.gameState.day,
          weight: window.gameState.weight,
          food: window.gameState.food,
          water: window.gameState.water,
          love: window.gameState.love,
          words: window.gameState.words,
          updatedAt: new Date().toISOString()
        };

        await setDoc(saveDocRef, saveData);
        window.showToast("データを クラウドに セーブしました!💾");
        window.addLog("セーブしました。いつでも つづきから あそべます。");
      } catch (e) {
        console.error("Save error: ", e);
        window.showToast("セーブに しっぱい しました。");
      }
    };

    // --- ゲームデータ読込 (ロード) ---
    window.loadGameData = async function() {
      if (!currentUser) {
        window.showToast("ロードするには ネットに せつぞくしてね。");
        return;
      }
      try {
        const saveDocRef = doc(db, 'artifacts', appId, 'users', currentUser.uid, 'saves', 'current');
        const docSnap = await getDoc(saveDocRef);

        if (docSnap.exists()) {
          const loadedData = docSnap.data();
          
          // gameStateに反映
          window.gameState.cage = loadedData.cage;
          window.gameState.bird = loadedData.bird;
          window.gameState.day = loadedData.day;
          window.gameState.weight = loadedData.weight;
          window.gameState.food = loadedData.food;
          window.gameState.water = loadedData.water;
          window.gameState.love = loadedData.love;
          window.gameState.words = loadedData.words || ['ピピッ!', 'ピヨ!'];

          // UI表示の更新
          window.applyLoadedGame();
          window.showToast("クラウドから ロードしました!📂");
          window.addLog(`セーブデータを ロードして ${window.gameState.day}日目から つづけます!`);
        } else {
          window.showToast("セーブデータが みつかりませんでした。");
        }
      } catch (e) {
        console.error("Load error: ", e);
        window.showToast("ロードに しっぱい しました。");
      }
    };

    // 自動でロードをこころみる
    async function tryAutoLoad() {
      if (!currentUser) return;
      const saveDocRef = doc(db, 'artifacts', appId, 'users', currentUser.uid, 'saves', 'current');
      const docSnap = await getDoc(saveDocRef);
      if (docSnap.exists()) {
        window.addLog("前の そだてデータが クラウドに あります。「ロード」ボタンから つづきを あそべます。");
      }
    }
  </script>

  <!-- ゲームロジック用一般スクリプト -->
  <script>
    // --- ゲームの初期データ/状態管理 ---
    window.gameState = {
      cage: {
        perch: 'natural', 
        toy: 'none',      
        paperColor: '#ffffff'
      },
      bird: {
        type: 'sekisei',  
        name: 'ピーちゃん',
        colorTheme: {
          tail: '#059669',
          body: '#10b981',
          belly: '#a7f3d0',
          head: '#10b981',
          cheek: '#4f46e5',
          cere: '#3b82f6' // ろう膜(鼻)の色
        }
      },
      day: 1,
      weight: 12.0,      
      food: 100,         
      water: 100,        
      love: 20,          
      words: ['ピピッ!', 'ピヨ!'], 
      teachingWord: '',  
      teachCount: 0,     
      isSleeping: false
    };

    // インコのカラーテーマ
    const birdColors = {
      sekisei: { tail: '#059669', body: '#10b981', belly: '#fde047', head: '#fde047', cheek: '#4f46e5', cere: '#3b82f6' },
      kozakura: { tail: '#0284c7', body: '#16a34a', belly: '#a7f3d0', head: '#f43f5e', cheek: '#f43f5e', cere: '#fca5a5' },
      okame: { tail: '#475569', body: '#64748b', belly: '#cbd5e1', head: '#fef08a', cheek: '#ea580c', cere: '#94a3b8' },
      mameru: { tail: '#3b82f6', body: '#3b82f6', belly: '#bfdbfe', head: '#60a5fa', cheek: '#1e40af', cere: '#3b82f6' },
      uroko: { tail: '#991b1b', body: '#15803d', belly: '#f59e0b', head: '#78350f', cheek: '#e11d48', cere: '#78350f' },
      botan: { tail: '#2563eb', body: '#dc2626', belly: '#fbbf24', head: '#7f1d1d', cheek: '#b91c1c', cere: '#fecaca' }
    };

    const stepCage = document.getElementById('step-cage');
    const stepChoose = document.getElementById('step-choose');
    const stepGame = document.getElementById('step-game');

    // --- STEP 1: おうちのじゅんび ---
    function selectPerch(type) {
      window.gameState.cage.perch = type;
      const preview = document.getElementById('preview-perch');
      const gamePerch = document.getElementById('game-perch');
      
      document.getElementById('btn-perch-natural').className = type === 'natural' 
        ? 'px-3 py-2 text-xs border-2 border-amber-500 bg-amber-50 rounded-xl text-amber-800 font-bold'
        : 'px-3 py-2 text-xs border border-gray-300 rounded-xl text-gray-600 hover:bg-gray-50';
      document.getElementById('btn-perch-straight').className = type === 'straight' 
        ? 'px-3 py-2 text-xs border-2 border-amber-500 bg-amber-50 rounded-xl text-amber-800 font-bold'
        : 'px-3 py-2 text-xs border border-gray-300 rounded-xl text-gray-600 hover:bg-gray-50';

      if (type === 'natural') {
        preview.style.height = '14px';
        preview.style.borderRadius = '30% 70% 70% 30% / 50% 30% 70% 50%';
        if(gamePerch) gamePerch.style.borderRadius = '30% 70% 70% 30% / 50% 30% 70% 50%';
      } else {
        preview.style.height = '12px';
        preview.style.borderRadius = '9999px';
        if(gamePerch) gamePerch.style.borderRadius = '9999px';
      }
    }

    function selectToy(type) {
      window.gameState.cage.toy = type;
      
      // ボタンデザイン切り替え
      ['none', 'bell', 'swing'].forEach(t => {
        const btn = document.getElementById(`btn-toy-${t}`);
        if(t === type) {
          btn.className = 'px-2 py-2 text-xs border-2 border-amber-500 bg-amber-50 rounded-xl text-amber-800 font-bold';
        } else {
          btn.className = 'px-2 py-2 text-xs border border-gray-300 rounded-xl text-gray-600 hover:bg-gray-50';
        }
      });

      // プレビューの切り替え
      const previewToy = document.getElementById('preview-toy');
      const pBell = document.getElementById('preview-toy-bell');
      const pSwing = document.getElementById('preview-toy-swing');

      if (type === 'none') {
        previewToy.classList.add('hidden');
      } else {
        previewToy.classList.remove('hidden');
        if (type === 'bell') {
          pBell.classList.remove('hidden');
          pSwing.classList.add('hidden');
        } else {
          pBell.classList.add('hidden');
          pSwing.classList.remove('hidden');
        }
      }

      // ゲーム画面の切り替え
      updateGameToyUI();
    }

    function updateGameToyUI() {
      const gBell = document.getElementById('game-toy-bell');
      const gSwing = document.getElementById('game-toy-swing');
      const type = window.gameState.cage.toy;

      if (type === 'none') {
        if(gBell) gBell.classList.add('hidden');
        if(gSwing) gSwing.classList.add('hidden');
      } else if (type === 'bell') {
        if(gBell) gBell.classList.remove('hidden');
        if(gSwing) gSwing.classList.add('hidden');
      } else {
        if(gBell) gBell.classList.add('hidden');
        if(gSwing) gSwing.classList.remove('hidden');
      }
    }

    function selectPaper(color) {
      window.gameState.cage.paperColor = color;
      document.getElementById('preview-cage-frame').style.backgroundColor = color;
      const gameCage = document.getElementById('game-cage-frame');
      if (gameCage) {
        gameCage.style.backgroundColor = color + 'cc';
      }
    }

    function finishStepCage() {
      showToast('ケージのじゅんび 完了!');
      stepCage.classList.add('hidden');
      stepChoose.classList.remove('hidden');
    }

    // --- STEP 2: インコえらび ---
    function selectBirdType(type) {
      window.gameState.bird.type = type;
      window.gameState.bird.colorTheme = birdColors[type];

      ['sekisei', 'kozakura', 'okame', 'mameru', 'uroko', 'botan'].forEach(t => {
        const card = document.getElementById(`card-${t}`);
        if (t === type) {
          card.classList.add('border-amber-400', 'bg-amber-50/50');
          card.classList.remove('border-gray-200');
        } else {
          card.classList.remove('border-amber-400', 'bg-amber-50/50');
          card.classList.add('border-gray-200');
        }
      });
    }

    function finishStepChoose() {
      const nameInput = document.getElementById('input-bird-name').value.trim();
      if (!nameInput) {
        showToast('なまえを入力してね!');
        return;
      }
      window.gameState.bird.name = nameInput;
      
      initGameScreen();
      
      stepChoose.classList.add('hidden');
      stepGame.classList.remove('hidden');
      
      showToast(`${window.gameState.bird.name}を お迎えしました!`);
      addLog(`かわいい ${window.gameState.bird.name}が やってきた!いっぱい なかよくしてね。`);
    }

    // --- STEP 3: メイン育成ゲーム ---
    
    function initGameScreen() {
      document.getElementById('stat-name').innerText = window.gameState.bird.name;
      updateStatusUI();
      applyBirdColor();
      updateGameToyUI();

      document.getElementById('game-cage-frame').style.backgroundColor = window.gameState.cage.paperColor + 'd0';
      updateLearnedWordsUI();
    }

    // インコSVGへの着色
    function applyBirdColor() {
      const colors = window.gameState.bird.colorTheme;
      document.getElementById('svg-tail').setAttribute('fill', colors.tail);
      document.getElementById('svg-body').setAttribute('fill', colors.body);
      document.getElementById('svg-belly').setAttribute('fill', colors.belly);
      document.getElementById('svg-head').setAttribute('fill', colors.head);
      document.getElementById('svg-cheek-l').setAttribute('fill', colors.cheek);
      document.getElementById('svg-cheek-r').setAttribute('fill', colors.cheek);
      document.getElementById('svg-cere').setAttribute('fill', colors.cere);
    }

    // ステータスUIのこうしん
    function updateStatusUI() {
      document.getElementById('stat-days').innerText = `${window.gameState.day}日目`;
      document.getElementById('stat-weight').innerText = `${window.gameState.weight.toFixed(1)}g`;
      document.getElementById('stat-words').innerText = `${window.gameState.words.length}語`;

      const foodLvl = document.getElementById('food-level');
      foodLvl.style.height = `${window.gameState.food / 15}px`;
      const foodMsg = document.getElementById('msg-food-status');
      if (window.gameState.food > 60) {
        foodMsg.innerText = '🌾 エサ:満足';
        foodMsg.className = 'bg-yellow-100 text-yellow-800 px-3 py-1 rounded-full font-bold';
      } else if (window.gameState.food > 20) {
        foodMsg.innerText = '🌾 エサ:普通';
        foodMsg.className = 'bg-amber-100 text-amber-800 px-3 py-1 rounded-full font-bold';
      } else {
        foodMsg.innerText = '🌾 エサ:おなかペコペコ';
        foodMsg.className = 'bg-rose-100 text-rose-800 px-3 py-1 rounded-full font-bold animate-pulse';
      }

      const waterLvl = document.getElementById('water-level');
      waterLvl.style.height = `${window.gameState.water / 15}px`;
      const waterMsg = document.getElementById('msg-water-status');
      if (window.gameState.water > 50) {
        waterMsg.innerText = '💧 お水:きれい';
        waterMsg.className = 'bg-sky-100 text-sky-800 px-3 py-1 rounded-full font-bold';
      } else {
        waterMsg.innerText = '💧 お水:よごれている';
        waterMsg.className = 'bg-blue-200 text-blue-900 px-3 py-1 rounded-full font-bold animate-pulse';
      }

      // 成長スケール
      const minW = 12.0;
      const maxW = 40.0;
      let scale = 0.6 + ((window.gameState.weight - minW) / (maxW - minW)) * 0.5;
      if (scale > 1.25) scale = 1.25;
      document.getElementById('bird-svg').style.transform = `scale(${scale})`;
    }

    // エサをあげる
    function feedBird() {
      if (window.gameState.isSleeping) {
        showToast('インコは ねむっています💤');
        return;
      }
      if (window.gameState.food >= 100) {
        showToast('もう おなかいっぱいです!');
        return;
      }

      window.gameState.food = Math.min(100, window.gameState.food + 40);
      window.gameState.love = Math.min(100, window.gameState.love + 5);
      
      triggerBirdAnimation('bird-eating');
      spawnEffect('🌾');
      spawnEffect('❤️');

      addLog(`${window.gameState.bird.name}は うれしそうに エサをつついた。`);
      updateStatusUI();

      setTimeout(() => {
        saySomething('モグモグ…おいしい!');
      }, 1000);
    }

    // 水をかえる
    function giveWater() {
      if (window.gameState.isSleeping) {
        showToast('インコは ねむっています💤');
        return;
      }
      if (window.gameState.water >= 100) {
        showToast('お水は すでに きれいです。');
        return;
      }

      window.gameState.water = 100;
      window.gameState.love = Math.min(100, window.gameState.love + 3);
      
      spawnEffect('💧');
      addLog('お水を あたらしく とりかえました。');
      updateStatusUI();

      setTimeout(() => {
        saySomething('コクコク…ぷはぁ!');
      }, 500);
    }

    // なでる・遊ぶ
    function playWithBird() {
      if (window.gameState.isSleeping) {
        showToast('インコは ねむっています💤');
        return;
      }

      window.gameState.love = Math.min(100, window.gameState.love + 10);
      spawnEffect('❤️');
      spawnEffect('🎶');

      addLog(`${window.gameState.bird.name}を なでてあげた。うれしそうに している。`);
      showEmotion('❤️');

      setTimeout(() => {
        const randWord = window.gameState.words[Math.floor(Math.random() * window.gameState.words.length)];
        saySomething(randWord);
      }, 600);
    }

    function tapBird() {
      if (window.gameState.isSleeping) {
        showEmotion('💤');
        saySomething('スースー…');
        return;
      }
      playWithBird();
    }

    // ことばを教える
    function teachWord() {
      if (window.gameState.isSleeping) {
        showToast('インコは ねむっています💤');
        return;
      }

      const input = document.getElementById('input-teach-word');
      const word = input.value.trim();

      if (!word) {
        showToast('おしえたい ことばを 入力してね!');
        return;
      }

      if (window.gameState.words.includes(word)) {
        showToast('その ことばは もう おぼえているよ!');
        return;
      }

      if (window.gameState.teachingWord !== word) {
        window.gameState.teachingWord = word;
        window.gameState.teachCount = 0;
      }

      window.gameState.teachCount++;
      spawnEffect('🎓');
      
      addLog(`${window.gameState.bird.name}に「${word}」と はなしかけた。`);
      
      if (window.gameState.teachCount >= 3) {
        window.gameState.words.push(word);
        window.gameState.teachingWord = '';
        window.gameState.teachCount = 0;
        
        spawnEffect('🎉');
        addLog(`【おしゃべり大成功】なんと!新しく「${word}」を おぼえた!`);
        showToast(`「${word}」を おぼえました!`);
        
        updateLearnedWordsUI();
        updateStatusUI();
        
        setTimeout(() => {
          saySomething(`${word}!!`);
        }, 800);
      } else {
        setTimeout(() => {
          const progressWord = word.substring(0, Math.ceil(word.length / 2)) + '…?';
          saySomething(progressWord);
        }, 800);
      }

      input.value = '';
    }

    function updateLearnedWordsUI() {
      const container = document.getElementById('learned-words-container');
      container.innerHTML = '';
      window.gameState.words.forEach(word => {
        const span = document.createElement('span');
        span.className = 'text-xs bg-white text-purple-600 px-2 py-1 rounded-md border border-purple-100 font-semibold shadow-sm';
        span.innerText = word;
        container.appendChild(span);
      });
    }

    // 1日進める
    function nextDay() {
      if (window.gameState.isSleeping) return;

      window.gameState.isSleeping = true;
      addLog(`よるに なりました。お部屋を くらくして 寝かせます…🌙`);
      
      const cage = document.getElementById('game-cage-frame');
      cage.style.filter = 'brightness(0.4)';
      showEmotion('💤');

      setTimeout(() => {
        window.gameState.day++;

        let weightGain = 0;
        if (window.gameState.food > 40) {
          if (window.gameState.weight < 35.0) {
            weightGain = 2.5 + Math.random() * 1.5; // ひな鳥の成長
          } else {
            weightGain = 0.1 + (Math.random() - 0.5) * 0.3; // 成鳥の安定
          }
        } else {
          weightGain = -1.0; 
          addLog('ちゅうい:ごはんが 足りなくて、少しやせてしまったようです…');
        }

        window.gameState.weight = Math.max(10.0, Math.min(45.0, window.gameState.weight + weightGain));
        window.gameState.food = Math.max(10, window.gameState.food - 35);
        window.gameState.water = Math.max(10, window.gameState.water - 40);

        window.gameState.isSleeping = false;
        cage.style.filter = 'brightness(1)';
        
        addLog(`あさになりました!${window.gameState.day}日目が はじまります。☀️`);
        
        if (window.gameState.weight >= 35.0 && window.gameState.day > 5) {
          addLog(`${window.gameState.bird.name}は すっかり おとなの インコになりました!`);
        }

        updateStatusUI();
        showEmotion('☀️');

        setTimeout(() => {
          const randWord = window.gameState.words[Math.floor(Math.random() * window.gameState.words.length)];
          saySomething(randWord + ' おはよ!');
        }, 1000);

      }, 3000); 
    }

    // ロードしたデータを画面に適用する
    window.applyLoadedGame = function() {
      // 画面切り替え(ケージ準備、お迎え画面だったらゲーム画面へ)
      stepCage.classList.add('hidden');
      stepChoose.classList.add('hidden');
      stepGame.classList.remove('hidden');

      initGameScreen();
    };

    // --- エフェクト・表示ヘルパー ---

    let speechTimeout;
    function saySomething(text) {
      const bubble = document.getElementById('bird-speech');
      bubble.innerText = text;
      bubble.classList.remove('opacity-0', 'translate-y-2');
      bubble.classList.add('opacity-100', 'translate-y-0');

      clearTimeout(speechTimeout);
      speechTimeout = setTimeout(() => {
        bubble.classList.remove('opacity-100', 'translate-y-0');
        bubble.classList.add('opacity-0', 'translate-y-2');
      }, 3000);
    }

    function triggerBirdAnimation(className) {
      const bird = document.getElementById('bird-character');
      bird.classList.remove('bird-idle');
      bird.classList.add(className);

      setTimeout(() => {
        bird.classList.remove(className);
        bird.classList.add('bird-idle');
      }, 1500);
    }

    let emotionTimeout;
    function showEmotion(emoji) {
      const emo = document.getElementById('bird-emotion');
      emo.innerText = emoji;
      emo.classList.remove('opacity-0');
      emo.classList.add('opacity-100');

      clearTimeout(emotionTimeout);
      emotionTimeout = setTimeout(() => {
        emo.classList.remove('opacity-100');
        emo.classList.add('opacity-0');
      }, 2000);
    }

    function spawnEffect(emoji) {
      const layer = document.getElementById('effect-layer');
      const particle = document.createElement('div');
      particle.className = 'effect-particle text-xl font-bold';
      
      const randomX = 40 + (Math.random() * 20);
      const randomY = 60 + (Math.random() * 10);
      
      particle.style.left = `${randomX}%`;
      particle.style.top = `${randomY}%`;
      particle.innerText = emoji;

      layer.appendChild(particle);

      setTimeout(() => {
        particle.remove();
      }, 1000);
    }

    window.addLog = function(text) {
      const log = document.getElementById('game-log');
      const div = document.createElement('div');
      div.innerText = `● ${text}`;
      log.appendChild(div);
      log.scrollTop = log.scrollHeight;
    }

    window.showToast = function(msg) {
      const toast = document.getElementById('toast-message');
      toast.innerText = msg;
      toast.classList.remove('opacity-0');
      toast.classList.add('opacity-100');
      setTimeout(() => {
        toast.classList.remove('opacity-100');
        toast.classList.add('opacity-0');
      }, 2500);
    }
  </script>
</body>
</html>
✨ ピックアップ

インコ育成ゲーム

by kizu

インコを育てるゲーム

🤖 使用したAI
Gemini
👁 34 回閲覧
📅 投稿:2026年6月24日 🔄 更新:2026年8月13日
応援スタンプを押してみよう!