iT邦幫忙

2022 iThome 鐵人賽

DAY 7
0

知道移動方向時要處理的項目(紀錄改變前的位置和方向)後,可以寫一連串的移動判斷

每次要移動時,檢查下列項目:

  1. 下一步的位置是否會超出範圍? -> yes: 遊戲結束
  2. 下一步的位置是否會碰到自己? -> yes: 遊戲結束
  3. 下一步的位置是食物? -> yes: 把食物位置push進蛇的一部分,並重新產生食物位置

有了這三個判斷大概就做完7成的功能了
片段程式碼解析

let direct = [[1,0], [0, 1], [-1, 0], [0, -1]]; // right, down, left, up
const k_map = new Map();
k_map.set("ArrowRight", 0);
k_map.set("ArrowDown", 1);
k_map.set("ArrowLeft", 2);
k_map.set("ArrowUp", 3);

function getKey(e)
{
    let tmp_x, tmp_y;
    tmp_x = snake[snake_len-1].x;
    tmp_y = snake[snake_len-1].y;
    
    k_value = k_map.get(e.code); // get key code, and mapping to the direction value(0,1,2,3)
    
    // get the next position
    tmp_x += direct[k_value][0] * snake_sz;
    tmp_y += direct[k_value][1] * snake_sz;

    // 1. over boarder?
    if ((tmp_x >= max_len) || (tmp_x < 0) || (tmp_y >= max_width) || (tmp_y<0))
    {
        alert("game over");
        location.reload();
        return;
    }
    // 2. meet body?
    if (chk_meet_body(tmp_x, tmp_y) === true)
    {
        alert("game over");
        location.reload();
        return;
    }
    // 3. eat food?
    if (chk_eat(food_x, food_y) === true)
    {
        snake.push({x: tmp_x, y: tmp_y});
        ctx.fillRect(tmp_x, tmp_y, snake_sz, snake_sz);
        ctx.clearRect(snake[0].x, snake[0].y, snake_sz, snake_sz);
        add_food();
        return;
    }
    
    // ============== 判斷出方向更換後,需做的蛇身未來要轉換方向的紀錄========
    
    // snake head, 轉換方向前的蛇頭
    tmp_x = snake[snake_len-1].x;
    tmp_y = snake[snake_len-1].y;

    // store the history direction for snake body to move
    //tmp_map.set(cur_direct, {x:tmp_x, y:tmp_y});
    direct_record.push({direct: cur_direct, x:tmp_x, y:tmp_y});
    
    // 歷史紀錄完以後,開始處理蛇頭的新位置,並移除蛇尾
    tmp_x += direct[k_value][0] * snake_sz;
    tmp_y += direct[k_value][1] * snake_sz;

    if (chk_meet_sth(food_x, food_y) === true)
    {
        snake.push({x: tmp_x, y: tmp_y});
        ctx.fillRect(tmp_x, tmp_y, snake_sz, snake_sz);
        cur_direct = k_value;
        add_food();
        return;
    }
    snake.push({x: tmp_x, y: tmp_y});
    ctx.fillRect(tmp_x, tmp_y, snake_sz, snake_sz);

    // get the history direction and move 
    let tmp = direct_record[0].direct;
    tmp_x = snake[0].x + direct[tmp][0] * snake_sz;
    tmp_y = snake[0].y + direct[tmp][1] * snake_sz;
    
    // 碰到轉折點後,將歷史紀錄移除,蛇尾之後有新的方向移動
    if ((tmp_x == direct_record[0].x) && (tmp_y == direct_record[0].y))
    {
        direct_record.shift();
    }
    
    // 移除蛇尾
    ctx.clearRect(snake[0].x, snake[0].y, snake_sz, snake_sz);
    snake.shift();
    cur_direct = k_value;
}

現在的版本,蛇的移動都是靠鍵盤有按下才會動起來,所以剩下的三成指的是,能每隔一段時間區間後,蛇自己移動,這部分留著下篇待續。


上一篇
貪食蛇 - 移動構思
下一篇
貪食蛇 - 自動移動
系列文
那些八年級生的經典迷你遊戲,前端JS自學之路20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言