欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何利用vue3實現(xiàn)一個俄羅斯方塊

 更新時間:2022年01月18日 09:25:17   作者:用戶名這個名字都有人取嗎  
俄羅斯方塊這個游戲相信大家都玩過,下面這篇文章主要給大家介紹了關于如何利用vue3實現(xiàn)一個俄羅斯方塊的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下

前言

之前寫了一個貪吃蛇的demo,但是公司最近沒業(yè)務還得繼續(xù)摸魚??。所以趁熱打鐵,在下又去攢了一個俄羅斯方塊。代碼地址

游戲相關設置

游戲界面設置

構建一個16×25的游戲界面,使用響應式數(shù)據(jù)存儲一個二維數(shù)組,該二維數(shù)據(jù)中存儲著每一個有關該方格信息的數(shù)組,該數(shù)組格式為[從上到下的坐標位置,從左到右的坐標位置, 該方格顏色(0為白色,1為紅色,2為綠色)]

image.png

//游戲界面(作為俄羅斯方塊在各個格子上渲染顏色的依據(jù))
let checkerboardInfo = reactive([]);

//設置游戲界面
const setCheckerboard = () =>{
  for (let i = 0; i < 25; i++) {
    for (let j = 0; j < 16; j++) {
      checkerboardInfo.push([i, j, 0])
    }
  }
}

存儲還在移動的俄羅斯方塊信息

可移動的俄羅斯方塊一共分為7種:正方形、長方形、L形、反L形、z形、反z形、三角形,使用隨機數(shù)選取每個可移動的俄羅斯方塊,使用二維數(shù)組存儲可移動的俄羅斯方塊四個坐標點,并確保其從游戲界面中間落下(實力有限,直接將七種形態(tài)用代碼窮舉了(●'?'●))

image.png

/存儲當前還在墜落的方格坐標
let moveSquareCoordinate = null;

/方塊類型(長方形、三角形、正方形,z字型, 反z字型,l型, 反l型)
let squareType = [0, 1, 2, 3, 4, 5, 6];

//方塊類型下標
let squareTypeIndex = -1;

//隨機選取方塊
const randomSquareType = ()=>{
  squareTypeIndex = Math.floor(Math.random()*(7));
};

//構造方塊
const setSquare = () =>{
  randomSquareType();
  switch(squareTypeIndex) {

    //長方形
    case 0:
      moveSquareCoordinate = [[0, 6], [0, 7], [0, 8], [0, 9]]
      break;

    //三角形
    case 1:
      moveSquareCoordinate = [[0, 8], [0, 9], [0, 10], [1, 9]]
      break;
    
    //正方形
    case 2:
      moveSquareCoordinate = [[0, 7], [0, 8], [1, 7], [1, 8]]
      break;

    //z字型
    case 3:
      moveSquareCoordinate = [[0, 7], [0, 8], [1, 8], [1, 9]]
      break;

    //反z字型
    case 4:
      moveSquareCoordinate = [[0, 8], [0, 7], [1, 7], [1, 6]]
      break;

    //l型
    case 5:
      moveSquareCoordinate = [[0, 8], [0, 9], [0, 10], [1, 8]]
      break;

    //反l型
    case 6:
      moveSquareCoordinate = [[0, 8], [0, 9], [0, 10], [1, 10]]
      break;
  }
}

存儲已經(jīng)不能移動的俄羅斯方塊信息

當俄羅斯方塊觸碰到底部邊界或者,觸碰到不能移動的俄羅斯方塊時,可移動的俄羅斯方塊就會變成不可移動的方塊,所以需要也需要用一個專門的數(shù)組存儲

//存儲當前已經(jīng)穩(wěn)定墜落的方塊的坐標
let stabilitySquareCoordinate = [];

使用之前在貪吃蛇中使用的顏色渲染工具

//改變棋盤格子顏色([A, B]為坐標,color是需要渲染為什么顏色(0為白色,1為紅色,2為綠色))
const changeCheckerboard = ([A, B], color) => {
  for (let i = 0; i < checkerboardInfo.length; i++) {
      let [x, y, num] = checkerboardInfo[i];
      if( A===x && B===y ){
        checkerboardInfo[i][2]=color;
        break
      }
    }
};

//清空棋盤顏色
const clearCheckerboard = () => {
  for (let index = 0; index < checkerboardInfo.length; index++) {
    checkerboardInfo[index][2] = 0
  }
};

讓方塊移動起來(不考慮切換方塊的形態(tài)切換)

