微信小程序使用canvas2d实现拼图游戏

发布时间 2023-04-20 20:43:54作者: 四个春天

根据周文洁微信小程序开发实战编写,但是微信更新了canvas接口,按照书上写的已经不能使用了。

目录

 

改进后如下:

app.wxss:

 1 .container {
 2   height: 100vh;
 3   color: #E64340;
 4   font-weight: bold;
 5   display: flex;
 6   flex-direction: column;
 7   align-items: center;
 8   justify-content:space-evenly;
 9 }
10 .title{
11   font-size: 18pt;
12 }
View Code

index.wxml:

1 <view class="container">
2   <view class="title">游戏选关</view>
3   <view class="level">
4     <view class="box" wx:for="{{levels}}" wx:key="level{{index}}" bindtap="choolLevel" data-level="{{item}}">
5       <image src="/images/{{item}}" mode=""/>
6       <text>第{{index+1}}关</text>
7     </view>
8   </view>
9 </view>
View Code

index.wxss:

 1 .level{
 2   width: 100%;
 3 }
 4 .box{
 5   width: 50%;
 6   float: left;
 7   margin: 25rpx 0;
 8   display: flex;
 9   flex-direction: column;
10   align-items: center;
11 }
12 image{
13   width: 260rpx;
14   height: 260rpx;
15 }
View Code

index.js:

 1   data: {
 2     levels:[
 3       'pic01.jpg',
 4       'pic02.jpg',
 5       'pic03.jpg',
 6       'pic04.jpg',
 7       'pic05.jpg',
 8       'pic06.jpg',
 9     ]
10   },
11   choolLevel:function(e){
12     let level=e.currentTarget.dataset.level;
13     wx.navigateTo({
14       url: '../game/game?level='+level,
15     })
16   },
View Code

games.wxml:

1 <view class="container">
2   <view class="title">提示图</view>
3   <image src="{{url}}" />
4   <canvas canvas-id="my-canvas" id="my-canvas" type="2d" bindtouchstart="touchBox" />
5   <button type="warn" bindtap="reset">重新开始</button>
6   <button type="primary" bindtap="help">帮助</button>
7 </view>
View Code

games.wxss:

1 image{
2   width: 250rpx;
3   height: 250rpx;
4 }
5 canvas{
6   border: 1rpx solid;
7   width: 300px;
8   height: 300px;
9 }
View Code

最重要的是games.js:

  1 var num=[
  2   ['00','01','02'],
  3   ['10','11','12'],
  4   ['20','21','22']
  5 ];
  6 var w=100;
  7 var url='/images/pic01.jpg';
  8 Page({
  9   data: {
 10     isWin:false
 11   },
 12   onLoad(options) {
 13     url='/images/'+options.level;
 14     this.setData({url:url});
 15     
 16     this.shuffle();
 17     this.drawCanvas();
 18   },
 19   shuffle:function(){
 20     num=[
 21       ['00','01','02'],
 22       ['10','11','12'],
 23       ['20','21','22']
 24     ];
 25     var row=2;
 26     var col=2;
 27     for (var i = 0; i < 100; i++) {
 28       var direction=Math.round(Math.random()*3);
 29       if(direction==0){
 30         if(row!=0){
 31           num[row][col]=num[row-1][col]
 32           num[row-1][col]='22';
 33           row-=1;
 34         }
 35       }else if (direction==1){
 36         if(row!=2){
 37           num[row][col]=num[row+1][col]
 38           num[row+1][col]='22';
 39           row+=1;
 40         }
 41       }else if (direction==2){
 42         if(col!=0){
 43           num[row][col]=num[row][col-1]
 44           num[row][col-1]='22';
 45           col-=1;
 46         }
 47       }else if (direction==3){
 48         if(col!=2){
 49           num[row][col]=num[row][col+1]
 50           num[row][col+1]='22';
 51           col+=1;
 52         }
 53       }
 54     }
 55   },
 56   drawCanvas:function(){
 57     //新方法
 58     const query = wx.createSelectorQuery(); 
 59     query.select('#my-canvas')
 60     .fields({ node: true, size: true }).exec((res) => {
 61           const canvas = res[0].node;
 62           const ctx = canvas.getContext('2d');
 63           ctx.clearRect(0,0,300,300);
 64           
 65           //生成图片
 66           for (let i = 0; i < 3; i++) {
 67             for (let j = 0; j < 3; j++) {
 68               if(num[i][j]!='22'){
 69                 let row=parseInt(num[i][j]/10);
 70                 let col=num[i][j]%10;
 71 
 72                 const img = canvas.createImage();
 73                 img.src=url;
 74                 img.onload = () => {
 75                   ctx.drawImage(img, col*w, row*w, w, w, j*w, i*w/2, w, 50);
 76                 }
 77 
 78               }
 79             }
 80           }
 81         })
 82   },
 83   //移动拼图
 84   touchBox:function(e){
 85     if(this.data.isWin) return;
 86     var x=e.changedTouches[0].x;
 87     var y=e.changedTouches[0].y;
 88 
 89     var row=parseInt(y/w);
 90     var col=parseInt(x/w);
 91 
 92     if(num[row][col]!='22'){
 93       this.moveBox(row,col);
 94     }
 95     this.drawCanvas();
 96     if(this.Win()){
 97       wx.createSelectorQuery()
 98       .select('#my-canvas')
 99       .fields({ node: true, size: true })
100       .exec(res=>{
101         let ctx2 = res[0].node.getContext('2d');
102         let canvas2 = res[0].node;
103         // 通过设备的像素比等重新绘制宽高
104         const dpr = wx.getSystemInfoSync().pixelRatio
105           canvas2.width = res[0].width * dpr
106           canvas2.height = res[0].height * dpr
107           ctx2.scale(dpr, dpr)
108           ctx2.font="30px Arial";
109           ctx2.fillText("笨蛋",10,150);
110       })
111 
112     }
113   },
114   //具体移动函数
115   moveBox:function(i,j){
116     if(i>0){
117       //方块在上边
118       if(num[i-1][j]=='22'){
119         num[i-1][j]=num[i][j];
120         num[i][j]='22';
121         return;
122       }
123     }
124     if(i<2){
125       //方块在下边
126       if(num[i+1][j]=='22'){
127         num[i+1][j]=num[i][j];
128         num[i][j]='22';
129         return;
130       }
131     }
132     if(j>0){
133       //方块在左边
134       if(num[i][j-1]=='22'){
135         num[i][j-1]=num[i][j];
136         num[i][j]='22';
137         return;
138       }
139     }
140     if(j<2){
141       //方块在左边
142       if(num[i][j+1]=='22'){
143         num[i][j+1]=num[i][j];
144         num[i][j]='22';
145         return;
146       }
147     }
148   },
149   Win:function(){
150     for (let t = 0; t < 3; t++) {
151       for (let v = 0; v < 3; v++) {
152         if(num[t][v]!=t*10+v){
153           return false;
154         }
155       }
156     }
157     return true;
158   },
159   reset:function(){
160     this.shuffle();
161     this.drawCanvas();
162   },
163   help:function(){
164     num=[
165       ['00','01','02'],
166       ['10','11','12'],
167       ['20','22','21']
168     ];
169     this.Win();
170     this.drawCanvas();
171   },
172 
173   //生命周期函数--监听页面初次渲染完成
174   onReady() {},
175
176   //生命周期函数--监听页面显示
177   onShow() {},
178 
179   //生命周期函数--监听页面隐藏
180   onHide() {},
181 
182   //生命周期函数--监听页面卸载
183   onUnload() {},
184 
185   //页面相关事件处理函数--监听用户下拉动作
186   onPullDownRefresh() {},
187 
188   //页面上拉触底事件的处理函数
189   onReachBottom() {},
190 
191   //用户点击右上角分享
192   onShareAppMessage() {}
193 })

微信的 wx.createCanvasContext('myCanvas')方法已经弃用 改为了wx.createSelectorQuery()

官方文档讲的太模糊压根看不明白。

这个Demo主要是通过改变数组元素的位置来实现拼图的位置变换的,所以只要对点击的图片判断白色方块是否在它的四周就可以了。

变换完数组的位置后,重新绘图,来改变图片在页面中的位置。

我觉得绘图主要的函数为 : 

ctx.drawImage(img, col*w, row*w, w, w, j*w, i*w/2, w, 50);

drawImage()函数和其中的参数定义了绘图的位置大小等等。

页面效果: