微信小程序——用canvas做個(gè)層疊消融游戲(一)

本篇為小程序的一學(xué)習(xí)筆記竣稽,以一小游戲‘層疊消融’為例子囱怕,對(duì)canvas組件進(jìn)行展開學(xué)習(xí)霍弹。

開場(chǎng)白就沒了,直奔主題娃弓。先來看看小程序在組件使用上典格,對(duì)canvas做了什么。

em……台丛,首先钝计,指定了作為唯一標(biāo)識(shí)符的屬性canvas-id,因?yàn)樾〕绦虼盍艘惶譓V*框架齐佳,所以對(duì)于元素綁定這個(gè)私恬,和用原生的js的方式不同。然后就是一系列的手勢(shì)觸發(fā)事件炼吴。其他的本鸣,其實(shí)在使用上也沒做什么特別的處理嘛。既然如此硅蹦,那就直接貼上對(duì)canvas進(jìn)行元素綁定的代碼吧荣德。

<!-- canvas.wxml -->

<canvas canvas-id="testCanvas"></canvas>

<!-- canvas.js -->

Page({

????onReady: function(e) {

????????// 使用wx.createContext獲取繪圖上下文 context

????????var context = wx.createCanvasContext('testCanvas');

????????context.setStrokeStyle('#00ff00');

????????context.rect(0,0,200,200);

????????context.draw();

????}

})


因?yàn)樾〕绦虻腸anvas元素默認(rèn)寬高是不會(huì)覆蓋全屏的,所以在初始化canvas之后要進(jìn)行重新設(shè)置寬高童芹。屏幕的寬高可以通過API:wx.getSystemInfo獲得涮瞻。


接下來就是畫圖了〖偻剩‘層疊消融’這個(gè)游戲的主要效果就是圖片疊加部分雙數(shù)相消署咽。具體效果如圖:


上面的圖形由三個(gè)基本圖形(正方形)組成,用這三個(gè)基本圖形拼出上面的目標(biāo)圖案生音,則算通關(guān)宁否。

需求:多圖形相疊雙數(shù)相消。要實(shí)現(xiàn)這個(gè)效果缀遍,用傳統(tǒng)的css是很麻煩的慕匠,這時(shí)canvas的靈活性就體現(xiàn)出來了。canvas對(duì)圖片圖形的處理是像素級(jí)的域醇,其本身提供了一系列的圖形遮蓋策略台谊。globalCompositeOperation這個(gè)屬性設(shè)定了在畫新圖形時(shí)采用的遮蓋策略,其值是一個(gè)標(biāo)識(shí)12種遮蓋方式的字符串譬挚。其中‘xor’方式正能實(shí)現(xiàn)我們雙數(shù)相消的需求锅铅。

立即貼上主要的代碼:

//繪制一個(gè)反相圖案

let revert = function(path){

????this.context.beginPath();

????this.context.fillStyle="#000";

????this.context.globalCompositeOperation="xor";

????for(let i=0;i<path.length;i++){

????????if(i==0){

????????????this.context.moveTo(path[i].x,path[i].y);

????????}else{

????????????this.context.lineTo(path[i].x,path[i].y);

????????}

????}

????this.context.fill();

????return this;

}


(小程序的onReady函數(shù),這里具體的調(diào)用我打包了一下殴瘦,具體打包細(xì)節(jié)我就不再這里細(xì)講了)

onReady: function(){

????let canvasCtl = new this.canvasCtl();

????canvasCtl.init(this);

????let block1 = new util.block([{x:200,y:50},{x:100,y:150},{x:100,y:50}],canvasCtl);

????block1.initBlock();

????let block2 = new util.block([{x:150,y:70},{x:250,y:70},{x:250,y:200}],canvasCtl);

????block2.initBlock();

????let block3 = new util.block([{x:50,y:60},{x:110,y:60},{x:110,y:110},{x:50,y:110}],canvasCtl);

????block3.initBlock();

????this.blockList.push(block1);

????this.blockList.push(block2);

????this.blockList.push(block3);

},

效果圖如下:


既然是小游戲狠角,那就要會(huì)動(dòng)是不是号杠。需求:手指點(diǎn)上時(shí)蚪腋,選中圖片跟著移動(dòng)丰歌。

這時(shí),就要用上小程序給我們提供的手勢(shì)觸發(fā)了屉凯,用到的有這兩個(gè):


bindtouchstart用于判斷手指選中那個(gè)圖形立帖,bindtouchmove用于圖形移動(dòng)。

對(duì)于判定選中圖形這個(gè)問題悠砚,趕緊回憶起你的小學(xué)數(shù)學(xué):沿著判定點(diǎn)向圖形方向畫一條射線晓勇,若相交點(diǎn)為單數(shù),則判定點(diǎn)在圖形中灌旧,否則绑咱,判定點(diǎn)在圖形外。轉(zhuǎn)換為代碼模式如下:

block.prototype.checkPointInRegion = function(pt){

????let nCross = 0; // 定義變量枢泰,統(tǒng)計(jì)目標(biāo)點(diǎn)向右畫射線與多邊形相交次數(shù)

????for (let i = 0; i < this.path.length; i++) { //遍歷多邊形每一個(gè)節(jié)點(diǎn)

????????let p1 = this.path[i];

????????let p2 = this.path[(i+1)%this.path.length];

????????// p1是這個(gè)節(jié)點(diǎn)描融,p2是下一個(gè)節(jié)點(diǎn),兩點(diǎn)連線是多邊形的一條邊

????????// 以下算法是用是先以y軸坐標(biāo)來判斷的

????????if ( p1.y == p2.y )continue;//如果這條邊是水平的衡蚂,跳過

????????if ( pt.y < ((p1.y= ((p1.y>p2.y)?p1.y:p2.y))continue;//如果目標(biāo)點(diǎn)高于這個(gè)線段窿克,跳過

????????//那么下面的情況就是:如果過p1畫水平線,過p2畫水平線毛甲,目標(biāo)點(diǎn)在這兩條線中間

????????let x = (pt.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;

????????// 這段的幾何意義是 過目標(biāo)點(diǎn)年叮,畫一條水平線,x是這條線與多邊形當(dāng)前邊的交點(diǎn)x坐標(biāo)

????????if ( x > pt.x ) nCross++; //如果交點(diǎn)在右邊玻募,統(tǒng)計(jì)加一只损。這等于從目標(biāo)點(diǎn)向右發(fā)一條射線(ray),與多邊形各邊的相交(crossing)次數(shù)

????}

????if (nCross % 2 == 1) {

????????return true; //如果是奇數(shù)七咧,說明在多邊形里

????} else {

????????return false; //否則在多邊形外 或 邊上

????}

}

下面就是移動(dòng)了改执,canvas的圖形的移動(dòng)很粗暴,那就是擦掉舊的重新畫上新的坑雅。需要記錄下多次bindtouchmove觸發(fā)時(shí)手指的位移->計(jì)算出圖形移動(dòng)后的新定點(diǎn)坐標(biāo)->在畫布上擦掉舊圖形->根據(jù)新坐標(biāo)畫上新圖形辈挂。下面貼上主要代碼:

searchBlock:function(e){?

????if(this.movePath.length>10){?

?????????this.movePath.shift();?

?????}

?????this.movePath.push(e);

? ??for(let i = 0; i < this.blockList.length; i++){//讓新選中的圖形永遠(yuǎn)處于第一位

? ? ? if(this.blockList[i].checkPointInRegion({ x: e.touches[0].x , y:e.touches[0].y })){

? ? ? ? [this.blockList[0],this.blockList[i]] = [this.blockList[i],this.blockList[0]]

? ? ? };

? ? }

? },?

?moveBlock:function(e){

? ? if(this.movePath.length>10){

? ? ? this.movePath.shift();

? ? }

? ? this.movePath.push(e);

? ? let oldPath = this.movePath[this.movePath.length-2]?this.movePath[this.movePath.length-2]:null;

? ? let newPath = e;

? ? this.blockList[0].move(oldPath.touches[0],newPath.touches[0]);

? },

block.prototype.move = function(oldPath,newPath){

? ? if(oldPath){

? ? ? var x = newPath.x - oldPath.x;

? ? ? var y = newPath.y - oldPath.y;

? ? ? this.changeLocation(x,y);

? ? }

}


效果圖如下:


接下去就是通關(guān)判定、關(guān)卡設(shè)置裹粤、關(guān)卡選擇……有點(diǎn)多终蒂,這些內(nèi)容就留到下期吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遥诉,一起剝皮案震驚了整個(gè)濱河市拇泣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矮锈,老刑警劉巖霉翔,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異苞笨,居然都是意外死亡债朵,警方通過查閱死者的電腦和手機(jī)子眶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來序芦,“玉大人臭杰,你說我怎么就攤上這事⊙柚校” “怎么了渴杆?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)宪塔。 經(jīng)常有香客問我磁奖,道長(zhǎng),這世上最難降的妖魔是什么某筐? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任点寥,我火速辦了婚禮,結(jié)果婚禮上来吩,老公的妹妹穿的比我還像新娘敢辩。我一直安慰自己,他們只是感情好弟疆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布戚长。 她就那樣靜靜地躺著,像睡著了一般怠苔。 火紅的嫁衣襯著肌膚如雪同廉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天柑司,我揣著相機(jī)與錄音迫肖,去河邊找鬼。 笑死攒驰,一個(gè)胖子當(dāng)著我的面吹牛蟆湖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玻粪,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼隅津,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了劲室?” 一聲冷哼從身側(cè)響起伦仍,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎很洋,沒想到半個(gè)月后充蓝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年谓苟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了官脓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娜谊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斤讥,到底是詐尸還是另有隱情纱皆,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布芭商,位于F島的核電站派草,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏铛楣。R本人自食惡果不足惜近迁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望簸州。 院中可真熱鬧鉴竭,春花似錦、人聲如沸岸浑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)矢洲。三九已至璧眠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間读虏,已是汗流浹背责静。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盖桥,地道東北人灾螃。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像揩徊,于是被迫代替她去往敵國(guó)和親睦焕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345