可移動的俄羅斯方塊會一直向下移動,能通過鍵盤左右鍵控制其向左右移動,通過鍵盤下鍵加速向下移動,不能向上移動(鍵盤上鍵控制該方塊形態(tài)的切換),移動時不能超過該游戲界面的范圍,如果移動的俄羅斯方塊觸碰到不可移動的俄羅斯方塊,則停止移動,并且會積累在不可移動的俄羅斯方塊上

在移動之前得先設置工具函數(shù),用于檢測移動后的俄羅斯方塊二維數(shù)組中存儲的坐標點數(shù)組是否會超出游戲界面的范圍,以及是否會觸碰到不可移動的俄羅斯方塊上

檢測移動的俄羅斯方塊二維數(shù)組在移動后它的每個坐標點數(shù)組是否有超出范圍的

在范圍之中則不管,不在范圍之中則不允許移動

//判斷是否碰到邊界(arr為可移動俄羅斯方塊上單個的坐標點)
const judgeBoundary = (arr) => {
  if((arr[0]<0||arr[0]>24)||(arr[1]<0||arr[1]>15)){
    return true
  };
  return false
}

檢測移動的俄羅斯方塊二維數(shù)組在移動后它的每個坐標點數(shù)組是否會觸碰到不可移動的俄羅斯方塊上

觀察可知,移動的俄羅斯方塊和不可移動的俄羅斯方塊觸碰到一起就是在它們存儲的坐標點數(shù)組下標為0的值相差一,而下標為1的值相等時,該移動的俄羅斯方塊變成不可移動的俄羅斯方塊

特殊情況:當移動方塊沒碰到不可移動的方塊,但是觸碰到游戲界面的最底部,即存儲的坐標點數(shù)組下標為0的值為24時該移動方塊亦會變成不可移動的方塊

//查看方塊是否碰到已經(jīng)存在的方格中(arr為可移動俄羅斯方塊上單個的坐標點)
const judgeStabilitySquareCoordinate = (arr) =>{
  //移動到最后一格時
  if( arr[0] === 24 ){
    return true
  }
  
  //遍歷不可移動的俄羅斯方塊與該點做比較
  for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
    if(stabilitySquareCoordinate[index][0]-1 === arr[0] && stabilitySquareCoordinate[index][1] === arr[1]){
      return true
    }
  };
  return false;
}

特殊情況(得分)

得分是在可移動的俄羅斯變?yōu)椴豢梢苿拥亩砹_斯方塊發(fā)生的一個判斷

如果在不可移動的俄羅斯方塊二維數(shù)組中,有坐標點數(shù)組下標為0的值相同且存在16個,那么這16個點應該被刪除出不可移動的俄羅斯方塊二維數(shù)組,這16個點被刪除后,在這些點上的坐標得向下移動一格(如下圖所示)

//得分(arr為可移動俄羅斯方塊上單個的坐標點)
const score = (arr)=>{
  let num = 0;
  for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
    if(arr[0] === stabilitySquareCoordinate[index][0]){
      num++;
      //等于16后滿足當前銷毀需求(直接跳出循環(huán)減少性能消耗)
      if(num === 16){
        break;
      }
    }    
  };
  if(num === 16){
  
    //刪除已經(jīng)在該數(shù)組中湊齊能得分的行數(shù)(小技巧,倒著循環(huán)數(shù)組能保證每個符合刪除條件的數(shù)據(jù)都能被刪除)
    for (let index = stabilitySquareCoordinate.length-1; index >-1; index--) {
      if(arr[0] === stabilitySquareCoordinate[index][0]){
        stabilitySquareCoordinate.splice(index, 1)
      }
    }
    
    //將所有在銷毀行上面的穩(wěn)定方塊移動至下一行去
    for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
      if(arr[0] > stabilitySquareCoordinate[index][0]){
        stabilitySquareCoordinate[index][0]++
      }
    }
  }
}

移動方法

移動就是通過監(jiān)聽鍵盤彈起事件,通過對應的keycode更改可移動的俄羅斯方塊中每個坐標點的值,然后再將獲取到的新的二維數(shù)組去執(zhí)行之前的三個方法依次判斷

//事件(方便后期摘除事件)
const listener = (event)=>{
  //只監(jiān)聽上下左右四個按鍵
  const keyCodeArr =  [37, 39, 40];
  if(keyCodeArr.includes(event.keyCode)){
    //監(jiān)聽方向鍵變化(執(zhí)行方塊移動方向)
    moveSquare(event.keyCode);
  }
}

//定時器(一直會有一個下移方塊指令執(zhí)行)
let timer = setInterval(()=>{
  moveSquare(40)
},500);

