iT邦幫忙

0

javascript 打磚塊小遊戲問題

  • 分享至 

  • xImage

請問為什麼在程式碼裡面加了這段

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

之後新增的磚塊都會變成只有一塊...
可是我是想寫出磚塊每隔一段時間就出現一排,
而且有時候球也會自己亂跑,請問是我哪裡寫錯了嗎?

以下是我全部的程式碼

    <script>
        const canvas = document.getElementById("myCanvas");
        const ctx = canvas.getContext("2d");
        let brick = {
            width: 75,
            height: 20,
            padding: 10,
            top: 30,
            left: 20
        }

        let Board = {
            x: (canvas.width - 75) / 2,
            y: canvas.height - 10,
            width: 75,
            height: 10,
            speed: 10
        }

        let Ball = {
            x: canvas.width / 2,
            y: canvas.height - 30,
            ballRadius: 10,
            dx: 2,
            dy: -2
        }

        let blocks = []

        for (let r = 0; r < 5; r++) {
            blocks[r] = []
            for (let c = 0; c < 9; c++) {
                blocks[r][c] = {
                    x: 0,
                    y: 0,
                    hidden: false
                }
            }
        }

        let interval = setInterval(startGame, 10);
        let newB = setInterval(addBlocks, 1000);

        function drawBlocks() {
            for (let r = 0; r < blocks.length; r++) {
                for (let c = 0; c < blocks[r].length; c++) {
                    if (!blocks[r][c].hidden) {
                        const brickX = (c * (brick.width + brick.padding)) + brick.left;
                        const brickY = (r * (brick.height + brick.padding)) + brick.top;
                        blocks[r][c].x = brickX;
                        blocks[r][c].y = brickY;
                        ctx.rect(brickX, brickY, brick.width, brick.height);
                        ctx.fillStyle = "#0095DD";
                        ctx.fill();
                    }
                }
            }
        }

        function drawBoard() {
            ctx.fillRect(Board.x, Board.y, Board.width, Board.height);
            ctx.fillStyle = "0095DD";
            ctx.fill();
        }

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

        function addBlocks() {
            let newBlocks = [];
            newBlocks[0] = [];
            for (let c = 0; c < 9; c++) {
                newBlocks[0][c] = {
                    x: 5,
                    y: 5,
                    hidden: false
                }
            }
            blocks.unshift(newBlocks);
        }



        window.onload = onPageLoaded

        function onPageLoaded() {
            document.addEventListener('keydown', moveBoard)
        }

        function moveBoard(event) {
            if (event.keyCode === 37) { // left arrow 
                Board.x -= Board.speed;
            }

            if (event.keyCode === 39) { // right arrow 
                Board.x += Board.speed;
            }
            if (Board.x + Board.width > canvas.width) {
                Board.x -= Board.speed;
            }
            if (Board.x < 0) {
                Board.x += Board.speed;
            }

        }

        function moveBall() {
            if (Ball.x + Ball.dx > canvas.width - Ball.ballRadius || Ball.x + Ball.dx < Ball.ballRadius) {
                Ball.dx = -Ball.dx;
            }

            if (Ball.y + Ball.dy < Ball.ballRadius) {
                Ball.dy = -Ball.dy;
            }

            if (Ball.y + Ball.dy + 10 > canvas.height - Ball.ballRadius) {
                if (Ball.x >= Board.x && Ball.x <= Board.x + Board.width) {
                    Ball.dy = -Ball.dy;
                }
            }

            if (Ball.y > canvas.height - Ball.ballRadius) {
                alert("GAME OVER");
                clearInterval(interval);
            }


            for (let r = 0; r < blocks.length; r++) {
                for (let c = 0; c < blocks[r].length; c++) {
                    const bk = blocks[r][c];
                    if (Ball.x >= bk.x && Ball.x <= bk.x + brick.width && Ball.y >= bk.y && Ball.y <= bk.y + brick.height) {
                        Ball.dy = -Ball.dy;
                        bk.hidden = true;
                    }
                }
            }
            
            Ball.x += Ball.dx;
            Ball.y += Ball.dy;
        }

        function GameOver() {
            for (let r = 0; r < blocks.length; r++) {
                for (let c = 0; c < blocks[r].length; c++) {
                    let bk = blocks[r][c];
                    if (bk.y > canvas.height - brick.top && bk.hidden === false) {
                        clearInterval(interval);
                        clearInterval(newB);
                        alert("GameOver");
                    }
                }
            }
        }

        function startGame() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            drawBlocks()
            drawBoard()
            drawBall()
            moveBall()
            GameOver()
        }
    </script>
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
bill0704
iT邦新手 5 級 ‧ 2023-01-29 21:47:54

