AI活用

【AI×育児】赤ちゃんが笑顔になるミニゲームを2つ作ってみた

shota

⬛︎はじめに

「子どもと遊ぶ時間をもっと楽しくしたい」

そんな気持ちから今回は、
“赤ちゃんが思わず笑顔になるミニゲーム” をAIを使って自作してみました。

実際に作った2つのゲームを紹介します。

  • シャボン玉割りゲーム
  • いないいないばぁゲーム

どちらも スマホ1台で遊べる シンプルなゲームで、
難しい操作もありません。

赤ちゃんと一緒に笑いながら遊べるようにデザインしています。


⬛︎ゲーム①:シャボン玉割りゲーム

まず最初に作ったのが「シャボン玉割りゲーム」です。

シャボン玉割りゲーム
シャボン玉割りゲーム
シャボン玉割りゲーム

画面の中にふわ〜っとシャボン玉が浮かび上がり、
タップすると “ポン!” と割れて音が鳴る シンプルなミニゲームです。

● こだわったポイント

  • 赤ちゃんが押しやすいように 大きめサイズの泡
  • 高すぎない控えめな 効果音
  • 時々出てくる “色違いシャボン玉”

赤ちゃんって「繰り返し」「音が鳴るもの」が本当に大好きなようで、
ただタップするだけなのにニコニコしてくれます。

しかも親も「ぱんぱん割れる感じが地味に気持ちいい」ので、
ついついつい一緒に遊んでしまいます。


⬛︎ゲーム②:いないいないばぁゲーム

次に作ったのが赤ちゃんの永遠の定番遊びである
「いないいないばぁ」をスマホバージョンにしたゲームです。

いないいないばぁゲーム
いないいないばぁゲーム
いないいないばぁゲーム

画面をタップすると…

  • 手で顔を隠す → 「いないいない…」
  • 手が下がって顔が出る → 「ばぁ!!」

という動きに切り替わります。

● 赤ちゃんが喜ぶための工夫

  • 画面をタップするだけの超シンプル操作
  • 大きめのフォント
  • かわいくて少し高めの 「ばぁ!」の効果音

これが思った以上に良くて、
赤ちゃんが画面をタップした瞬間に「ばぁ!!」と出るので、
リアルで遊んでるみたいに楽しんでくれます。


⬛︎作ってみて感じたこと

● AI時代の育児はもっと“遊びの幅”が広がる

今回のゲームはどちらも ChatGPTでHTML+CSS+JSを生成してもらい、貼り付けただけ で動くもので作成しました。

育児をしていると余裕がない日もあるけれど、
スマホ1つでこんなふうに小さな遊び場を作れるのは、
AI時代ならではだと思います。

● 思ったことが形になる

赤ちゃん向けのアプリは世の中に大量にあるけれど、
その中のどれとも違う自分だけのオリジナル作品が作れるのは
とてもすごいと思います。

そして子どもが、

  • 何度も触る
  • 声を上げて笑う
  • 手を伸ばす
  • 親の顔を見てもう一回の催促をする

このように喜んでくれると嬉しさは倍増です。
子どもの笑顔が何よりも宝物です。


⬛︎今回作ったコード

今回作ったゲームのHTMLコードです。
そのままでも、アレンジしてみてもOKです!

ぜひ活用してみて下さい。