//在window上掛載事件監(jiān)聽器
window.addEventListener("keydown", listener);
//移動方塊的指令
const moveSquare = (num) => {
  if( !isShowSquare.value ){
    return
  };

  //移動
  for (let index = 0; index < moveSquareCoordinate.length; index++) {
    switch (num) {
      //鍵盤對應數(shù)字如下
      //40:下;37:左;39:右;
      case 37:
        moveSquareCoordinate[index][1] = moveSquareCoordinate[index][1]-1
        break;
      case 39:
        moveSquareCoordinate[index][1] = moveSquareCoordinate[index][1]+1
        break;
      case 40:
        moveSquareCoordinate[index][0] = moveSquareCoordinate[index][0]+1
        break;
    };
  };

  //是否超過邊界的標桿
  let flag1 = false;
  for (let index = 0; index < moveSquareCoordinate.length; index++) {
    if(judgeBoundary(moveSquareCoordinate[index])){
      flag1 = true;
    }
  }

  //標桿滿足后方塊復位
  if(flag1){
    for (let index = 0; index < moveSquareCoordinate.length; index++) {
      switch (num) {
        case 37:
          moveSquareCoordinate[index][1] = moveSquareCoordinate[index][1]+1
          break;
        case 39:
          moveSquareCoordinate[index][1] = moveSquareCoordinate[index][1]-1
          break;
        case 40:
          moveSquareCoordinate[index][0] = moveSquareCoordinate[index][0]-1
          break;
      };
    };
  }

  //能否觸碰到已穩(wěn)定方塊的標桿
  let flag2 = false;
  let coordinate = [];
  for (let index = 0; index < moveSquareCoordinate.length; index++) {
    if(judgeStabilitySquareCoordinate(moveSquareCoordinate[index])){
      flag2 = true;
    }
  };

  //只要碰到了
  if (flag2) {

    //添加進入不移動的方塊坐標數(shù)組
    for (let index = 0; index < moveSquareCoordinate.length; index++) {
      stabilitySquareCoordinate.push(moveSquareCoordinate[index]);
      if(moveSquareCoordinate[index][0]-1 === 0){
        //輸了就跳出循環(huán),不必再給已穩(wěn)定的方塊坐標添加新坐標了
        isFail.value = true;
        break
      }
    }

    //如果已經(jīng)失敗則停止移動
    if (isFail.value) {
      return
    }
    isShowSquare.value = false;

    //將移動方塊中每個點坐標去做得分判斷
    for (let index = 0; index < moveSquareCoordinate.length; index++) {
      score(moveSquareCoordinate[index]);
    }
  }
  
  //重新渲染游戲界面顏色
  clearCheckerboard();
  for (let index = 0; index < moveSquareCoordinate.length; index++) {
    changeCheckerboard(moveSquareCoordinate[index], 2)
  }
  for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
    changeCheckerboard(stabilitySquareCoordinate[index], 1)
  }
};

經(jīng)過一系列的操作,我們已經(jīng)得到了一個可以玩的俄羅斯方塊,它能夠移動方塊,也能得分,但是不能將移動的俄羅斯方塊切換形態(tài),十分沒有游戲體驗感,那就再加切換形態(tài)的操作??(這個操作把我差點帶走,看到這里多少給個贊唄o( ̄▽ ̄)ブ)

切換操作書寫

先窮舉七種形狀的不同形態(tài)(如下圖)

形態(tài)變化 
長方形2種
正方形1種
z形2種
反z形2種
三角形4種
L形4種
反L形4種

設計檢測該形狀形態(tài)的方法

檢測長方形形態(tài)的方法

通過判斷A、B兩點的下標為0是的值是否相同來返回形態(tài)

const detectionToolAboutRectangle = () => {
  if (moveSquareCoordinate[0][0] !== moveSquareCoordinate[1][0]) {
    //豎直的方塊
    return 0
  }

  //橫著的長方形方塊
  return 1
};

檢測z形和反z形形態(tài)的方法

通過判斷A、B兩點的下標為0是的值是否相同來返回形態(tài)

//檢驗工具(z字形和反z字形)
const detectionToolAboutZOr_Z = () => {
  if(moveSquareCoordinate[0][0] === moveSquareCoordinate[1][0]){
    //z字形
    return 0
  }
  //n字形
  return 1
};

檢測L形、反L形、三角形形態(tài)的方法

通過判斷判斷A、B、C三點構成的線與D點的相對位置來判斷形態(tài),第一種形態(tài)為D點在線段ABC下方,第二種形態(tài)為D點在線段ABC左邊,第三種形態(tài)為D點在線段ABC上方,第四種形態(tài)為D點在線段ABC右邊,

