国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - vue+canvas實現拼圖小游戲

vue+canvas實現拼圖小游戲

2021-09-29 15:18膠帶小車 JavaScript

這篇文章主要為大家詳細介紹了vue+canvas實現拼圖小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

利用 vue+canvas 實現拼圖小游戲,供大家參考,具體內容如下

思路步驟

  • 一個拼圖拼盤和一個原圖參照
  • 對原圖的切割以及隨機排序
  • 通過W/A/D/S或上下左右進行移動
  • 難度的自主選擇
  • 對拼圖是否完成的判定

JS實現部分

數據分析

  • row:拼圖的總行數;column:拼圖的總列數。 (用來設置拼圖難度,也是每個拼圖塊寬高的設置規則)
  • pic[{x,y,row,column,index}]:小拼圖的集合,其內元素為小拼圖的數據結構。 (x、y:拼圖塊在canvas的繪制規則,初始化后不會進行改變;row、column:對原圖進行切割并繪制的規則;index:用來判定是否完成拼圖的規則之一,繪制空白塊的規則,其中空白塊的index=-1)
  • num:隨機排列的次數。
  • sign:空白塊在拼圖集合 pic 中的索引。 (數字類型,用來定位空白塊,跟隨空白塊的移動而變化,是進行移動的規則之一;默認為:15)
  • isWin:用來判斷是否完成拼圖的條件。 (布爾類型,默認為false)
  • step:表示移動的有效步數。 (數字類型,默認為0,重新游戲及完成游戲會清零)
  • maskShow: 編輯游戲 的判定條件。 (布爾類型,用來顯示與隱藏編輯游戲的對話框,默認為false)

方法分析

拼圖集合 pic 的初始化及隨機排列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
randomHandler() {
 // pic的初始化
 for(let i=0;i<this.row*this.column;i++) {
 // 設置切割后每個小圖片的位置
 let row = parseInt(i/this.row);
 let column = i - row*this.column;
 // 對在canvas的排列進行初始化,后續不會進行改變
 let x = parseInt(i/this.row);
 let y = i - x*this.column;
 this.pic[i] = {...this.pic[i],x:x,y:y,row:row,column:column,index:i};
 // 設置最后一個元素為空白塊,index = -1
 if(i == (this.row*this.column-1)) {
  this.pic[i] = {...this.pic[i],row:row,column:column,index:-1};
 }
 }
 // 隨機排列 pic集合
 for(let i=0;i<this.num;i++) {
 let ran1,ran2,temp={};
 // 隨機獲取0-14
 ran1 = parseInt((this.row*this.column-1)*Math.random())
 ran2 = parseInt((this.row*this.column-1)*Math.random())
 temp.row = this.pic[ran1].row
 temp.column = this.pic[ran1].column
 this.pic[ran1] = {...this.pic[ran1],row:this.pic[ran2].row,column:this.pic[ran2].column}
 this.pic[ran2] = {...this.pic[ran2],...temp}
 }
}

拼圖的繪制 (根據得到的隨機 pic 集合進行繪制)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
drawHandler() {
 // 獲取 canvas DOM元素
 let canvas = this.$refs.can;
 let ctx = canvas.getContext('2d');
 canvas.width = 400;
 canvas.height = 400;
 ctx.clearRect(0,0,400,400);
 // 每個小拼圖的寬高,根據canvas的寬高和拼圖行數row列數column來動態設置
 // 是進行難度動態設置的唯一方式
 let width = canvas.width/this.column;
 let height = canvas.width/this.row;
 // 必須通過 Image 構造函數動態創建,若是通過獲取 DOM 節點,則onload只執行一次,無法進行移動
 let img = new Image();
 img.src = require('../../public/image/test.png');
 img.onload = () => {
 for(let i=0;i<this.row*this.column;i++) {
  // 繪制到canvas的各元素的起始坐標
  let dx = this.pic[i].y * width;
  let dy = this.pic[i].x * height;
  // 對圖片進行切割的起始點坐標
  let cx = this.pic[i].column * width;
  let cy = this.pic[i].row * height;
  // 參數:img圖片,切割的起始點坐標,切割的寬高,繪制的起始點坐標,繪制的寬高
  ctx.drawImage(img,cx,cy,width,height,dx,dy,width,height);
  if(this.pic[i].index == -1) {
  this.sign = i;
  ctx.clearRect(dx,dy,width,height);
  }
 }
 }
}

其中 img 必須通過 Image 構造函數動態創建

拼圖的移動

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 在 mounted 鉤子進行鍵盤的監聽事件
mounted() {
 this.newGame();
 document.onkeydown = (event) => {
 let key = event.keyCode;
 if(key==38 || key==87) this.moveHandler('up');
 else if (key==40 || key==83 ) this.moveHandler('down');
 else if (key==37 || key==65 ) this.moveHandler('left');
 else if (key==39 || key==68 ) this.moveHandler('right');
 }
 }
methods: {
 moveHandler(dir) {
 // re:空白塊根據方向最終需移動到的位置索引
 let re,temp = {};
 if(dir == 'up' && this.pic[this.sign].x>0) {
 // 根據空白塊的row和column推算出上面一塊圖片的序號
 // 在將兩個圖片快進行互換位置,及交換row、column、index
 // 重新賦值this.sign(標志著空白塊的序號:默認15)
 re = (this.pic[this.sign].x-1) * this.row + this.pic[this.sign].y;
 temp.row = this.pic[re].row;
 temp.column = this.pic[re].column;
 temp.index = this.pic[re].index;
 this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
 this.pic[this.sign] = {...this.pic[this.sign],...temp};
 this.step = this.step + 1;
 }
 else if(dir == 'down' && this.pic[this.sign].x<this.row-1) {
 re = (this.pic[this.sign].x+1) * this.row + this.pic[this.sign].y;
 temp.row = this.pic[re].row;
 temp.column = this.pic[re].column;
 temp.index = this.pic[re].index;
 this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
 this.pic[this.sign] = {...this.pic[this.sign],...temp};
 this.step = this.step + 1;
 }
 else if(dir == 'left' && this.pic[this.sign].y>0) {
 re = (this.pic[this.sign].x) * this.row + this.pic[this.sign].y-1;
 temp.row = this.pic[re].row;
 temp.column = this.pic[re].column;
 temp.index = this.pic[re].index;
 this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
 this.pic[this.sign] = {...this.pic[this.sign],...temp};
 this.step = this.step + 1;
 }
 else if(dir == 'right' && this.pic[this.sign].y<this.column-1) {
 re = (this.pic[this.sign].x) * this.row + this.pic[this.sign].y+1;
 temp.row = this.pic[re].row;
 temp.column = this.pic[re].column;
 temp.index = this.pic[re].index;
 this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
 this.pic[this.sign] = {...this.pic[this.sign],...temp};
 this.step = this.step + 1;
 }
 // 重新繪制拼圖,也可以通過計算只重新繪制移動的部分區域
 this.drawHandler();
 }
}

完成拼圖的判定

?
1
2
3
4
5
6
7
8
9
10
isWinHandler() {
 // 通過比較所有元素的x、y和row、column是否相等即可,也可以通過index來判斷
 for(let i=0;i<this.row*this.column;i++) {
 if(this.pic[i].x == this.pic[i].row && this.pic[i].y == this.pic[i].column) {
  // 顯示成功的狀態以及清空步數
  this.isWin = true;
  this.step = 0;
 }
 }
}

重新游戲

?
1
2
3
4
5
6
7
8
newGame() {
 // 在 mounted 鉤子進行
 // 隱藏完成狀態,清空步數,獲取隨機排列,繪制拼圖模塊
 this.isWin = false;
 this.step = 0;
 this.randomHandler();
 this.drawHandler();
 }

JS總合

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<script>
export default {
 data() {
 return {
 // row:拼圖的總行數,column:拼圖的總列數
 row:2,
 column:2,
 // 隨機打亂的次數
 num:100,
 // pic:拼圖的所有子集和;
 // 元素:index:子圖片的位置編號
 // row/column:對原圖分割后的橫縱編號
 // x/y:在canvas中的坐標位置(不會改變)
 pic:[{x:0,y:0,row:0,column:0,index:0}],
 sign:15,
 isWin: false,
 step:0,
 maskShow:false
 }
 },
 mounted() { 代碼在拼圖移動模塊中 },
 methods: {
 // 判斷是否完成拼圖
 isWinHandler() { ... },
 // 移動的函數方法
 moveHandler(dir) { ... },
 // 繪制拼圖
 drawHandler() { ... },
 // 獲取隨機排序
 randomHandler() { ... },
 newGame() { ... }
}
</script>

HTML部分

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
 <div class="index">
 <div class="contain">
 <canvas class="can" ref="can"></canvas>
 <!-- 完成拼圖的狀態顯示 -->
 <div v-if="isWin" class="win">游戲勝利!</div>
 <div class="btns">
 <span @click="newGame">重新游戲</span>
 <span @click="maskShow = true">編輯游戲</span>
 <span @click="isWinHandler">檢驗</span>
 <span>{{step}}</span>
 </div>
 <!-- 點擊編輯游戲的彈出框 -->
 <div v-show="maskShow" class="mask">
 行:<input type="text" v-model="row" placeholder="請輸入行數">
 列:<input type="text" v-model="column" placeholder="請輸入列數">
 <button @click="maskShow = false">完成</button>
 </div>
 </div>
 <img ref="img" class="img" src="../../public/image/test.png" alt="error">
 </div>
</template>

CSS部分

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<style scoped>
/* 編輯的彈出框 */
.mask {
 width: 200px;
 height: 200px;
 background-color: rosybrown;
 position: absolute;
 left: 510px;
 top: 0;
}
/* 按鈕樣式 */
.btns > span {
 display: inline-block;
 width: 80px;
 font-size: 12px;
 height: 24px;
 text-align: center;
 line-height: 24px;
 margin-bottom: 5px;
 background-color: thistle;
 cursor: pointer;
}
/* 右側按鈕區 */
.btns {
 width: 80px;
 height: 400px;
 border: 1px solid tan;
 border-radius: 5px;
 background-origin: border-box;
 padding: 5px;
 position: absolute;
 left: 412px;
 top: 0;
}
/* 完成拼圖的狀態 */
.win {
 width: 402px;
 height: 402px;
 line-height: 402px;
 text-align: center;
 font: 24px;
 opacity: 0.5;
 background-color: paleturquoise;
 position: absolute;
 top: 0;
 left: 0;
}
.img {
 display: inline-block;
}
/* canvas */
.can {
 border: 1px solid teal;
}
/* canvas容器 */
.contain {
 position: relative;
}
</style>

最終的完成結果圖

vue+canvas實現拼圖小游戲

代碼地址:拼圖游戲

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/yunpuY/article/details/108600068

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青青在线精品视频 | 日本精品一区二区三区视频 | 尤物视频在线观看 | 亚洲精品久久久久久下一站 | 亚洲欧美在线一区 | 欧美三区二区一区 | 中文在线视频 | 噜噜噜在线观看免费视频日本 | 欧美日韩一级电影 | 福利视频网 | 成人狠狠色综合 | 日本一区二区不卡在线观看 | 紧缚调教一区二区三区视频 | 午夜小视频在线观看 | 国产精品九九九 | 中文字幕日韩欧美 | 伊人av成人 | 日韩免费在线 | 亚洲国产精品久久久久秋霞蜜臀 | 久久国产精品久久精品国产演员表 | 欧美日韩不卡 | 国产97在线 | 免费 | 欧美激情国产日韩精品一区18 | 色网站在线观看 | 91视频网页版 | 精品一区二区不卡 | 日本成人网址 | 亚洲欧洲自拍 | 黄色动漫在线观看 | 久草在线| 国产视频在线播放 | 精品一区二区三区中文字幕老牛 | 国产成人自拍视频在线观看 | 先锋影音av资源站 | 日本精品视频在线观看 | 黄色美女视频网站 | 婷婷在线免费视频 | 国产精品一区二区久久 | 亚洲精品日韩激情在线电影 | 91天堂网| 精品久久久久久久久久久下田 |