見出し画像

ChatGPT4:ブロック崩しの自動生成(2) 「具体的に指示しようと決めた!」



ボールを増やす機能を追加!

ありがとう動くのは確認しました。
スコアによってボールを増やしたいんだけど処理追加してくれる?
(*音声による入力)

以下のスクリプトでは、スコアが5ポイント毎にボールが1つ追加されるようになります。複数のボールを管理するために、ボールごとの座標、速度、そしてボールの数を格納する配列を用意しています。それぞれのボールについて描画と衝突判定を行うように変更しています。

<!DOCTYPE html>
<html>
<head>
    <style>
        .block1 { background-color: red; }
        .block2 { background-color: green; }
        .block3 { background-color: blue; }
    </style>
</head>
<body>
    <canvas id="myCanvas" width="480" height="320"></canvas>
    <script>
        var canvas = document.getElementById("myCanvas");
        var ctx = canvas.getContext("2d");
        var ballRadius = 10;
        var paddleHeight = 10;
        var paddleWidth = 75;
        var paddleX = (canvas.width-paddleWidth) / 2;
        var rightPressed = false;
        var leftPressed = false;
        var score = 0;
        var blockRowCount = 3;
        var blockColumnCount = 5;
        var blockWidth = 75;
        var blockHeight = 20;
        var blockPadding = 10;
        var blockOffsetTop = 30;
        var blockOffsetLeft = 30;
        
        // ball properties
        var balls = [{
            x: canvas.width/2,
            y: canvas.height-30,
            dx: 2,
            dy: -2
        }];

        var blocks = [];
        for(var c=0; c<blockColumnCount; c++) {
            blocks[c] = [];
            for(var r=0; r<blockRowCount; r++) {
                blocks[c][r] = { x: 0, y: 0, status: 1, class: `block${r+1}` };
            }
        }

        document.addEventListener("keydown", keyDownHandler, false);
        document.addEventListener("keyup", keyUpHandler, false);

        function keyDownHandler(e) {
            if(e.key == "Right" || e.key == "ArrowRight") {
                rightPressed = true;
            }
            else if(e.key == "Left" || e.key == "ArrowLeft") {
                leftPressed = true;
            }
        }

        function keyUpHandler(e) {
            if(e.key == "Right" || e.key == "ArrowRight") {
                rightPressed = false;
            }
            else if(e.key == "Left" || e.key == "ArrowLeft") {
                leftPressed = false;
            }
        }

        function drawBall(ball) {
            ctx.beginPath();
            ctx.arc(ball.x, ball.y, ballRadius, 0, Math.PI*2);
            ctx.fillStyle = "#0095DD";
            ctx.fill();
            ctx.closePath();
        }

        function drawPaddle() {
            ctx.beginPath();
            ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
            ctx.fillStyle = "#0095DD";
            ctx.fill();
            ctx.closePath();
        }

        function drawBlocks() {
            for(var c=0; c<blockColumnCount; c++) {
                for(var r=0; r<blockRowCount; r++) {
                    if(blocks[c][r].status == 1) {
                        var blockX = (c*(blockWidth+blockPadding))+blockOffsetLeft;
                        var blockY = (r*(blockHeight+blockPadding))+blockOffsetTop;
                        blocks[c][r].x = blockX;
                        blocks[c][r].y = blockY;
                        ctx.beginPath();
                        ctx.rect(blockX, blockY, blockWidth, blockHeight);
                        ctx.fillStyle = window.getComputedStyle(document.body).getPropertyValue(blocks[c][r].class);
                        ctx.fill();
                        ctx.closePath();
                    }
                }
            }
        }

        function drawScore() {
            ctx.font = "16px Arial";
            ctx.fillStyle = "#0095DD";
            ctx.fillText("Score: "+score, 8, 20);
        }

        function collisionDetection(ball) {
            for(var c=0; c<blockColumnCount; c++) {
                for(var r=0; r<blockRowCount; r++) {
                    var b = blocks[c][r];
                    if(b.status == 1) {
                        if(ball.x > b.x && ball.x < b.x+blockWidth && ball.y > b.y && ball.y < b.y+blockHeight) {
                            ball.dy = -ball.dy;
                            b.status = 0;
                            score++;
                            if(score % 5 == 0) {  // Every 5 points, add a new ball
                                balls.push({
                                    x: canvas.width/2,
                                    y: canvas.height-30,
                                    dx: 2,
                                    dy: -2
                                });
                            }
                            if(score == blockRowCount*blockColumnCount) {
                                alert("YOU WIN, CONGRATS!");
                                document.location.reload();
                                clearInterval(interval); 
                            }
                        }
                    }
                }
            }
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            drawBlocks();
            balls.forEach(ball => drawBall(ball));
            drawPaddle();
            drawScore();
            balls.forEach(ball => collisionDetection(ball));

            balls.forEach((ball, i) => {
                if(ball.x + ball.dx > canvas.width-ballRadius || ball.x + ball.dx < ballRadius) {
                    ball.dx = -ball.dx;
                }
                if(ball.y + ball.dy < ballRadius) {
                    ball.dy = -ball.dy;
                }
                else if(ball.y + ball.dy > canvas.height-ballRadius) {
                    if(ball.x > paddleX && ball.x < paddleX + paddleWidth) {
                        ball.dy = -ball.dy;
                    }
                    else {
                        alert("GAME OVER");
                        document.location.reload();
                        clearInterval(interval);
                    }
                }
                ball.x += ball.dx;
                ball.y += ball.dy;
            });

            if(rightPressed && paddleX < canvas.width-paddleWidth) {
                paddleX += 7;
            }
            else if(leftPressed && paddleX > 0) {
                paddleX -= 7;
            }
        }

        var interval = setInterval(draw, 10);
    </script>

</body>
</html>

ボール追加も余裕じゃん!?

音声入力で、適当な指示で依頼してみましたが、
意図は汲み取って貰えた様です。
スコア5以上になるまでテストプレイし、しっかりとボールが追加されことを確認しましたが、2つのボールのいずれか1つでも落下させてしまうと、即ゲームオーバーになってしまう様です。

これは、こちらの意図とは異なりますねー。

具体的な指示の必要性

改めて、
ChatGPTには具体的に指示をしなければいけない
ことを思い出しました。

共通の意図を持つ!
同じゴールを設定をする!

そのために、プロンプトがあるのですよね。

いいですね。次の改善をお願いします。
・画面幅サイズを1280に拡大
・表示ブロック数を増やす
・全てのブロックを消せたら、ブロックを並べ替えて次のステージが始まる。
・現在のステージ数を画面に常に表示しておく。
・全10ステージ。

感動していることには変わりがないので、褒め言葉は忘れずに伝えます。

加えて、
箇条書きに「どうすればギャップがない様に指示を伝えることができるか?」を意識して、仕様改善を要求してみます。

この辺は、対人間コミュニケーションと同じですよね!!

ご要望に応じて、以下にスクリプトを改良します。画面幅を1280pxに拡大し、ブロックの数を増やします。さらに、全てのブロックが消えると次のステージが始まるようにしました。現在のステージ数も画面に表示されます。最後に、全10ステージで、全てのステージをクリアするとゲームが終了します。

ご要望www

こちらの指示を反芻して貰えるのは、
「伝わっているかどうか」という意味で、
こちらに安心感を与えてくれますね。

相手の言葉をこちらも繰り返すテクニック!大切です!

<!DOCTYPE html>
<html>
<head>
    <style>
        .block1 { background-color: red; }
        .block2 { background-color: green; }
        .block3 { background-color: blue; }
    </style>