//檢驗工具(三角形、l型、反l型)
const detectionToolAboutTriangle = () => {
  
  //判斷四種形態(tài)
  if ((moveSquareCoordinate[0][0] === moveSquareCoordinate[1][0] && moveSquareCoordinate[1][0] === moveSquareCoordinate[2][0]) && moveSquareCoordinate[1][0]<moveSquareCoordinate[3][0]) {
    return 0
  }
  if ((moveSquareCoordinate[0][1] === moveSquareCoordinate[1][1] && moveSquareCoordinate[1][1] === moveSquareCoordinate[2][1]) && moveSquareCoordinate[2][1]>moveSquareCoordinate[3][1]) {
    return 1
  }
  if ((moveSquareCoordinate[0][0] === moveSquareCoordinate[1][0] && moveSquareCoordinate[1][0] === moveSquareCoordinate[2][0]) && moveSquareCoordinate[1][0]>moveSquareCoordinate[3][0]) {
    return 2
  }
  if ((moveSquareCoordinate[0][1] === moveSquareCoordinate[1][1] && moveSquareCoordinate[1][1] === moveSquareCoordinate[2][1]) && moveSquareCoordinate[2][1]<moveSquareCoordinate[3][1]) {
    return 3
  }
};

設計切換方法

需要判斷其現(xiàn)有形態(tài),然后判斷切換后是否會超出游戲范圍界面,或者觸碰到不能移動,如果不超出且不觸碰則切換狀態(tài)

切換L形形態(tài)(代碼過多只解釋一個,其余的可以看我倉庫代碼)

由于業(yè)務水平緣故,在下直接保證每次切換形態(tài)都是向右旋轉90度(如圖旋轉)

在每一次旋轉后,都以之前的B點坐標重構方塊,(沒錯在下直接窮舉了7種方塊的18個類型變化,如果有其他好方法,歡迎評論區(qū)留言,謝謝大哥??)

const toggleSquareShapeAboutL= () => {
  
  //改變后的俄羅斯方塊數(shù)組
  let arr = null;
  
  //滿足哪種形態(tài)則將后一種形態(tài)的坐標點存儲進該數(shù)組中
  switch (detectionToolAboutTriangle()) {
    case 0:
      arr = [[moveSquareCoordinate[1][0]-1,moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0]+1,moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0]-1,moveSquareCoordinate[1][1]-1]];
      
      //判斷每個點會不會超出游戲界面或者觸碰到不可移動的俄羅斯方塊上
      for (let index = 0; index < arr.length; index++) {
        if(judgeBoundary(arr[index]) || judgeStabilitySquareCoordinate(arr[index])){
          return
        }
      }
      moveSquareCoordinate = arr;
      clearCheckerboard();
      for (let index = 0; index < moveSquareCoordinate.length; index++) {
        changeCheckerboard(moveSquareCoordinate[index], 2)
      }
      for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
        changeCheckerboard(stabilitySquareCoordinate[index], 1)
      }
      break;
    case 1:
      arr = [[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]+1],[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]-1],[moveSquareCoordinate[1][0]-1,moveSquareCoordinate[1][1]+1]];
      for (let index = 0; index < arr.length; index++) {
        if(judgeBoundary(arr[index]) || judgeStabilitySquareCoordinate(arr[index])){
          return
        }
      }
      moveSquareCoordinate = arr;
      clearCheckerboard();
      for (let index = 0; index < moveSquareCoordinate.length; index++) {
        changeCheckerboard(moveSquareCoordinate[index], 2)
      }
      for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
        changeCheckerboard(stabilitySquareCoordinate[index], 1)
      }
      break;
    case 2:
      arr = [[moveSquareCoordinate[1][0]+1,moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0]-1,moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0]+1,moveSquareCoordinate[1][1]+1]];
      for (let index = 0; index < arr.length; index++) {
        if(judgeBoundary(arr[index]) || judgeStabilitySquareCoordinate(arr[index])){
          return
        }
      }
      moveSquareCoordinate = arr;
      clearCheckerboard();
      for (let index = 0; index < moveSquareCoordinate.length; index++) {
        changeCheckerboard(moveSquareCoordinate[index], 2)
      }
      for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
        changeCheckerboard(stabilitySquareCoordinate[index], 1)
      }
      break;
    case 3:
      arr = [[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]-1],[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]],[moveSquareCoordinate[1][0],moveSquareCoordinate[1][1]+1],[moveSquareCoordinate[1][0]+1,moveSquareCoordinate[1][1]-1]];
      for (let index = 0; index < arr.length; index++) {
        if(judgeBoundary(arr[index]) || judgeStabilitySquareCoordinate(arr[index])){
          return
        }
      }
      
      //給移動的俄羅斯方塊數(shù)組重新賦值
      moveSquareCoordinate = arr;
      
      //重新渲染游戲界面
      clearCheckerboard();
      for (let index = 0; index < moveSquareCoordinate.length; index++) {
        changeCheckerboard(moveSquareCoordinate[index], 2)
      }
      for (let index = 0; index < stabilitySquareCoordinate.length; index++) {
        changeCheckerboard(stabilitySquareCoordinate[index], 1)
      }
      break;
  }
};