⚫︎シャボン玉割りゲーム

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0" />
  <title>シャボン玉割りゲーム</title>
  <style>
    /* ページ全体のスクロールはさせる */
    html, body {
      margin: 0;
      padding: 0;
      font-family: "Helvetica Neue", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
    }

    /* 記事内に収まる箱型ゲームエリア */
    .game-wrapper {
      max-width: 640px;
      margin: 0 auto 32px auto; /* 中央寄せ+下に余白 */
      padding: 8px;
      box-sizing: border-box;
    }

    .game-title {
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 6px;
      text-align: center;
      color: #ff7aa2;
    }

    .game-container {
      position: relative;
      width: 100%;
      height: 480px; /* 見やすい固定高さ(必要ならここを変えてOK) */
      overflow: hidden; /* ゲームエリア内だけはみ出し防止 */
      background: linear-gradient(to bottom, #aee1ff, #ffffff);
      border-radius: 16px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.08);
      touch-action: pan-y; /* 縦スクロールはOK、横パンは抑えめ */
    }

    .header {
      position: absolute;
      top: 10px;
      left: 50%;
      transform: translateX(-50%);
      text-align: center;
      z-index: 10;
      padding: 6px 12px;
      background: rgba(255, 255, 255, 0.8);
      border-radius: 999px;
      box-shadow: 0 2px 6px rgba(0,0,0,0.08);
      box-sizing: border-box;
      max-width: 94%;
    }

    #score {
      font-size: 16px;
      font-weight: bold;
      color: #ff7aa2;
      white-space: nowrap;
    }

    #startButton {
      margin-top: 4px;
      padding: 6px 16px;
      font-size: 14px;
      border-radius: 999px;
      border: none;
      background: #ffb6d9;
      color: #ffffff;
      font-weight: bold;
      cursor: pointer;
      box-shadow: 0 2px 4px rgba(0,0,0,0.15);
    }

    #startButton:active {
      transform: translateY(1px);
      box-shadow: 0 1px 3px rgba(0,0,0,0.15);
    }

    .bubble {
      position: absolute;
      border-radius: 50%;
      box-shadow: 0 0 10px rgba(255,255,255,0.9);
    }

    /* ふつうのシャボン玉 */
    .bubble-normal {
      background: radial-gradient(circle at 30% 30%,
        rgba(255,255,255,0.95),
        rgba(173,216,230,0.75)
      );
    }

    /* レアなキラキラシャボン玉(色違い) */
    .bubble-rare {
      background: radial-gradient(circle at 30% 30%,
        rgba(255,255,255,0.95),
        rgba(255,192,203,0.85)
      );
      box-shadow: 0 0 16px rgba(255,192,203,0.9);
    }

    @keyframes float-up {
      from {
        bottom: -150px;
        opacity: 0.9;
        transform: scale(0.9);
      }
      to {
        bottom: 100%;
        opacity: 0;
        transform: scale(1.1);
      }
    }

    .pop {
      animation-name: pop;
      animation-duration: 0.25s;
      animation-timing-function: ease-out;
      animation-fill-mode: forwards;
    }

    @keyframes pop {
      from {
        transform: scale(1);
        opacity: 1;
      }
      to {
        transform: scale(1.4);
        opacity: 0;
      }
    }

    .message {
      position: absolute;
      pointer-events: none;
      font-size: 22px;
      font-weight: bold;
      color: #ff7aa2;
      text-shadow: 0 0 4px rgba(255,255,255,0.9);
      animation: message-up 0.6s ease-out forwards;
      z-index: 20;
    }

    @keyframes message-up {
      from {
        transform: translate(-50%, 0);
        opacity: 1;
      }
      to {
        transform: translate(-50%, -40px);
        opacity: 0;
      }
    }

    .hint {
      margin-top: 6px;
      font-size: 12px;
      color: rgba(0,0,0,0.45);
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="game-wrapper">
    <div class="game-title">🫧 ぽんぽんシャボン玉ゲーム 🫧</div>
    <div class="game-container" id="game">
      <div class="header">
        <div id="score">ぽんした回数:0</div>
        <button id="startButton" type="button">ゲームスタート</button>
      </div>
    </div>
    <div class="hint">画面の中のシャボン玉をタップして「ポン!」✨</div>
  </div>

  <script>
    const game = document.getElementById("game");
    const scoreEl = document.getElementById("score");
    const startButton = document.getElementById("startButton");

    let score = 0;
    let playing = false;
    let bubbleInterval = null;

    const normalMessages = ["ポン!", "いいね!", "すごーい!", "パチパチ!"];
    const rareMessages = ["キラポン!", "やったー!", "キラキラ★"];

    function updateScore() {
      scoreEl.textContent = "ぽんした回数:" + score;
    }

    function clearBubbles() {
      const bubbles = document.querySelectorAll(".bubble");
      bubbles.forEach(b => b.remove());
    }

    function startGame() {
      playing = true;
      score = 0;
      updateScore();
      clearBubbles();

      startButton.textContent = "もっとあそぶ";
      startButton.disabled = true;
      setTimeout(() => { startButton.disabled = false; }, 500);

      if (bubbleInterval) {
        clearInterval(bubbleInterval);
      }

      createBubble();
      bubbleInterval = setInterval(createBubble, 900);
    }

    function createBubble() {
      if (!playing) return;

      const bubble = document.createElement("div");
      bubble.classList.add("bubble");

      // たまにレアシャボン玉(約 20% の確率)
      const isRare = Math.random() < 0.2;
      if (isRare) {
        bubble.classList.add("bubble-rare");
        bubble.dataset.rare = "true";
      } else {
        bubble.classList.add("bubble-normal");
      }

      // 大きさ(ベビーでも押しやすいサイズ)
      const size = Math.random() * 50 + 70; // 70〜120px
      bubble.style.width = size + "px";
      bubble.style.height = size + "px";

      // 横位置(ゲームエリア内で完結)
      const maxX = game.clientWidth - size - 10;
      const x = Math.max(0, Math.random() * maxX);
      bubble.style.left = x + "px";

      // 下から出す
      bubble.style.bottom = "-150px";

      // 浮かぶスピード
      const duration = 6 + Math.random() * 4; // 6〜10秒
      bubble.style.animation = "float-up " + duration + "s linear forwards";

      // タップで割る
      bubble.addEventListener("pointerdown", (e) => {
        // e.preventDefault(); ← これを外して縦スクロールを邪魔しにくくする
        popBubble(bubble, e.clientX, e.clientY);
      });

      // 画面外まで行ったら削除
      bubble.addEventListener("animationend", () => {
        bubble.remove();
      });

      game.appendChild(bubble);
    }

    function popBubble(bubble, x, y) {
      if (bubble.dataset.popped === "true") return;
      bubble.dataset.popped = "true";

      score++;
      updateScore();
      showMessage(bubble, x, y);
      playPopSound();

      bubble.style.animation = "none";
      void bubble.offsetWidth; // 再描画トリガー
      bubble.classList.add("pop");

      setTimeout(() => {
        bubble.remove();
      }, 250);
    }

    function showMessage(bubble, x, y) {
      const msg = document.createElement("div");
      msg.className = "message";

      const isRare = bubble.dataset.rare === "true";
      if (isRare) {
        msg.textContent = rareMessages[Math.floor(Math.random() * rareMessages.length)];
      } else {
        msg.textContent = normalMessages[Math.floor(Math.random() * normalMessages.length)];
      }

      msg.style.left = x + "px";
      msg.style.top = y + "px";

      game.appendChild(msg);

      setTimeout(() => {
        msg.remove();
      }, 600);
    }

    // 「ポン」音
    let audioCtx = null;
    function playPopSound() {
      const AudioContext = window.AudioContext || window.webkitAudioContext;
      if (!AudioContext) return;

      if (!audioCtx) {
        audioCtx = new AudioContext();
      }

      const now = audioCtx.currentTime;
      const osc = audioCtx.createOscillator();
      const gain = audioCtx.createGain();

      osc.type = "sine";
      osc.frequency.setValueAtTime(900, now);
      gain.gain.setValueAtTime(0.2, now);
      gain.gain.exponentialRampToValueAtTime(0.001, now + 0.2);

      osc.connect(gain);
      gain.connect(audioCtx.destination);

      osc.start(now);
      osc.stop(now + 0.2);
    }

    startButton.addEventListener("click", startGame);
  </script>
</body>
</html>

⚫︎いないいないばぁゲーム

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0" />
  <title>いないいないばぁゲーム</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      font-family: "Helvetica Neue", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
    }

    .peekaboo-wrapper {
      max-width: 640px;
      margin: 0 auto 32px auto;
      padding: 8px;
      box-sizing: border-box;
    }

    .peekaboo-title {
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 6px;
      text-align: center;
      color: #ff7aa2;
    }

    .peekaboo-container {
      position: relative;
      width: 100%;
      height: 420px;
      overflow: hidden;
      background: linear-gradient(to bottom, #ffe4f1, #ffffff);
      border-radius: 16px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.08);
      touch-action: pan-y;
    }

    /* 顔エリア */
    .peekaboo-stage {
      position: absolute;
      top: 60px;
      left: 50%;
      transform: translateX(-50%);
      width: 80%;
      height: 320px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    /* 顔の基本デザイン */
    .peekaboo-face {
      position: relative;
      width: 210px;
      height: 210px;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 30%, #fffaf5, #ffd5b8);
      box-shadow: 0 6px 14px rgba(0,0,0,0.12);
      display: flex;
      align-items: center;
      justify-content: center;
      transition: transform 0.2s ease-out;
    }

    .eyes {
      position: absolute;
      top: 70px;
      left: 50%;
      transform: translateX(-50%);
      width: 120px;
      display: flex;
      justify-content: space-between;
    }

    .eye {
      width: 18px;
      height: 24px;
      border-radius: 50%;
      background: #333;
    }

    .mouth {
      position: absolute;
      bottom: 60px;
      left: 50%;
      transform: translateX(-50%);
      width: 70px;
      height: 40px;
      border-radius: 0 0 70px 70px;
      border-bottom: 6px solid #ff6b81;
    }

    .cheek {
      position: absolute;
      top: 115px;
      width: 32px;
      height: 18px;
      border-radius: 50%;
      background: rgba(255,153,153,0.5);
    }
    .cheek-left { left: 45px; }
    .cheek-right { right: 45px; }

    /* 手 */
    .hands {
      position: absolute;
      bottom: 40px;
      left: 50%;
      transform: translateX(-50%);
      width: 160px;
      display: flex;
      justify-content: space-between;
      transition: transform .25s ease-out;
    }

    .hand {
      width: 70px;
      height: 70px;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 30%, #fff7f0, #ffd1b8);
      box-shadow: 0 3px 8px rgba(0,0,0,0.12);
    }

    /* テキスト(いないいない / ばぁ) */
    .peekaboo-text {
      position: absolute;
      top: -10px;
      left: 50%;
      transform: translateX(-50%);
      font-size: 24px;
      font-weight: bold;
      color: #ff7aa2;
      text-shadow: 0 0 4px rgba(255,255,255,0.9);
      white-space: nowrap;
      transition: opacity 0.2s ease-out;
    }

    .text-hidden { opacity: 1; }
    .text-shown { opacity: 0; }

    .state-shown .text-hidden { opacity: 0; }
    .state-shown .text-shown { opacity: 1; }

    /* 手の位置 */
    .state-hidden .hands { transform: translate(-50%, -40px); }
    .state-shown  .hands { transform: translate(-50%, 40px); }

  </style>
</head>
<body>
  <div class="peekaboo-wrapper">
    <div class="peekaboo-title">🙈 いないいないばぁゲーム 🙉</div>

    <div class="peekaboo-container" id="peekaboo-game">
      <div class="peekaboo-stage state-hidden" id="peekaboo-stage">

        <!-- テキスト -->
        <div class="peekaboo-text text-hidden">いないいない…</div>
        <div class="peekaboo-text text-shown">ばぁ!!</div>

        <!-- 顔 -->
        <div class="peekaboo-face">
          <div class="eyes">
            <div class="eye"></div>
            <div class="eye"></div>
          </div>
          <div class="mouth"></div>
          <div class="cheek cheek-left"></div>
          <div class="cheek cheek-right"></div>

          <!-- 手 -->
          <div class="hands">
            <div class="hand"></div>
            <div class="hand"></div>
          </div>
        </div>
      </div>
    </div>

    <div style="margin-top:6px;font-size:12px;text-align:center;color:rgba(0,0,0,0.45);">
      画面をタップすると「いないいない… / ばぁ!!」が切り替わるよ 👶✨
    </div>
  </div>

  <script>
    const stage = document.getElementById("peekaboo-stage");
    const gameBox = document.getElementById("peekaboo-game");

    let isShown = false; // false = 隠れ, true = ばぁ

    function setState(hidden) {
      if (hidden) {
        stage.classList.remove("state-shown");
        stage.classList.add("state-hidden");
        isShown = false;
      } else {
        stage.classList.remove("state-hidden");
        stage.classList.add("state-shown");
        isShown = true;
      }
    }

    function togglePeekaboo() {
      // いない → ばぁ
      if (!isShown) {
        setState(false);
        playPeekSound();
      }
      // ばぁ → いない
      else {
        setState(true);
      }
    }

    // シンプルな「ばぁ!」効果音
    let pbAudioCtx = null;
    function playPeekSound() {
      const AudioContext = window.AudioContext || window.webkitAudioContext;
      if (!AudioContext) return;
      if (!pbAudioCtx) pbAudioCtx = new AudioContext();

      const now = pbAudioCtx.currentTime;
      const osc = pbAudioCtx.createOscillator();
      const gain = pbAudioCtx.createGain();

      osc.type = "triangle";
      osc.frequency.setValueAtTime(600, now);
      osc.frequency.exponentialRampToValueAtTime(900, now + 0.18);
      gain.gain.setValueAtTime(0.25, now);
      gain.gain.exponentialRampToValueAtTime(0.001, now + 0.2);

      osc.connect(gain);
      gain.connect(pbAudioCtx.destination);

      osc.start(now);
      osc.stop(now + 0.25);
    }

    // 画面全体で操作
    gameBox.addEventListener("pointerdown", () => {
      togglePeekaboo();
    });
  </script>
</body>
</html>

⬛︎おわりに

プログラミングの技術がある人もない人も、
AIを使えば“うちの子のためだけの遊び” をすぐに形にできます

確かに育児は大変です。

しかし、
こういう小さな「遊びの魔法」を足せると、
毎日がちょっと楽しくなります。

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

プロフィール
shota
shota
会社員 AI活用について日々奮闘中
こんにちは!shotaと申します。 ブログを見ていただきありがとうございます。 私自身が経験したこと、悩んで解決したことなどを記事にしております。特にAI活用について学び自分の時間をどのようにして増やすか?を追求しており、日々奮闘中です。私が学んだこと、考えていることを記事にしていきます。そんな記事が皆様のお役に立てれば光栄です。ぜひ、気になる記事があれば片っ端から読んでみてください!きっと明日の希望になるはず!!
記事URLをコピーしました