html5+canvas+純原生javascript+audio開發仙劍記憶力翻牌遊戲
阿新 • • 發佈:2019-01-29
感覺又是在發小白文,沒辦法,我還在不斷學習中。前端進階計劃再一次因為學習難度,專案經驗而告吹。
好在,我在緩慢進步~
文章內容來源我網路上看到別人用js和css3寫的仙劍記憶力翻牌遊戲,感覺自己可以學到些什麼。所以就有了一天一夜的奮鬥成果,寫的過程,感覺好坎坷,又是檢視canvas的API,又是設定相關變數,又得摸索坑爹費腦的遊戲邏輯!
說實話,人家那個玩的挺爽,想過很炫。換成我做得,不說了,去把他的網頁考下來參考參考。
說下游戲相關:滑鼠點選事件(根據卡牌顯示大小,確定滑鼠有效點選區域,觸發點選事件)
canvas繪圖(將座標分好的圖片載入進去)
計時器(使用瀏覽器運動API---requestAnimationFrame)我壓根不知道如何停止這貨
遊戲卡牌匹配有bug,效能也不咋滴,直接上程式碼
html頁面程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content=”width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0″ name=”viewport” /> <meta content=”yes” name=”apple-mobile-web-app-capable” /> <meta content=”black” name=”apple-mobile-web-app-status-bar-style” /> <meta content=”telephone=no” name=”format-detection” /> <title>js版仙劍翻牌記憶力遊戲</title> <link rel="stylesheet" type="text/css" href="css/memory.css"> <script type="text/javascript" src="js/memory.js"></script> </head> <body> <header id="memory"> <canvas id="show"></canvas> <audio id="astart" loop='loop'> <source id="as1" type="audio/ogg" src="music/start.ogg"> <source id="as2" type="audio/mpeg" src="music/start.mp3"> </audio> <audio id="afail" > <source id="af1" type="audio/ogg" src="music/fail.ogg"> <source id="af2" type="audio/mpeg" src="music/fail.mp3"> </audio> <audio id="asucess"> <source id="asu1" type="audio/ogg" src="music/success.ogg"> <source id="asu2" type="audio/mpeg" src="music/success.mp3"> </audio> <audio id="aclear"> <source id="ac" type="audio/ogg" src="music/clear.ogg"> <source id="ac2" type="audio/mpeg" src="music/clear.mp3"> </audio> </header> </body> </html>
css程式碼:可以忽略
body{margin:0;padding:0;background: url(../images/gamebg.jpg) no-repeat;}
header{width: 1000px;height: 600px;position: relative;top:0;left: 50%;margin-left: -575px;}
#show{background: #000;position: absolute;top:50%;left: 0;margin-top: -267px;}
js程式碼:有bug,大家看著解決吧
程式碼比較混亂,不管怎麼說都耗費了我接近20小時的時間,雖然不咋滴,也很小白,但我相信,只要我堅持,技術會好的,經驗會有的,麵包也會很多的。var canvas; var audio; window.requestAnimFrame=(function(){ return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { return window.setTimeout(callback, 1000 / 60); }; })();//自動執行函式 window.onload=function(){ canvas=document.getElementById('show');//畫布canvas astart=document.getElementById('astart');//音樂 afail=document.getElementById('afail');//音樂 asucess=document.getElementById('asucess');//音樂 aclear=document.getElementById('aclear');//音樂 canvas.width=1150; canvas.height=600;//畫布寬高 Card.init(); game(); astart.play(); } //遊戲重新整理函式 function game(){ Card.draw(); requestAnimFrame(game); } //牌物件類 var Card={ x:[], y:[],//圖片位置陣列 boardArr:[],//牌陣列 arr:[], num:8,//初始化為8 first:-1,//是否全部開牌 ctx:null,//畫筆 pic:null,//卡牌正面 bg:new Image(),//背面 tbg:new Image(),//剩餘時間 fail:new Image(), sucess:new Image(), img:null, k:null,//下一次開啟的圖片 l:null,//上一次點選開啟的圖片 click:true,//防止多次點選 lookNum:10,//記憶時間 playerTime:60,//遊戲時間 count:0,//遊戲成功判斷 flag:0,//0:正在執行 1:失敗 2:成功 //初始化 init:function(){ this.ctx=canvas.getContext('2d'); this.fail.src='./images/fail.png'; this.sucess.src='./images/success.png'; this.bg.src='./images/cardbg.jpg';//牌反面圖片地址 this.tbg.src='./images/sword.png';//遊戲時間背景圖片 var rom=Math.floor(Math.random()*(10-this.num)); for(var i=rom+1;i<this.num+rom+1;i++){ this.pic=new Image(); this.pic.src='./images/card'+i+'.jpg';//卡牌正面 this.boardArr.push({ca:this.pic,bg:this.bg,key:i,open:false});//圖片物件插入陣列 } // 二維陣列深度複製 this.extend(this.arr,this.boardArr); this.boardArr=this.arr.concat(this.boardArr); //陣列元素隨機排列 this.boardArr=this.shuffle(this.boardArr); this.boardArr.push({tbg:this.tbg});//遊戲時間背景圖片 this.boardArr.push({fail:this.fail});//遊戲失敗圖片 this.boardArr.push({sucess:this.sucess});//遊戲成功圖片 //圖片顯示位置 for(var m=0;m<8;m++){ for(var n=1;n<3;n++){ this.x.push(m*142); this.y.push(n*199); } } //遊戲時間圖片的位置 this.x.push(550); this.y.push(0); //遊戲失敗圖片 this.x.push(350); this.y.push(250); //成功圖片 this.x.push(350); this.y.push(250); this.isSame(); // 為了避免與介面重新整理定期器時間干擾,將時間倒計時定時器獨立出來 var timer=setInterval(function(){ Card.lookNum--; if(Card.lookNum<=0){ Card.playerTime--; if(Card.playerTime<=0){ this.flag=1; clearInterval(timer); } } },1000); }, //隨機洗牌函式 shuffle:function(arr){ var len = arr.length; for(var i = 0; i < len - 1; i++){ var idx = Math.floor(Math.random() * (len - i)); var temp = arr[idx]; arr[idx] = arr[len - i - 1]; arr[len - i -1] = temp; } return arr; }, //畫圖 draw:function(){ for(var i in this.boardArr){//起始圖片展示 if(Card.first==-1){ Card.img=Card.boardArr[i].ca; if(Card.lookNum<=0){ Card.first=0; return} } if(!this.boardArr[i].open&&Card.first==0){ this.img=this.boardArr[i].bg; if(Card.playerTime<=0){ this.boardArr[i].open=false; i==this.boardArr[i].length-2; Card.flag=1; Card.click=false; } }else{ this.img=this.boardArr[i].ca; } if(i<this.boardArr.length-3){ this.ctx.drawImage(this.img,this.x[i],this.y[i]);//畫出圖片 }else{ if(i==this.boardArr.length-3&&Card.playerTime>0&&this.flag==0){ this.img=this.boardArr[this.boardArr.length-3].tbg; this.ctx.drawImage(this.img,this.x[i],this.y[i]);//畫出圖片 } if(i==this.boardArr.length-2&&Card.playerTime<=0&&this.flag==1){ astart.pause(); aclear.pause(); afail.play();//失敗 this.img=this.boardArr[this.boardArr.length-2].fail; this.ctx.drawImage(this.img,this.x[i],this.y[i]);//畫出圖片 } if(i==this.boardArr.length-1&&Card.playerTime>0&&this.flag==2){ this.img=this.boardArr[this.boardArr.length-1].sucess; this.ctx.drawImage(this.img,this.x[i],this.y[i]);//畫出圖片 astart.pause(); aclear.pause(); asucess.play();//成功 } this.fontText(); } } }, //判斷是否相同 isSame:function(){ //滑鼠點選 if(Card.flag==0){ window.addEventListener('click',function(e){ if(Card.click){ Card.click=false; if(e.offSetX||e.layerX){//相容性寫法 //三元運算子 mx=e.offSetX==undefined?e.layerX:e.offSetX; my=e.offSetY==undefined?e.layerY:e.layerY; } for(var i in Card.boardArr){ if(parseFloat(mx)<=1150&&parseFloat(mx)>=0&&parseFloat(my)>=199&&parseFloat(my)<=600){ if(parseFloat(mx)>=parseFloat(Card.x[i])&&parseFloat(mx)<=parseFloat(Card.x[i])+142&&parseFloat(my)>=parseFloat(Card.y[i])&&parseFloat(my)<=parseFloat(Card.y[i])+199){ // 可以旋轉開啟 if(!Card.boardArr[i].open){ if(Card.k==null){ Card.k=i; this.img=Card.boardArr[i].ca; Card.boardArr[i].open=true; Card.click=true; return; } else if(Card.boardArr[i].key==Card.boardArr[Card.k].key){//相同圖片顯示 if(i==Card.k){return} this.img=Card.boardArr[i].ca; Card.boardArr[i].open=true; Card.k=null;//上一張圖片標誌 Card.click=true; Card.count++; astart.pause(); aclear.play(); if(Card.count==Card.num){Card.flag=2;}//成功 }else{//不同圖片都不顯示 this.img=Card.boardArr[i].ca; Card.boardArr[i].open=true; Card.l=i; setTimeout(function(){ if(!Card.k){return} this.img=Card.boardArr[Card.l].bg; this.img=Card.boardArr[Card.k].bg; Card.boardArr[Card.k].open=false; Card.boardArr[Card.l].open=false; Card.k=null;//上一張圖片標誌情況 Card.l=null; Card.click=true; },800); if(Card.count!=Card.num){Card.flag=1;}//失敗 } }else{//點選同一張圖片 Card.click=true; } } } } } }); } }, getType:function(o){ var _t; return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase(); }, extend:function(destination,source){ for(var p in source) { if(Card.getType(source[p])=="array"||Card.getType(source[p])=="object") { destination[p]=Card.getType(source[p])=="array"?[]:{}; arguments.callee(destination[p],source[p]); } else { destination[p]=source[p]; } } }, fontText:function(){ this.ctx.fillStyle="#000";//白色為例子; this.ctx.fillRect(735,40,180,22); this.ctx.beginPath(); this.ctx.font='20px Courier 微軟雅黑'; this.ctx.fillStyle='red'; if(this.lookNum<=0){this.ctx.fillText('遊戲剩餘時間 '+this.playerTime,740,60);return;} this.ctx.fillText('記憶時間倒計時 '+this.lookNum,740,60); this.ctx.closePath(); } }