今天的目標是要能夠完成消磚塊的動作,明天做個收尾,第一個遊戲就結束啦~~~
好的,那麼今天我們要寫的球與磚的互動,按照我們的分類,需要寫在move
中,裡面目前有球本身的移動,還有paddle與球的互動,如果我們直接把磚塊的互動加進去,會變得很複雜,不方便除錯.所以今天的第一件事情是把動作分成不同的function.
這邊是目前的code
// 負責處理動作
move = () => {
ball_x += ball_speed_x;
ball_y += ball_speed_y;
// 碰觸邊界動作
if (ball_x < (0 + ball_r)) {
ball_speed_x *= -1;
}
if (ball_x > (canvas.width - ball_r)) {
ball_speed_x *= -1;
}
if (ball_y < (LIFE_SIZE + ball_r)) {
ball_speed_y *= -1;
}
if (ball_y > canvas.height) {
resetBall();
chance -= 1;
if (chance < 0) {
chance = 3;
}
}
// 定義paddle四個角的座標
var paddleTopEdgeY = canvas.height - PADDLE_HEIGHT - PADDLE_HIGH;
var paddleBottomEdgeY = paddleTopEdgeY + PADDLE_HEIGHT;
var paddleLeftEdgeX = paddle_x;
var paddleRightEdgeX = paddleLeftEdgeX + PADDLE_WIDTH;
// 碰到paddle反彈
if (ball_y > (paddleTopEdgeY - ball_r) &&
ball_y < paddleBottomEdgeY &&
ball_x > paddleLeftEdgeX &&
ball_x < paddleRightEdgeX) {
// 加速
ball_speed += 0.5;
// paddle中心
var centerOfPaddleX = paddle_x + PADDLE_WIDTH / 2;
// 計算X軸球速
ball_speed_x = ball_speed * ((ball_x - centerOfPaddleX) / (0.51 * PADDLE_WIDTH));
// 計算Y軸球速
ball_speed_y = -1 * countBallSpeedY(ball_speed, ball_speed_x);
}
}
我們先改成
// 負責處理動作
move = () => {
// 處理球的動作
moveBall()
// paddle互動
actionPaddle()
}
// 球移動
moveBall = () => {
ball_x += ball_speed_x;
ball_y += ball_speed_y;
// 碰觸邊界動作
if (ball_x < (0 + ball_r)) {
ball_speed_x *= -1;
}
if (ball_x > (canvas.width - ball_r)) {
ball_speed_x *= -1;
}
if (ball_y < (LIFE_SIZE + ball_r)) {
ball_speed_y *= -1;
}
if (ball_y > canvas.height) {
resetBall();
chance -= 1;
if (chance < 0) {
chance = 3;
}
}
}
// paddle互動
actionPaddle = () => {
// 定義paddle四個角的座標
var paddleTopEdgeY = canvas.height - PADDLE_HEIGHT - PADDLE_HIGH;
var paddleBottomEdgeY = paddleTopEdgeY + PADDLE_HEIGHT;
var paddleLeftEdgeX = paddle_x;
var paddleRightEdgeX = paddleLeftEdgeX + PADDLE_WIDTH;
// 碰到paddle反彈
if (ball_y > (paddleTopEdgeY - ball_r) &&
ball_y < paddleBottomEdgeY &&
ball_x > paddleLeftEdgeX &&
ball_x < paddleRightEdgeX) {
// 加速
ball_speed += 0.5;
// paddle中心
var centerOfPaddleX = paddle_x + PADDLE_WIDTH / 2;
// 計算X軸球速
ball_speed_x = ball_speed * ((ball_x - centerOfPaddleX) / (0.51 * PADDLE_WIDTH));
// 計算Y軸球速
ball_speed_y = -1 * countBallSpeedY(ball_speed, ball_speed_x);
}
}
好的,到這裡需要先測試一下是否能正常運作,以免要是等等加入新程式時會難以除錯.
正常執行的話我們要來說明一下等等如何處理球碰到磚塊的狀態,說明流程後看code就很容易了.
昨天結束時,我們用陣列畫出了方塊,那判斷球有沒有碰到磚塊的方式就是將球的座標,轉換到磚塊的矩陣中,然後確定對應的陣列位置是否有磚塊.如果對應到的位置是有磚塊的,就需要處理碰撞的動作.
好的~我們先寫出上述敘述的程式吧.
首先先寫個判斷對應位置磚塊是否存在的函式.
//確認磚塊是不是存在
isBrickExist = ( col, row ) => {
if (col >= 0 && col < BRICK_COLS &&
row >= 0 && row < BRICK_ROWS) {
var brickIndexUnderCoord = rowColToArrayIndex(col, row);
return brick_grid[brickIndexUnderCoord];
} else {
return false;
}
}
接下來就是球與磚的互動了
// 碰到磚的動作
actionBrick = () => {
// 球的座標轉換成磚塊的陣列位置
var ballBrickCol = Math.floor(ball_x / BRICK_WIDTH);
var ballBrickRow = Math.floor(ball_y / BRICK_HEIGHT);
var brickIndexUnderBall = rowColToArrayIndex(ballBrickCol, ballBrickRow);
// 判斷球的位置是否在我們設計有磚塊的區域內
if (ballBrickCol >= 0 && ballBrickCol < BRICK_COLS &&
ballBrickRow >= 0 && ballBrickRow < BRICK_ROWS) {
// 確認該位置的磚塊在不在
if (isBrickExist(ballBrickCol, ballBrickRow)){
}
}
}
到這邊寫完了觸發碰撞動作的條件,在開始寫碰撞動作前來介紹一下碰撞的種類.
分為三種:側邊撞擊、上下面的撞擊還有撞在角的位置
前兩種都好判斷及處理,第三種的處理方式就是X軸速度及Y軸速度都完全相反.那判別的方式就是非前兩種情況的撞擊,都算在這一類.
可能有點說明不太清楚,我們配合程式碼看吧
// 確認該位置的磚塊在不在
if (isBrickExist(ballBrickCol, ballBrickRow)) {
// 消除方塊
brick_grid[brickIndexUnderBall] = false;
// 剩餘磚塊的數量減一
bricks_left--;
// 方便判斷撞擊位置的參數
var prevBallX = ball_x - ball_speed_x;
var prevBallY = ball_y - ball_speed_y;
var prevBrickCol = Math.floor(prevBallX / BRICK_WIDTH);
var prevBrickRow = Math.floor(prevBallY / BRICK_HEIGHT);
// 預設非側邊或上下面撞擊
var bothTestFailed = true;
// 側邊撞擊
if (prevBrickCol != ballBrickCol) {
if (isBrickExist(ballBrickCol, ballBrickRow) == false) {
ball_speed_x *= -1;
bothTestFailed = false;
}
}
// 上下面撞擊
if (prevBrickRow != ballBrickRow) {
if (isBrickExist(ballBrickCol, ballBrickRow) == false) {
ball_speed_y *= -1;
bothTestFailed = false;
}
}
// 撞到角的情況
if (bothTestFailed) {
ball_speed_x *= -1;
ball_speed_y *= -1;
}
}
最後在move
中加入
// 負責處理動作
move = () => {
// 處理球的動作
moveBall()
// paddle互動
actionPaddle()
// 磚互動
actionBrick()
}
執行後應該會出現這畫面
明天稍微做一些最後的收尾,第一個遊戲就算完成了~~ 今天就不附上全部程式碼啦,明天再放出來。