先說好像有蠻多地方必須要修正的
但我改了addBlocks的function後會變成插入一排
建議程式碼很多地方需要注意...
只能先就你的問題解決

  //newBlocks=[{..} ...] 插入blocks好像才對的樣子?
  //你寫的會變成[[{..} ...]]插入blocks
  function addBlocks() {
            let newBlocks = [];
            
            for (let c = 0; c < 9; c++) {
                newBlocks[c] = {
                    x: 5, //這裡沒用到喔,會被你邏輯覆蓋
                    y: 5, //這裡沒用到喔,會被你邏輯覆蓋
                    hidden: false
                }
            }
            blocks.unshift(newBlocks);
        }
看更多先前的回應...收起先前的回應...
xiao_wen iT邦新手 5 級 ‧ 2023-01-29 22:03:21 檢舉

了解,謝謝你/images/emoticon/emoticon02.gif

xiao_wen iT邦新手 5 級 ‧ 2023-01-29 22:07:43 檢舉

聽說寫小遊戲可以訓練邏輯,聽起來很容易....可是做起來好難啊/images/emoticon/emoticon06.gif

bill0704 iT邦新手 5 級 ‧ 2023-01-29 22:20:30 檢舉

我也深有同感/images/emoticon/emoticon02.gif

淺水員 iT邦大師 6 級 ‧ 2023-01-30 00:23:28 檢舉

主旨:改成讓 Board 滑順

加上 direction 屬性,代表向左或向右鍵按下的狀態
bit 0 被設定時,代表向左鍵按下
bit 1 被設定時,代表向右鍵按下

const MOVE = {
    LEFT: 1,
    RIGHT: 2
};
let Board = {
    x: (canvas.width - 75) / 2,
    y: canvas.height - 10,
    width: 75,
    height: 10,
    speed: 3,
    direction: 0 
}

當使用者按下(或放開)左或右時,只設定 Board.direction

function onPageLoaded() {
    document.addEventListener('keydown', function(event) {
        if (event.code === 'ArrowLeft') {
            Board.direction |= MOVE.LEFT;
        } else if (event.code === 'ArrowRight') {
            Board.direction |= MOVE.RIGHT;
        }
    });
    document.addEventListener('keyup', function(event) {
        if (event.code === 'ArrowLeft') {
            Board.direction &= ~MOVE.LEFT;
        } else if (event.code === 'ArrowRight') {
            Board.direction &= ~MOVE.RIGHT;
        }
    });
}

讓每次畫面更新時,都依據鍵盤按下的狀態更新 Board

function moveBoard() {
    let d = Board.direction;
    if (d & MOVE.LEFT) {
        Board.x -= Board.speed;
    }
    if (d & MOVE.RIGHT) {
        Board.x += Board.speed;
    }
    if (Board.x + Board.width > canvas.width) {
        Board.x -= Board.speed;
    }
    if (Board.x < 0) {
        Board.x += Board.speed;
    }
}
function startGame() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawBlocks()
    drawBoard()
    drawBall()
    moveBall()
    moveBoard() // 加上這行
    GameOver()
}
xiao_wen iT邦新手 5 級 ‧ 2023-01-30 10:51:09 檢舉

謝謝你的回答!!!
小弟這裡有個問題想請教...

function onPageLoaded() {
    document.addEventListener('keydown', function(event) {
        if (event.code === 'ArrowLeft') {
            Board.direction |= MOVE.LEFT;
        } else if (event.code === 'ArrowRight') {
            Board.direction |= MOVE.RIGHT;
        }
    });
    document.addEventListener('keyup', function(event) {
        if (event.code === 'ArrowLeft') {
            Board.direction &= ~MOVE.LEFT;
        } else if (event.code === 'ArrowRight') {
            Board.direction &= ~MOVE.RIGHT;
        }
    });
}

裡面的

Board.direction |= MOVE.LEFT;

Board.direction &= ~MOVE.LEFT;

這個是做什麼用的呢!!!
有稍微在網路上看了一下,但是不理解為什麼要用這個,大神能教教我嗎/images/emoticon/emoticon02.gif

淺水員 iT邦大師 6 級 ‧ 2023-01-30 12:41:57 檢舉

|& 是位元運算
MOVE.LEFT 我前面設定為 1
用二進位表示為 0001
(javascript的整數是 32bit,為了方便說明,這邊假設整數是 4bit)
~MOVE.LEFT 是取反運算,二進位是 1110

當某個數 xMOVE.LEFT| 運算時
會把 x 的最低位設為 1。

x~MOVE.LEFT& 運算時
會把 x 的最低位設為 0。

例如
|x|x | MOVE.LEFT| x & ~MOVE.LEFT |
|---|---|---|
| 0000 | 0001 | 0000 |
| 0001 | 0001 | 0000 |
| 0010 | 0011 | 0010 |
| 0100 | 0101 | 0100 |
| 0101 | 0101 | 0100 |

xiao_wen iT邦新手 5 級 ‧ 2023-01-30 13:48:34 檢舉

原來如此!!! 感謝大神詳細的解說!

我要發表回答

立即登入回答