GASとChatGPTで簡単なゲームを作ってみる

はじめに
-
[CYBIRD Advent Calendar 2024](https://qiita.com/advent-calendar/2024/cybird) 1日目担当の @cy_hinano_imai です。
サイバードには2023年に新卒入社し、現在はイケメンシリーズの１タイトルでクライアント兼サーバーエンジニアとして開発/運用を担当しています。
今年も参加しようと準備していたので、すごい勢いで1日目を取りにきました。:dove::heart_exclamation:


こんな人におすすめ
-
・GASをよく触っている
・ブラウザベースの簡単なゲームを作りたい
・JavaScript・HTML・CSSにサクッと触れてみたい


概要
-
最近GASを触る機会が増えたので、GASでゲームも作れるのかな？と思ってChatGPTに聞いてみました。
(ChatGPT 4o mini)
![スクリーンショット 2024-11-22 15.12.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626087/34b2a8a9-d1ef-78ad-2c14-9d41bf79994c.png)
![スクリーンショット 2024-11-22 15.12.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626087/5572d460-259f-08a2-5504-89f01c3fb806.png)
こんな感じの返答が返ってきました。シンプルなゲームであれば作れるみたいです。

そこで、ChatGPTに「GASでブラウザベースの簡単なゲームを作りたい」と聞いてみると、作成に必要なコードを全部出力してくれます。なんて便利なんだろう。



作成してみる
-

以下は、ある程度端を折っていますが、ほぼChatGPTからのコピペです。

HTML ファイルの例：
```html:index.html
<!DOCTYPE html>
<html>
<head>
  <title>クリックゲーム</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
    }
    #score {
      font-size: 30px;
      margin-bottom: 20px;
    }
    #clickButton {
      padding: 10px 20px;
      font-size: 20px;
    }
  </style>
</head>
<body>
  <h1>クリックして点数を増やそう！</h1>
  <div id="score">スコア: 0</div>
  <button id="clickButton">クリック！</button>

  <script>
    var score = 0;
    var scoreElement = document.getElementById('score');
    var button = document.getElementById('clickButton');

    button.onclick = function() {
      score++;
      scoreElement.innerText = "スコア: " + score;
    };
  </script>
</body>
</html>
```

Google Apps Script のコード例：
```javascript:javascript
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}
```

以上をGASで作成し、動作確認(WEBアプリとして公開)までしてみます。

WEBアプリとして公開してみる
-

* GASのエディタの上部にある「デプロイ」ボタンをクリックして、「新しいデプロイ」をクリック
* 「種類の選択」から「ウェブアプリ」を選び、右下のデプロイボタンをクリック
* ウェブアプリのURLが生成されると思うので、そのURLにアクセスすると、作成したゲームがブラウザに表示される

今回はこんな感じ。
![スクリーンショット 2024-11-22 16.00.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626087/54af8bbe-fe09-4495-25dc-1348e0bf74af.png)
時間制限もまだついていないので、ボタンをクリックする度にスコアが増えます。ゲームとはいえど、本当に最低限の要素しか入っていません。

これで完成！とは流石に言えないので、時間制限だけでも追加してみましょう。

時間制限付きにしてみる
-
今度はChatGPTに「GASで時間制限付きのブラウザクリックゲームを作ってください」と注文してみます。

以下も、ある程度端を折っていますが、ほぼChatGPTからのコピペです。

HTML ファイルの例：
```html:index.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>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
      margin-top: 50px;
    }
    #game-container {
      margin-top: 20px;
    }
    #click-button {
      padding: 20px 50px;
      font-size: 20px;
      cursor: pointer;
      border: none;
      background-color: #4CAF50;
      color: white;
      border-radius: 5px;
    }
    #score {
      font-size: 24px;
      margin-top: 20px;
    }
    #timer {
      font-size: 24px;
      margin-top: 20px;
    }
    #end-message {
      font-size: 30px;
      color: red;
      margin-top: 30px;
    }
  </style>
</head>
<body>
  <h1>クリックゲーム</h1>
  <p id="timer">時間制限: 10秒</p>
  <div id="game-container">
    <button id="click-button" onclick="handleClick()">クリック</button>
  </div>
  <p id="score">スコア: 0</p>
  <p id="end-message" style="display: none;">ゲーム終了！</p>

  <script>
    let score = 0;
    let timer = 10;
    let timerInterval;
    let gameEnded = false;

    // タイマーのカウントダウン
    function startTimer() {
      timerInterval = setInterval(function() {
        timer--;
        document.getElementById('timer').innerText = "時間制限: " + timer + "秒";
        if (timer <= 0) {
          clearInterval(timerInterval);
          endGame();
        }
      }, 1000);
    }

    // ゲームの開始
    function startGame() {
      gameEnded = false;
      score = 0;
      timer = 10;
      document.getElementById('score').innerText = "スコア: " + score;
      document.getElementById('end-message').style.display = "none";
      document.getElementById('click-button').disabled = false;
      startTimer();
    }

    // クリック処理
    function handleClick() {
      if (gameEnded) return;
      score++;
      document.getElementById('score').innerText = "スコア: " + score;
    }

    // ゲーム終了
    function endGame() {
      gameEnded = true;
      document.getElementById('click-button').disabled = true;
      document.getElementById('end-message').style.display = "block";
    }

    // ページ読み込み時にゲームを開始
    window.onload = function() {
      startGame();
    }
  </script>
</body>
</html>
```

Google Apps Script のコード例：
```javascript:javascript
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}
```

以上です。こちらも動作確認(WEBアプリとして公開)までしてみます。

WEBアプリとして公開してみる
-

* GASのエディタの上部にある「デプロイ」ボタンをクリックして、「新しいデプロイ」をクリック
* 「種類の選択」から「ウェブアプリ」を選び、右下のデプロイボタンをクリック
* ウェブアプリのURLが生成されると思うので、そのURLにアクセスすると、作成したゲームがブラウザに表示される

今回はこんな感じ。
![スクリーンショット 2024-11-28 12.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626087/9e0463b6-c39a-5e7b-143f-b7692b4359a5.png)

ブラウザを開いた時点でゲームが開始し、制限時間を過ぎると下に「ゲーム終了！」と出て、ボタンもクリックできないようになりました。

初回よりはいい感じです。ついでにindex.htmlにどこが何の処理なのか、コメント文もつくようになりました。結構ありがたいです。

メリットとデメリット
-
メリット
・サーバーやインフラを構築する必要がない
・デプロイが簡単
・ゲームのスコアボードをスプレッドシートに保存したりできる

デメリット
・パフォーマンスが制限される
・高頻度の更新が必要なゲームには向かない(GASには1日あたりの実行時間やAPIの呼び出し回数に制限があるため)
・特に動的なゲームグラフィックには不向き

まとめ
-

私はゲームのアイデアを出すのが苦手なので、ChatGPTにはアイデア出しや基盤の作成をやってもらっています。
「土台だけ作ってもらって、後付けしていく」という流れを気に入っていまして、気が向いた時にバージョンアップさせてみるというのが、エンジニアとしての息抜きにちょうど良いです。
GASなら手間をかけることなく動作の確認もできますし、ChatGPTがサンプルコードの提供もしてくれる(しかもコメントつき！)ので、初めてHTMLを触る人の勉強や、苦手意識の払拭に良いかもしれませんね。:santa:

最後に
-
[CYBIRD Advent Calendar 2024](https://qiita.com/advent-calendar/2024/cybird) 2日目は @chikako_ikeda さんの「Android15の録画検出機能を試した話」です！
お楽しみに！