</head>
<body>
    <canvas id="myCanvas" width="1280" height="720"></canvas>
    <script>
        var canvas = document.getElementById("myCanvas");
        var ctx = canvas.getContext("2d");
        var ballRadius = 10;
        var paddleHeight = 10;
        var paddleWidth = 75;
        var paddleX = (canvas.width-paddleWidth) / 2;
        var rightPressed = false;
        var leftPressed = false;
        var score = 0;
        var stage = 1;
        var blockRowCount = 6;
        var blockColumnCount = 8;
        var blockWidth = 75;
        var blockHeight = 20;
        var blockPadding = 10;
        var blockOffsetTop = 30;
        var blockOffsetLeft = 30;

        var balls = [{
            x: canvas.width/2,
            y: canvas.height-30,
            dx: 2,
            dy: -2
        }];

        var blocks = [];

        function generateBlocks() {
            for(var c=0; c<blockColumnCount; c++) {
                blocks[c] = [];
                for(var r=0; r<blockRowCount; r++) {
                    blocks[c][r] = { x: 0, y: 0, status: 1, class: `block${((c*r+stage)%3)+1}` };
                }
            }
        }
        generateBlocks();

        document.addEventListener("keydown", keyDownHandler, false);
        document.addEventListener("keyup", keyUpHandler, false);

        function keyDownHandler(e) {
            if(e.key == "Right" || e.key == "ArrowRight") {
                rightPressed = true;
            }
            else if(e.key == "Left" || e.key == "ArrowLeft") {
                leftPressed = true;
            }
        }

        function keyUpHandler(e) {
            if(e.key == "Right" || e.key == "ArrowRight") {
                rightPressed = false;
            }
            else if(e.key == "Left" || e.key == "ArrowLeft") {
                leftPressed = false;
            }
        }

        function drawBall(ball) {
            ctx.beginPath();
            ctx.arc(ball.x, ball.y, ballRadius, 0, Math.PI*2);
            ctx.fillStyle = "#0095DD";
            ctx.fill();
            ctx.closePath();
        }

        function drawPaddle() {
            ctx.beginPath();
            ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
            ctx.fillStyle = "#0095DD";
            ctx.fill();
            ctx.closePath();
        }

        function drawBlocks() {
            for(var c=0; c<blockColumnCount; c++) {
                for(var r=0; r<blockRowCount; r++) {
                    if(blocks[c][r].status == 1) {
                        var blockX = (c*(blockWidth+blockPadding))+blockOffsetLeft;
                        var blockY = (r*(blockHeight+blockPadding))+blockOffsetTop;
                        blocks[c][r].x = blockX;
                        blocks[c][r].y = blockY;
                        ctx.beginPath();
                        ctx.rect(blockX, blockY, blockWidth, blockHeight);
                        ctx.fillStyle = window.getComputedStyle(document.body).getPropertyValue(blocks[c][r].class);
                        ctx.fill();
                        ctx.closePath();
                    }
                }
            }
        }

        function drawScore() {
            ctx.font = "16px Arial";
            ctx.fillStyle = "#0095DD";
            ctx.fillText("Score: "+score, 8, 20);
        }

        function drawStage() {
            ctx.font = "16px Arial";
            ctx.fillStyle = "#0095DD";
            ctx.fillText("Stage: "+stage, canvas.width - 100, 20);
        }

        function collisionDetection(ball) {
            for(var c=0; c<blockColumnCount; c++) {
                for(var r=0; r<blockRowCount; r++) {
                    var b = blocks[c][r];
                    if(b.status == 1) {
                        if(ball.x > b.x && ball.x < b.x+blockWidth && ball.y > b.y && ball.y < b.y+blockHeight) {
                            ball.dy = -ball.dy;
                            b.status = 0;
                            score++;
                            if(score % 5 == 0) {
                                balls.push({
                                    x: canvas.width/2,
                                    y: canvas.height-30,
                                    dx: 2,
                                    dy: -2
                                });
                            }
                            if(score == blockRowCount*blockColumnCount*stage) {
                                if(stage == 10) {
                                    alert("YOU WIN, CONGRATS!");
                                    document.location.reload();
                                    clearInterval(interval); 
                                } else {
                                    stage++;
                                    generateBlocks();
                                }
                            }
                        }
                    }
                }
            }
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            drawBlocks();
            balls.forEach(ball => drawBall(ball));
            drawPaddle();
            drawScore();
            drawStage();
            balls.forEach(ball => collisionDetection(ball));

            balls.forEach((ball, i) => {
                if(ball.x + ball.dx > canvas.width-ballRadius || ball.x + ball.dx < ballRadius) {
                    ball.dx = -ball.dx;
                }
                if(ball.y + ball.dy < ballRadius) {
                    ball.dy = -ball.dy;
                }
                else if(ball.y + ball.dy > canvas.height-ballRadius) {
                    if(ball.x > paddleX && ball.x < paddleX + paddleWidth) {
                        ball.dy = -ball.dy;
                    }
                    else {
                        alert("GAME OVER");
                        document.location.reload();
                        clearInterval(interval);
                    }
                }
                ball.x += ball.dx;
                ball.y += ball.dy;
            });

            if(rightPressed && paddleX < canvas.width-paddleWidth) {
                paddleX += 7;
            }
            else if(leftPressed && paddleX > 0) {
                paddleX -= 7;
            }
        }

        var interval = setInterval(draw, 10);
    </script>

</body>
</html>

表示位置問題

画面も広がり、ステージもバッチリ実装!
で、ブロック位置は微妙。

そうですよね、
「画面の真ん中にブロックを表示する」は、
「分かって貰えているだろう」ではなく、
こちらが具体的に伝えるべきことなんですよね。

うん、表示位置ねw

続きは、また次回に!

この記事が気に入ったらサポートをしてみませんか?