單個方格組件展示

CheckerboardItem.vue

只通過存入的方格顏色信息(方格信息數(shù)組中的第三個值)來判斷當前方格顯示的顏色

const props = defineProps({
  checkerboardItemInfo:Array,
});

//通過toRefs解構方格信息數(shù)組中的第三個值(只有使用toRefs才能保持該引用數(shù)據(jù)解構后的數(shù)據(jù)依然保持響應式)
let [ x, y, num] = toRefs(props.checkerboardItemInfo)

let color = ref('');

//使用監(jiān)聽器完成數(shù)據(jù)監(jiān)聽,給背景色設置不同值
watchEffect(()=>{
  switch (num.value) {
    case 0:
      color.value = 'while'
      break;
    case 1:
      color.value = 'red'
      break;
    case 2:
      color.value = 'green'
      break;
  }
})
<style lang="less" scoped>
.checkerboardItem{
  //vue3.2能在css中使用v-bind綁定響應式數(shù)據(jù)
  background-color: v-bind(color);
}
</style>

好了,俄羅斯方塊搞定

總結

到此這篇關于如何利用vue3實現(xiàn)一個俄羅斯方塊的文章就介紹到這了,更多相關vue3寫俄羅斯方塊內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 淺談VUE uni-app 生命周期

    淺談VUE uni-app 生命周期

    這篇文章主要介紹了uni-app 的生命周期,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • 詳解vue-cli快速構建項目以及引入bootstrap、jq

    詳解vue-cli快速構建項目以及引入bootstrap、jq

    本篇文章主要介紹了vue-cli快速構建項目以及引入bootstrap、jq,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Vue + Element UI圖片上傳控件使用詳解

    Vue + Element UI圖片上傳控件使用詳解

    這篇文章主要為大家詳細介紹了Vue + Element UI圖片上傳控件的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • vue中v-for通過動態(tài)綁定class實現(xiàn)觸發(fā)效果

    vue中v-for通過動態(tài)綁定class實現(xiàn)觸發(fā)效果

    這篇文章主要介紹了vue中v-for通過動態(tài)綁定class實現(xiàn)觸發(fā)效果,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-12-12
  • Vue最新防抖方案(必看篇)

    Vue最新防抖方案(必看篇)

    今天小編就為大家分享一篇Vue最新防抖方案(必看篇),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • 關于vuepress部署出現(xiàn)樣式的問題及解決

    關于vuepress部署出現(xiàn)樣式的問題及解決

    這篇文章主要介紹了關于vuepress部署出現(xiàn)樣式的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue如何把組件方法暴露到window對象中

    vue如何把組件方法暴露到window對象中

    這篇文章主要介紹了vue如何把組件方法暴露到window對象中,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue如何通過id從列表頁跳轉到對應的詳情頁

    vue如何通過id從列表頁跳轉到對應的詳情頁

    這篇文章主要介紹了vue如何通過id從列表頁跳轉到對應的詳情頁 ,需要的朋友可以參考下
    2018-05-05
  • vue清除瀏覽器全部cookie的問題及解決方法(絕對有效!)

    vue清除瀏覽器全部cookie的問題及解決方法(絕對有效!)

    最近項目要實現(xiàn)關閉瀏覽器清除用戶緩存的功能,下面這篇文章主要給大家介紹了關于vue清除瀏覽器全部cookie的問題及解決方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • Vue3中級指南之如何在vite中使用svg圖標詳解

    Vue3中級指南之如何在vite中使用svg圖標詳解

    在以webpack為構建工具的開發(fā)環(huán)境中我們可以很方便的實現(xiàn)SVG圖標的組件化,下面這篇文章主要給大家介紹了關于Vue3中級指南之如何在vite中使用svg圖標的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-04-04

最新評論