周末手痒,试了试微信小游戏的开发,写个俄罗斯方块。
先创建画布:
/**
* 俄罗斯方块
* @author wxh
*/
wx.tmGlobal = {
name:"清新俄罗斯方块"
};
wx.tmGlobal.sysInfo = wx.getSystemInfoSync();
//console.log("sysInfo:",wx.tmGlobal.sysInfo);
wx.tmGlobal.canvas = wx.createCanvas();
wx.tmGlobal.context = wx.tmGlobal.canvas.getContext('2d');
可怜,连按钮都要自己绘制到画布上,wx框架为何不提供一个函数绘制普通按钮,只有一个wx.createUserInfoButton函数可以绘制一个用户授权按钮。准备用来获取微信用户账号,上传积分:
var button = wx.createUserInfoButton({
type: 'image',
image:"images/upload.png",
style: {
left: wx.tmGlobal.canvas.width-45,
top: wx.tmGlobal.sysInfo.statusBarHeight + 40,
width: 40,
height: 40,
//lineHeight: 40,
backgroundColor: 'blue',
color: 'white',
textAlign: 'center',
//fontSize: 16,
borderRadius: 4
}
});
button.show();
button.onTap((res) => {
wx.showModal({
title: '',
content: JSON.stringify(res)
});
//console.log(res);
});
按钮的图标,这里有雷锋:https://www.iconfont.cn
再绘制棋盘格子,然后用timer让当前block往下掉:
g_timer = setInterval(function () {
if (g_status != "run") return;
tryMoveBlock('down');
}, t);
在模拟器中看起来都ok,但是在android实体机中,就出现了花屏:
哦,一般的游戏,为了避免闪烁,都会搞个双buffer,或者双画布,先在背景的画布中绘制好(多次擦除、绘制),然后一次贴到前景画布上。微信小游戏中如何做呢?
看文档,说还可以创建第2个第3个...canvas,叫“离屏画布”,不会显示出来。于是搞一个:
wx.tmGlobal.bkgCanvas = wx.createCanvas();
wx.tmGlobal.bkgContext = wx.tmGlobal.bkgCanvas.getContext('2d');
背景画布先反复擦除,绘制,然后一次贴出来:
function updateCanvas(){
wx.tmGlobal.context.clearRect(0, 0, wx.tmGlobal.canvas.width, wx.tmGlobal.canvas.height);
wx.tmGlobal.context.drawImage(wx.tmGlobal.bkgCanvas,0,0,
wx.tmGlobal.canvas.width,wx.tmGlobal.canvas.height);
}
注意,clearRect是必须的,否则会花屏。
扫描二维码关注公众号,回复:
11211736 查看本文章
如何擦除一个格子呢?
我是在棋盘背景图和格子绘制完毕后,用g_bkgImageData把画布数据保存起来:
function drawQiPan() {
wx.tmGlobal.bkgContext.fillStyle = "white";
wx.tmGlobal.bkgContext.font = "16px Arial";
wx.tmGlobal.bkgContext.fillText(wx.tmGlobal.name, 5+g_gap*4+5, wx.tmGlobal.sysInfo.statusBarHeight+25);
wx.tmGlobal.bkgContext.drawImage(image_bkg, g_margin.left, g_margin.top,
wx.tmGlobal.bkgCanvas.width - g_margin.left - g_margin.right,
wx.tmGlobal.bkgCanvas.height - g_margin.top - g_margin.bottom);
wx.tmGlobal.bkgContext.strokeStyle = "gray";
//画纵线
for (let col = 0; col <= g_colCount; col++) {
wx.tmGlobal.bkgContext.moveTo(g_margin.left + (col + 1) * g_gap,
g_margin.top + g_gap);
wx.tmGlobal.bkgContext.lineTo(g_margin.left + (col + 1) * g_gap,
g_margin.top + g_gap+g_rowCount * g_gap);
}
wx.tmGlobal.bkgContext.stroke();
//画外框
wx.tmGlobal.bkgContext.strokeRect(g_margin.left + g_gap-3, g_margin.top + g_gap-3,
g_colCount * g_gap+6,
g_rowCount * g_gap+6
);
//保存完整背景图,用于局部恢复
g_bkgImageData = wx.tmGlobal.bkgContext.getImageData(0,0,
wx.tmGlobal.bkgCanvas.width,wx.tmGlobal.bkgCanvas.height);
}
擦除格子cell时,从g_bkgImageData 取出原来的一块,用putImageData贴上去:
//获取大背景图的一个局部
function getBackgroundCell(x,y,w,h){
let data=wx.tmGlobal.bkgContext.createImageData(w,h);//new Array(w*h*4);
for(let c=0;c<w;c++){
for(let r=0;r<h;r++){
var p1 = (r * w + c)*4;
var p2 = ((y+r) * wx.tmGlobal.canvas.width + x+c)*4;
data.data[p1+0] = g_bkgImageData.data[p2+0]; //red
data.data[p1+1] = g_bkgImageData.data[p2+1]; //green
data.data[p1+2] = g_bkgImageData.data[p2+2]; //blue
data.data[p1+3] = g_bkgImageData.data[p2+3]; //alpha
}
}
return data;
}
function eraseCell_xy(x, y) {
let imgData=getBackgroundCell(x, y, g_gap, g_gap);
wx.tmGlobal.bkgContext.putImageData(imgData,x,y);
}
效果: