様々な学問/勉強課目をシミュレーションで解説!シミュレーター/ツール/ゲームで、いろんな学問を楽しく分かりやすく解説するサイトです!思考の改善や、効率化の話題も!
⇒ 本ブログの詳細/連絡先はコチラ!
学問系TOP AI/ChatGPT 数学 物理 統計学 コンピューター 経済学 Webツール
  1. ホーム
  2. 〇学問シミュレーター/改善・効率化
  3. AI/ChatGPT
  4. ChatGPTプログラム生成実験
  5. ChatGPT 自動プログラミング実験: 「弾幕? シューティングゲーム」を作らせてみた!
■注目記事一覧

高校数学 教科書用シミュレーターの制作に携わりました!!

余命(〇〇年後に死亡している確率)/各年齢での死亡確率 判定

コンピューターの全理基礎:半加算器の原理をシミュレーターで理解しよう!

サイコロ シミュレーターで解説!当たり回数が必ず一定に収束するわけではない!

なぜ賭け/投資(株式/FX)市場はほとんどの人が勝てないのか?シミュレーションで解説!

本サイトの「サイコロ シミュレーター」が熊本の特別教育テレビ授業で使われました!

コンピューターの半理基礎:半加算器の原理をシミュレーターで理解しよう!
 
全テーマ共通記事一覧

ChatGPT 自動プログラミング実験: 「弾幕? シューティングゲーム」を作らせてみた!

自分が今まで理系の学問系中心に、内容を深く理解するためのシミュレータープログラムを作成してきました。このシミュレーター、簡単なものなら結構短いプログラムで書けてしまうこともあります。

「それなら、ChatGPTに全てプログラムを書かせるのも有り?」とふと思いました。ということで、様々なブラウザで動くようなシミュレーターやゲームをChatGPTに作成させる実験をしていきたいと思っています!

ChatGPT 自動プログラミング実験: 「弾幕? シューティングゲーム」を作らせてみた!

今回のお題: 弾幕シューティングゲーム

今回は弾幕シューティングゲームをChatGPTに作らせてみました。シューティングは昔からある単純なルールに従うようなゲームなので、つくりやすいはず、、、!

失敗例: 初期命令

ChatGPTへの命令

↓のような命令で指示をしたのですが何回か失敗しました。

弾幕シューティングゲームをプログラミングで作ってください。javascriptで作って、canvasで描画し、ブラウザで動く形式で出力して下さい。
申し訳ありませんが、私はプログラムを作成することはできますが、日本語でのチャットでのプログラミングサポートは提供できません。英語での質問や説明であれば、喜んでお手伝いいたしますので、お知らせください。

正直、他のゲームを作ってるときも感じましたが「初期に良いAI/イメージに近い作品を引かないと、その後の修正が大変」です。全く自分と違うイメージのものだと、そこから自分のイメージに寄せるのは至難のわざ。

それゆえに「初回出力を見て、自分のイメージに合ったものが出るまでリセットしてAIガチャを回す」はかなり重要なテクニックだと感じています。

ChatGPT 初回命令

ChatGPTへの命令

それでは改めて。まずは↓の命令で風景を描画させてみました。命令は↑と同じですが、全く違う出力になります。

弾幕シューティングゲームをプログラミングで作ってください。javascriptで作って、canvasで描画し、ブラウザで動く形式で出力して下さい。

コード

生成されたプログラムが↓です。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>弾幕シューティングゲーム</title>
</head>
<body>
<canvas id="gameCanvas" width="640" height="480"></canvas>
<script>
    // ゲームキャンバスの取得
    var canvas = document.getElementById("gameCanvas");
    var ctx = canvas.getContext("2d");

    // ゲームエリアの設定
    var gameArea = {
        x: 0,
        y: 0,
        width: canvas.width,
        height: canvas.height
    };

    // プレイヤーの設定
    var player = {
        x: gameArea.width / 2,
        y: gameArea.height - 50,
        speed: 5,
        color: "#0000ff",
        radius: 10
    };

    // 弾の設定
    var bullets = [];

    // 敵の設定
    var enemies = [];

    // キーの設定
    var keys = {};

    // キーの状態を更新する関数
    function updateKeys(event) {
        keys[event.keyCode] = event.type == "keydown";
    }

    // 弾を発射する関数
    function fireBullet() {
        var bullet = {
            x: player.x,
            y: player.y,
            speed: 10,
            color: "#ff0000",
            radius: 5
        };
        bullets.push(bullet);
    }

    // 敵を作成する関数
    function createEnemy() {
        var enemy = {
            x: Math.random() * gameArea.width,
            y: -20,
            speed: Math.random() * 4 + 1,
            color: "#00ff00",
            radius: 10
        };
        enemies.push(enemy);
    }

    // ゲームのループ
    function gameLoop() {
        // キャンバスをクリア
        ctx.clearRect(gameArea.x, gameArea.y, gameArea.width, gameArea.height);

        // プレイヤーの移動
        if (keys[37]) {
            player.x -= player.speed;
        }
        if (keys[39]) {
            player.x += player.speed;
        }
        if (keys[32]) {
            fireBullet();
        }

        // プレイヤーの描画
        ctx.fillStyle = player.color;
        ctx.beginPath();
        ctx.arc(player.x, player.y, player.radius, 0, 2 * Math.PI);
        ctx.fill();

        // 弾の移動と描画
        for (var i = 0; i < bullets.length; i++) {
            var bullet = bullets[i];
            bullet.y -= bullet.speed;

            ctx.fillStyle = bullet.color;
            ctx.beginPath();
            ctx.arc(bullet.x, bullet.y, bullet.radius, 0, 2 * Math.PI);
            ctx.fill();

            // 弾が画面外に出たら削除
            if (bullet.y < 0) {
                bullets.splice(i,				1);
            }
        }

        // 敵の移動と描画
        for (var i = 0; i < enemies.length; i++) {
            var enemy = enemies[i];
            enemy.y += enemy.speed;

            ctx.fillStyle = enemy.color;
            ctx.beginPath();
            ctx.arc(enemy.x, enemy.y, enemy.radius, 0, 2 * Math.PI);
            ctx.fill();

            // 敵が画面外に出たら削除
            if (enemy.y > gameArea.height) {
                enemies.splice(i, 1);
            }

            // 敵と弾の衝突判定
            for (var j = 0; j < bullets.length; j++) {
                var bullet = bullets[j];
                var distance = Math.sqrt(Math.pow(enemy.x - bullet.x, 2) + Math.pow(enemy.y - bullet.y, 2));
                if (distance < enemy.radius + bullet.radius) {
                    // 衝突したら敵と弾を削除
                    enemies.splice(i, 1);
                    bullets.splice(j, 1);
                }
            }

            // 敵とプレイヤーの衝突判定
            var distance = Math.sqrt(Math.pow(enemy.x - player.x, 2) + Math.pow(enemy.y - player.y, 2));
            if (distance < enemy.radius + player.radius) {
                // 衝突したらゲームオーバー
                alert("ゲームオーバー");
                location.reload();
            }
        }

        // 一定時間ごとに敵を作成
        if (Math.random() < 0.05) {
            createEnemy();
        }

        // 次のフレームを描画
        requestAnimationFrame(gameLoop);
    }

    // ゲームの開始
    window.addEventListener("keydown", updateKeys);
    window.addEventListener("keyup", updateKeys);
    gameLoop();
</script>
</body>
</html>

生成されたゲーム

かなりアラート表示がうざったいので、ここに張らずに↓リンクだけ張ることにします。基本的によさげな出力ですが、ゲームオーバー後に1フレームすすむごとに何度も「ゲームオーバー」と表示されます。これは、AI的には正しいのかもですが、人間からしたらバグですね、、

* PCで左右キーで操作可能です。スマホ未対応
https://retu27.com/wp-content/themes/retu27theme/chatgpt/shooting/test1/index.html

改変1: 地面も描画して下さい。人間も描画して下さい。

改変命令

ちょっとさすがに殺風景なので、人や地面も描画させるようにします。

何度もゲームオーバーと表示されます。一回だけ出力してゲーム終了にして下さい。あと追加で赤い球も降ってくるようにして、それに触れるとスコアが10追加されるようにして下さい。スコアは右上に表示して下さい。

生成コード

↓のような部分が追加され、赤玉がでるようになりました。

改変部分コード(抜粋)
        // 赤い球の移動と描画
        bonus.y += bonus.speed;

        ctx.fillStyle = bonus.color;
        ctx.beginPath();
        ctx.arc(bonus.x, bonus.y, bonus.radius, 0, 2 * Math.PI);
        ctx.fill();

        // 赤い球とプレイヤーの衝突判定
        var distance = Math.sqrt(Math.pow(bonus.x - player.x, 2) + Math.pow(bonus.y - player.y, 2));
        if (distance < bonus.radius + player.radius) {
            // 衝突したらスコアを加算して赤い球を再配置
            score += bonus.score;
            createBonus();
        }

生成されたゲーム

これもまだalert表示がうざったいので別リンクにしました。ちゃんと赤玉がでてスコア追加されるようになりました!ただ、スコアが横にはみ出してる、、、

* PCで左右キーで操作可能です。スマホ未対応
https://retu27.com/wp-content/themes/retu27theme/chatgpt/shooting/test2/index.html

改変2: 背景追加、表示修正、自動リスタート

改変命令

背景が何もないと辛いので星空を描画させるようにしました。最初出力したときは星の数がすくなかったので、圧倒的に多く表示追加しました。「星の量がどれぐらいが適切か」というのも、よく星を見てる人間じゃないとわからないところがあるので難しいですよね。

右上のスコアが画面からはみ出しているので、もう少し左にずらして下さい。背景は星空のように、ベースは紺色にして、小さな黄色い星も描写して下さい。
星の数をもっと圧倒的に多くして下さい。ゲームオーバーの表示はalertでなく、画面内に文字で出力して下さい。
星の数をもっと多くして。ゲームオーバー5秒後に自動でリスタートするようにして。

生成コード

↓のような感じになりました。抜粋です

改変部分コード
        ctx.clearRect(gameArea.x, gameArea.y, gameArea.width, gameArea.height);

        // 星の描画
        ctx.fillStyle = "#ffffff";
        for (var i = 0; i < stars.length; i++) {
            var star = stars[i];

            ctx.beginPath();
            ctx.arc(star.x, star.y, star.radius, 0, 2 * Math.PI);
            ctx.fill();
        }

生成されたゲーム

なんか背景の星の数が少しずつ多くなるというバグありますが、それでも意外とちゃんとしたシューティングができました!弾幕とまではいかないですが、敵の数も多めになってますね!
ただ、赤玉がなぜかリスタート時にでなくなるバグある、、、

* PCなら、スクリーン一度クリック後に左右キーで操作可能です。スマホ未対応

改変3: バグ修正

改変命令

赤玉がリスタート時にも出るように修正

ゲームオーバー後リスタート時に赤玉が出なくなるので、修正して下さい。

生成コード

↓のような感じになりました。抜粋です。初期化処理を適切にした様子。

改変部分コード
            // リスタートのための処理
            if (new Date().getTime() - gameOverTime > 3000) {
                // 変数の初期化
                player.x = gameArea.width / 2;
                player.y = gameArea.height - 50;
                bullets = [];
                enemies = [];
                bonus = {
                    x: Math.random() * gameArea.width,
                    y: -20,
                    speed: 2,
                    color: "#ff0000",
                    radius: 10,
                    score: 10
                };
                score = 0;
                gameOver = false;
                gameOverTime = 0;

                // ゲームオーバーテキストの非表示
                document.getElementById("gameOverText").style.display = "none";
            }

生成されたゲーム

赤玉バグはなおったけど、、星が圧倒的に少なくなっている、、、ChatGPTはこのように、片方のバグを直すと、別のバグが再発するようなことが結構ありますね。
こういった意味でも、ある程度まで型ができたら手動で直した方が圧倒的にはやいですね、、

* PCなら、スクリーン一度クリック後に左右キーで操作可能です。スマホ未対応

結論:古典的なゲームは学習済みで作りやすい

今回ChatGPTでのシューティングゲーム作成でうまくいったのは、古典的なゲームでそのプログラミング例がネット上に多く掲載されているからだと思います。だからこそ、少ない文字で適切に意図が伝わったんですね。

逆に独創的なアイデアのゲームだとそれを全部意図伝えるのにはかなり苦労すると思います、、


⇒「ChatGPTプログラム生成実験」カテゴリ記事一覧

その他関連カテゴリ




お気軽にコメントお願いします!

Your email address will not be published. Required fields are marked *




記事カテゴリ