首页 > 代码库 > [原创]html5游戏_五线谱打音符

[原创]html5游戏_五线谱打音符

html5手机游戏—五线谱打音符

1.[用五线谱打唱名]

2.[用唱名五线谱]

3.[无限练习模式]

用来熟悉五线谱上音符的位置

代码不难,这回注释还是有认真写的[只是废代码没有全部删除。。。]

效果图:

技术分享

技术分享

技术分享

---

在线地址:

http://wangxinsheng.herokuapp.com/staffgame

---

代码:

index.html

 1 <!DOCTYPE html> 2 <html> 3     <head> 4         <meta charset="utf-8"> 5         <meta name="description" content="html5 staff game"> 6         <meta name="keywords" content="staff,html5,canvas,web,game"> 7         <meta name="author" content="WangXinsheng"> 8         <meta name="apple-mobile-web-app-capable" content="yes"> 9         <meta name="apple-mobile-web-app-status-bar-style" content="black">10         <meta name="viewport" id="viewport" content="width = device-width, initial-scale = 1, minimum-scale = 1, maximum-scale = 1, user-scalable=no">11         <meta http-equiv="X-UA-Compatible" content="chrome=1">12         <meta http-equiv="Pragma" content="no-cache">13         <meta http-equiv="Cache-Control" content="no-cache">14         <meta equiv="Expires" content="0">15         <meta http-equiv="content-script-type" content="text/javascript">16         <link type="image/x-icon" rel="shortcut icon" href="img/staffFavicon.ico" />17         <title>CopyRight&copy;WangXinsheng</title>18         <script src="requestNextAnimationFrame.js"></script>19         <style type="text/css">20          html {color:#000;background:#fff;margin:0px;}21          body {-webkit-user-select:none;margin:0px;}22         #gameWorld{cursor:pointer;}23         #btn_start{color:red;font-size:40px;font-weight:bold;z-index:999;background:#fff;text-align:center;overflow:hidden;}24         #btn_start p {vertical-align:middle;cursor:pointer;background:yellow;margin:20px 0px;}25         #scoreC,#lx{width:100%;color:red;font-size:20px;font-weight:bold;z-index:999;display:none;cursor:pointer;}26         #btn_start #copy {font-size:15px;vertical-align:middle;cursor:pointer;background:white;color:blue;}27         </style>28     </head>29     <body>30     <section>31         <div style=‘position:absolute;left:0px;top:0px;width:100%;height:100%‘ id=‘btn_start‘>32             <p id=‘s1‘ onclick=‘javascript:staffGameGo(0,false);‘>五线谱打唱名</p>33             <p id=‘s2‘ onclick=‘javascript:staffGameGo(1,false);‘>唱名打五线谱</p>34             <p id=‘s3‘ onclick=‘javascript:staffGameGo(0,true);‘>无限练习<br />五线谱打唱名</p>35             <p id=‘s4‘ onclick=‘javascript:staffGameGo(1,true);‘>无限练习<br />唱名打五线谱</p>36             <p id=‘copy‘>powered by 王欣盛<br />2015/01/22+1+1<br />wangxsh42@126.com</p>37         </div>38         <div style=‘position:absolute;left:0px;top:0px;‘ id=‘scoreC‘>39         </div>40         <div style=‘position:absolute;left:0px;top:0px;‘ id=‘lx‘>41         </div>42         <canvas id="gameWorld" style="position: absolute; left: 0px; top: 0px;">43             <p>You need a modern browser to view this.</p>44         </canvas>45         <canvas id="gameWorldTouch" style="position: absolute; left: 0px; top: 0px;display:none;">46         </canvas>47     </section>48     </body>49     <script src="staffGame.js"></script>50 </html>

staffGame.js

  1 ;  2 var debug = true;  3 var gameWorld = function (mode,goOn) {  4     //this.mode = mode;  5     /*function init params*/  6     function doVarInit() {  7         //总线数  8         allLine = gyj.x + dyj.x + gy.x + dy.x + doo.x;  9         //总间数 10         allGap = gyj.j + dyj.j + gy.j + dy.j + doo.j; 11         if(debug) 12             console.log("总线数 "+allLine,"总间数 "+allGap); 13         jxObjLst=[]; 14         djBtnLst=[]; 15         circleDoLst=[]; 16         wxpDoLst=[]; 17     } 18     /*function on resize the window*/ 19     function doSize() { 20         if(!picIsLoaded()){setTimeout(doSize,200);} 21         document.getElementById("gameWorldTouch").style.display="block"; 22         caW = window.innerWidth; 23         caH = window.innerHeight; 24         caObj.width = caW; 25         caObj.height = caH; 26         caObj.style.width = caW + "px"; 27         caObj.style.height = caH + "px"; 28         caTObj.width = caW; 29         caTObj.height = caH; 30         caTObj.style.width = caW + "px"; 31         caTObj.style.height = caH + "px"; 32         bdjPX =Math.floor( caW / 80); 33         lastFpsUpdateTime = new Date; 34         lastFpsUpdateTimeBDJ = new Date; 35         score = 0; 36         wrong = 0; 37         /*线宽,间宽计算*/ 38         //1/3为五线谱,或按钮 39         buttonH = parseInt(caH / 3); 40         if(mode==0){ 41             //五线谱 高度 42             buttonH = parseInt(caH / 3 * 2); 43             //线宽为间宽的0.5 44             lineW = parseInt(buttonH / (allGap*2+allLine)); 45             //间宽 46             gapW = lineW * 2; 47             /*线等高于间 补丁,线太细就太难点中了*/ 48             lineW = parseInt(buttonH / (allGap+allLine)); 49             gapW = lineW; 50             //最高音 51             highest = gyj.x + gyj.j + gy.x + gy.j; 52             //最低音 53             low = dyj.x + dyj.j + dy.x + dy.j; 54  55             if(debug) 56                 console.log("线宽 "+lineW,"间宽 "+gapW); 57             wxpO = new wxp(caH,caW,buttonH,gyj,dyj,gy,dy,doo,allLine,allGap,lineW,gapW,mode,picsLst); 58             wxpO.draw(caCt); 59             //gen("circleDo"); 60  61             /*生成间线对象列表*/ 62             if(debug)console.log("线间对象列表---Start"); 63             var nowTop = caH - (lineW * allLine + gapW * allGap) + 0.5; 64             var high = 0; 65             // 高音谱上加 66             var base = gy.x + gy.j; 67             for(i=gyj.x+gyj.j;i>=1;i--){ 68                 if(i%2==0){ 69                     high = lineW; 70                 }else{ 71                     high = gapW; 72                 } 73                 jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"}); 74                 if(debug)console.log("gyj: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap")); 75                 nowTop += high; 76             } 77             // 高音谱 78             base = 0; 79             for(i=gy.x+gy.j;i>=1;i--){ 80                 if(i%2==0){ 81                     high = lineW; 82                 }else{ 83                     high = gapW; 84                 } 85                 jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"}); 86                 if(debug)console.log("gy: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap")); 87                 nowTop += high; 88             } 89             // doo 90             jxObjLst.push({"v":0,"top":nowTop,"high":lineW,"type":"Line"}); 91             if(debug)console.log("doo: v "+0,"top "+nowTop,"high "+lineW,"type "+"Line"); 92             nowTop += lineW; 93             // 低音谱 94             base = 0; 95             for(i=1;i<=dy.x+dy.j;i++){ 96                 if(i%2==0){ 97                     high = lineW; 98                 }else{ 99                     high = gapW;100                 }101                 jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});102                 if(debug)console.log("dy: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));103                 nowTop += high;104             }105             // 低音谱下加106             base = -dy.x-dy.j;107             for(i=1;i<=dyj.x+dyj.j;i++){108                 if(i%2==0){109                     high = lineW;110                 }else{111                     high = gapW;112                 }113                 jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});114                 if(debug)console.log("dyj: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));115                 nowTop += high;116             }117             if(debug)console.log("线间对象列表---End");118 119         }else if(mode==1){120             /*五线谱*/121             //五线谱 高度122             buttonH = parseInt(caH / 3 * 2);123             //线宽为间宽的0.5124             lineW = parseInt(buttonH / (allGap*2+allLine));125             //间宽126             gapW = lineW * 2;127             /*线等高于间 补丁,线太细就太难点中了*/128             lineW = parseInt(buttonH / (allGap+allLine));129             gapW = lineW;130             //最高音131             highest = gyj.x + gyj.j + gy.x + gy.j;132             //最低音133             low = dyj.x + dyj.j + dy.x + dy.j;134             //五线谱最左边135             wxpDoLeft = gapW * 6;136 137             if(debug)138                 console.log("线宽 "+lineW,"间宽 "+gapW);139             wxpO = new wxp(caH,caW,buttonH,gyj,dyj,gy,dy,doo,allLine,allGap,lineW,gapW,mode,picsLst);140             wxpO.draw(caCt);141             //gen("circleDo");142 143             /*生成间线对象列表*/144             if(debug)console.log("线间对象列表---Start");145             var nowTop = 0;146             var high = 0;147             // 高音谱上加148             var base = gy.x + gy.j;149             for(i=gyj.x+gyj.j;i>=1;i--){150                 if(i%2==0){151                     high = lineW;152                 }else{153                     high = gapW;154                 }155                 jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});156                 if(debug)console.log("gyj: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));157                 nowTop += high;158             }159             // 高音谱160             base = 0;161             for(i=gy.x+gy.j;i>=1;i--){162                 if(i%2==0){163                     high = lineW;164                 }else{165                     high = gapW;166                 }167                 jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});168                 if(debug)console.log("gy: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));169                 nowTop += high;170             }171             // doo172             jxObjLst.push({"v":0,"top":nowTop,"high":lineW,"type":"Line"});173             if(debug)console.log("doo: v "+0,"top "+nowTop,"high "+lineW,"type "+"Line");174             nowTop += lineW;175             // 低音谱176             base = 0;177             for(i=1;i<=dy.x+dy.j;i++){178                 if(i%2==0){179                     high = lineW;180                 }else{181                     high = gapW;182                 }183                 jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});184                 if(debug)console.log("dy: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));185                 nowTop += high;186             }187             // 低音谱下加188             base = -dy.x-dy.j;189             for(i=1;i<=dyj.x+dyj.j;i++){190                 if(i%2==0){191                     high = lineW;192                 }else{193                     high = gapW;194                 }195                 jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});196                 if(debug)console.log("dyj: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));197                 nowTop += high;198             }199             if(debug)console.log("线间对象列表---End");200             /*唱名按钮*/201             var rw = Math.floor(caW / 8);202             var rh = Math.floor((caH - Math.ceil(buttonH)) / 4);203             var r = rw<rh?rw:rh;204             if(debug)console.log("唱名打击按钮半径: ",rw,rh,r);205             for(var i=0;i<7;i++){206                 var name = ((i==0)?"do":(i==1)?"re":(i==2)?"mi":(i==3)?"fa":(i==4)?"so":(i==5)?"la":(i==6)?"si":"do");207                 var diff =  Math.floor(caH - Math.ceil(buttonH));208                 var top = 0;209                 var left = 0;210                 if(i<3){211                     top = Math.ceil(buttonH) + Math.floor(diff / 4);212                     left = (caW / 3) * (0.5 + i%3);213                 }else{214                     top = Math.ceil(buttonH) + Math.floor(diff / 4 * 3);215                     left = (caW / 4) * (0.5 + (i-3)%4);216                 }217                 djBtnLst.push(new djBtn(bgCLst[i],fontCLst[i],name,name,top,r,left));218                 djBtnLst[i].draw(caCt);219             }220         }221 222     }223     function gen(name) {224         /*product object*/225         switch(name){226             case "circleDo":227                 //音值228                 var v = parseInt(229                 Math.random()>0.34230                 ?Math.random()*(highest)231                 :-1*low+Math.random()*(low)232                 );233                 //唱名234                 var vT = Math.abs(v % 7);235                 vT = v<0?7-vT:vT;236                 //音阶237                 var yj = (v / 7)>0?Math.floor(v / 7):Math.ceil(v / 7);238                 var name2 = 239                 v<0?((yj-1)+‘‘).replace(‘-‘,‘↓‘):((yj>=1&&v!=6)?"↑":‘‘)240                 +((yj-((v+7)%7==0?1:0))+‘‘).replace("0",‘‘).replace("-1",‘‘);241                 var name = ((vT==0)?"do":(vT==1)?"re":(vT==2)?"mi":(vT==3)?"fa":(vT==4)?"so":(vT==5)?"la":(vT==6)?"si":"do") + name2;242                 r = Math.floor((caH - buttonH)/4);243                 cy = Math.floor(r + Math.random()*(caH - buttonH - 2*r));244                 if(debug)console.log("音值 "+v,"唱名 "+name,"音阶 "+yj,"唱名值 "+vT);245                 var cDo =new circleDo(bgCLst[vT],fontCLst[vT],v,name,cy,r,circleDoLst.length>0?circleDoLst[circleDoLst.length-1].left+2.5*circleDoLst[circleDoLst.length-1].r:caW-r);246                 circleDoLst.push(cDo);247                 //cDo.draw(caCt);248                 break;249             case "wxpDo":250                 //音值251                 var v = parseInt(252                 Math.random()>0.34253                 ?Math.random()*(highest)254                 :-1*low+Math.random()*(low)255                 );256                 //唱名257                 var vT = Math.abs(v % 7);258                 vT = v<0?7-vT:vT;259                 //音阶260                 var yj = (v / 7)>0?Math.floor(v / 7):Math.ceil(v / 7);261                 var name2 = 262                 v<0?((yj-1)+‘‘).replace(‘-‘,‘↓‘):((yj>=1&&v!=6)?"↑":‘‘)263                 +((yj-((v+7)%7==0?1:0))+‘‘).replace("0",‘‘).replace("-1",‘‘);264                 var name = ((vT==0)?"do":(vT==1)?"re":(vT==2)?"mi":(vT==3)?"fa":(vT==4)?"so":(vT==5)?"la":(vT==6)?"si":"do") + name2;265                 r = Math.floor(gapW*1);266                 var cy = 0;267                 for(var j=0;j<jxObjLst.length;j++){268                     if(jxObjLst[j].v==v){269                         cy = jxObjLst[j].top+jxObjLst[j].high*0.5;270                         break;271                     }272                 }273                 if(debug)console.log("音值 "+v,"唱名 "+name,"音阶 "+yj,"唱名值 "+vT);274                 var cDo =new wxpDo(‘blue‘,‘white‘,v,name,cy,r,wxpDoLst.length>0?wxpDoLst[wxpDoLst.length-1].left+gapW*4:caW-gapW*2);275                 wxpDoLst.push(cDo);276                 cDo.draw(caCt);277                 //cDo.draw(caCt);278                 break;279             default:280         }281     }282     function picIsLoaded() {283         return toLoadPicCount <= loadPicCount ? true : false;284     }285     function loadPics() {286         /*load pic to objectList*/287         for (var i = 0; i < pics.length; i++) {288             var imgTmp = new Image();289             imgTmp.src =http://www.mamicode.com/ pics[i];290             imgTmp.onload = loadedImg;291             picsLst.push(imgTmp);292         }293     }294     function loadedImg() {295         //console.log(loadPicCount, toLoadPicCount);296         return ++loadPicCount;297     }298     function animate(time) {299         if (picIsLoaded()) {300             if(!goOn && (wrong>=maxWrong || score<=-100 || score>15000)){301                 var s = Math.floor(score);302                 var name="";303                 if(s<=-50){304                     name=‘音盲‘;305                 }else if(s<500){306                     name=‘普通人‘307                 }else if(s<5000){308                     name=‘识音达人‘309                 }else if(s<10000){310                     name=‘识音天才‘311                 }else{312                     name=‘绝对音感?‘313                 }314                 document.getElementById("scoreC").innerHTML = "称号: "+name +",得分: "+s+" 【游戏结束】";315                 316                 document.getElementsByTagName(‘title‘)[0].innerHTML = name+",得分【"+Math.floor(score)+"】";317                 document.getElementById("btn_start").style.display="block";318                 document.getElementById("gameWorldTouch").style.display="none";319                 return;320             }321             var now = (+new Date);322             if (mode == 0 && now - lastFpsUpdateTimeBDJ > bdjTime) {323                 bdjLeft = circleDoLst.length>0?circleDoLst[0].left:r*2;324                 if(bdjLeft>=r){325                     lastFpsUpdateTimeBDJ = now;326                     wxpO.clearCircleDo(caCt);327                     for(var i=0;i<circleDoLst.length;i++){328                         circleDoLst[i].left -= bdjPX;329                         circleDoLst[i].draw(caCt);330                     }331                     bdjLeft = circleDoLst.length>0?circleDoLst[0].left:r*2;332                     if(circleDoLst.length>0 && (circleDoLst[circleDoLst.length-1].left+r)<= caW){333                         gen("circleDo");334                     }335                     /*draw canvas*/336                     //caCt.save();337                     //caCt.beginPath();338                     //caCt.restore();339                 }else{340                     if(!goOn)score-=scoreFu;341                 }342             }343             if (mode == 1 && now - lastFpsUpdateTimeBDJ > bdjTime) {344                 bdjLeft = wxpDoLst.length>0?wxpDoLst[0].left:wxpDoLeft;345                 if(bdjLeft>=wxpDoLeft){346                     lastFpsUpdateTimeBDJ = now;347                     wxpO.clearWXPDo(caCt);348                     for(var i=0;i<wxpDoLst.length;i++){349                         wxpDoLst[i].left -= bdjPX;350                         wxpDoLst[i].draw(caCt);351                     }352                     bdjLeft = wxpDoLst.length>0?wxpDoLst[0].left:wxpDoLeft;353                     if(wxpDoLst.length>0 && wxpDoLst[wxpDoLst.length-1].left<= caW){354                         gen("wxpDo");355 if(debug){console.log(‘a‘);}356                     }357                     /*draw canvas*/358                     //caCt.save();359                     //caCt.beginPath();360                     //caCt.restore();361                 }else{362                     if(!goOn)score-=scoreFu;363                 }364             }365             366             /*score*/367             if(!goOn){368                 document.getElementById("scoreC").innerHTML = "得分: "+Math.floor(score)+" 错误: "+wrong+" / "+maxWrong;369             }else{370                 document.getElementById("lx").innerHTML = "无限练习模式,点击此处返回菜单";371                 document.getElementById("lx").addEventListener("click", backMenu, false);372                 document.getElementById("lx").addEventListener("touchstart", backMenu, false);373             }374         }375         window.requestNextAnimationFrame(animate);376         /*if (isStop) {377             isStart = false;378             btn_start.innerHTML += "<br />游戏结束,马上重新开始";379             reStart();380             return;381         }382         if (isStart) {383             //var pastTime = Math.round(((new Date).getTime() - startTime) / 1E3 * 100) / 100;384             btn_start.innerHTML = pastTime;385             btn_start.innerHTML = "分数: " + goodPass + " <br />用时: " + pastTime + " 秒";386             var now = (+new Date);387             if (now - lastFpsUpdateTime > 100) {388                 lastFpsUpdateTime = now;389                 goOn();390                 caCt.fillStyle = "#fff";391                 caCt.fillRect(0, 0, caObj.width, caObj.height);392                 caCt.fillStyle = "#000";393                 //caCt.clearRect(0, 0, caObj.width, caObj.height);394                 drawBird();395                 drawZALst();396                 doJudge();397             }398         } else {399             caCt.clearRect(0, 0, caObj.width, caObj.height);400             drawBird();401             drawZALst();402         }*/403     }404     function backMenu(){405         document.getElementById("btn_start").style.display= "block";406         document.getElementById("gameWorldTouch").style.display="none";407         return;408     }409     function eventBund(){410         if(!v){411             //caTObj.addEventListener("mousemove", onm ouseMove, false);412             caTObj.addEventListener("click", onm ouseClick, false);413         }else{414             caTObj.addEventListener("touchstart", onTouchStart, false);415             caTObj.addEventListener("touchmove", onTouchMove, false);416             caTObj.addEventListener("touchend", stopEvent, false);417             caTObj.addEventListener("touchcancel", stopEvent, false);418             caTObj.addEventListener("gesturestart", stopEvent, false);419             caTObj.addEventListener("gesturechange", stopEvent, false);420             caTObj.addEventListener("gestureend", stopEvent, false);421         }422         //document.getElementById("s1").addEventListener("click", onStart, false);423         //document.getElementById("s2").addEventListener("click", onStart, false);424     }425     function onStart(e){426         document.getElementById("btn_start").style.display="none";427         if(!goOn){428             document.getElementById("scoreC").style.display="block";429         }else{430             document.getElementById("lx").style.display="block";431         }432     }433     function onm ouseMove(e){434         //mouseTObj.x = e.pageX;435         //mouseTObj.y = e.pageY;436     }437     function onTouchMove(e){438         e.preventDefault();439         var touch = e.touches[0];440         //mouseTObj.x = touch.pageX;441         //mouseTObj.y = touch.pageY;442         return false;443     }444     function onTouchStart(e){445         e.preventDefault();446         var touch = e.touches[0];447         touched({"x":touch.pageX,"y":touch.pageY});448         //mouseTObj.x = touch.pageX;449         //mouseTObj.y = touch.pageY;450         return false;451     }452     function onm ouseClick(e){453         touched({"x":e.pageX,"y":e.pageY});454     }455     function touched(pos){456         if(mode==0){457             // 五线谱458             if(debug){console.log("click: ",pos);}459             /*判断哪个线间被点中*/460             //jxObjLst item: {"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"}461             var value = http://www.mamicode.com/null;462             for(i=0;i<jxObjLst.length;i++){463                 //if(debug){console.log("loop: ",jxObjLst[i].top,jxObjLst[i].high);}464                 if(pos.y>jxObjLst[i].top){465                     if(pos.y<=jxObjLst[i].top + jxObjLst[i].high){466                         value =http://www.mamicode.com/ jxObjLst[i];467                         break;468                     }469                 }470             }471             if(value=http://www.mamicode.com/=null)return;472             if(debug){console.log("poisiton,value",pos,value);}473             /*判断正确与否,并消除被打击对象*/474             if(debug)console.log(‘被打击对象列表: ‘,circleDoLst);475             /*高亮提示当前所点线间*/476             if(value!=null){477                 //唱名478                 var vT = Math.abs(value.v % 7);479                 vT = value.v<0?7-vT:vT;480                 var name = ((vT==0)?"do":(vT==1)?"re":(vT==2)?"mi":(vT==3)?"fa":(vT==4)?"so":(vT==5)?"la":(vT==6)?"si":"do");481                 // 画图482                 caTCt.clearRect(0,0,caW,caH);483                 wxpO.drawOne(caTCt,value.top,value.high,alertColor);484                 wxpO.drawText(caTCt,caW/2,caH/2,caW/5,name,alertColor);485                 setTimeout(clearTouchCanvas,alertTime);486             }487             if(circleDoLst.length>0 && value!=null && circleDoLst[0].value =http://www.mamicode.com/= value.v){488                 if(debug)console.log("%cclick right!!!","color:green");489                 if(debug)console.log(‘被打击对象列表: ‘,circleDoLst);490                 circleDoLst.splice(0,1);491                 gen("circleDo");492                 bdjLeft = circleDoLst.length>0?circleDoLst[0].left:2*r;493                 if(!goOn)score+=scoreOne;494                 //wxpO.clearCircleDo(caCt);495                 //gen("circleDo"); // temp496             }else{497                 if(debug)console.log("%cclick wrong!!!","color:red");498                 if(!goOn)wrong++;499                 if(debug)console.log("error",wrong);500             }501         }else if(mode==1){502             // 五线谱503             if(debug){console.log("click: ",pos);}504             /*判断哪个按钮点中*/505             //djBtnLst item: (bgC,fontC,value,name,top,r,left)506             var value = http://www.mamicode.com/null;507             for(i=0;i<djBtnLst.length;i++){508                 //if(debug){console.log("loop: ",jxObjLst[i].top,jxObjLst[i].high);}509                 //var distance = Math.abs(((pos.x-djBtnLst[i].left)^2 + (pos.y-djBtnLst[i].top)^2)^0.5);510                 var calX = pos.x - djBtnLst[i].left;        511                 var calY = pos.y - djBtnLst[i].top;512                 var distance = Math.pow((calX *calX + calY * calY), 0.5);513                 514                 console.log(distance,djBtnLst[i].r);515                 if(distance<=djBtnLst[i].r){516                     value =http://www.mamicode.com/ djBtnLst[i];517                     break;518                 }519             }520             if(value=http://www.mamicode.com/=null)return;521             if(debug){console.log("poisiton,value",pos,value);}522             /*判断正确与否,并消除被打击对象*/523             if(debug)console.log(‘被打击对象列表: ‘,wxpDoLst);524             /*高亮提示当前点击的所有线间*/525             caTCt.clearRect(0,0,caW,caH);526             if(value!=null){527                 //线间list528                 //var indexLst = [];529                 for(var i = 0;i<jxObjLst.length;i++){530                     var vT = Math.abs(jxObjLst[i].v % 7);531                     vT = jxObjLst[i].v<0?7-vT:vT;532                     var name = ((vT==0)?"do":(vT==1)?"re":(vT==2)?"mi":(vT==3)?"fa":(vT==4)?"so":(vT==5)?"la":(vT==6)?"si":"do");533                     if(name==value.name){ 534                         wxpO.drawOne(caTCt,jxObjLst[i].top,jxObjLst[i].high,alertColor);535                     }536                     //if(name==value.name){indexLst.push(i);}537                 }538                 // 清空画图539                 setTimeout(clearTouchCanvas,alertTime);540             }541             if(wxpDoLst.length>0 && value!=null && wxpDoLst[0].name.indexOf(value.name)!=-1){542                 if(debug)console.log("%cclick right!!!","color:green");543                 if(debug)console.log(‘被打击对象列表: ‘,circleDoLst);544                 wxpDoLst.splice(0,1);545                 gen("wxpDo");546                 bdjLeft = wxpDoLst.length>0?wxpDoLst[0].left:wxpDoLeft;547                 if(!goOn)score+=scoreOne;548                 //wxpO.clearCircleDo(caCt);549                 //gen("circleDo"); // temp550             }else{551                 if(debug)console.log("%cclick wrong!!!","color:red");552                 if(!goOn)wrong++;553                 if(debug)console.log("error",wrong);554             }555         }556     }557     function clearTouchCanvas(){558         caTCt.clearRect(0,0,caW,caH);559         if(debug)console.log(‘clear‘);560     }561     function stopEvent(e) { e.preventDefault(); e.stopPropagation(); }562     var v = navigator.userAgent.toLowerCase().indexOf("android") != -1 || navigator.userAgent.toLowerCase().indexOf("iphone") != -1 || navigator.userAgent.toLowerCase().indexOf("ipad") != -1,563     caW = window.innerWidth,564     caH = window.innerHeight,565     caObj = document.getElementById("gameWorld"),566     caCt = caObj.getContext("2d"),567     caTObj = document.getElementById("gameWorldTouch"),568     caTCt = caTObj.getContext("2d"),569     //rabitPicLst = ["img/rabit_left_stop.png", "img/rabit_on_ground_left_jump0.png", "img/rabit_on_ground_left_jump1.png", "img/rabit_right_stop.png", "img/rabit_on_ground_right_jump0.png", "img/rabit_on_ground_right_jump1.png", "img/rabit_on_air_left_stop.png", "img/rabit_on_air_left_down.png", "img/rabit_on_air_right_stop.png", "img/rabit_on_air_right_down.png"],570     //rabitPicOLst = [],571     pics = [‘img/gyph.png‘,‘img/dyph.png‘],572     loadPicCount = 0,573     toLoadPicCount = 2,574     /*线与间*/575     //高音普上加线,3线,2间,上下无间576     gyj = {x:2,j:2,up:0,down:0},577     //低音普上加线,2线,1间,上下无间578     dyj = {x:0,j:0,up:0,down:0},579     //高音普线,5线,6间,上下有间580     gy = {x:5,j:5,up:1,down:1},581     //低音普线,5线,6间,上下有间582     dy = {x:5,j:5,up:1,down:1},583     //高音低音间do584     doo = {x:1,j:1,up:0,down:0},585     //最高音 五线谱用586     highest = 0,587     //最低音 五线谱用588     low = 0,589     //被打击对象列表 五线谱用590     circleDoLst = [],591     //被打击对象列表 唱名用592     wxpDoLst = [],593     //总线数594     allLine = 0,595     //总间数596     allGap = 0,597     //线宽598     lineW = 0,599     //间宽600     gapW = 0,601     //打击区总高度602     buttonH = 0,603     //五线谱object604     wxpO = null,605     //唱名object606     cmO = null,607     //模式 0:五线谱打,1:唱名打608     mode = mode,609     //间线对象列表610     jxObjLst = [],611     //颜色 五线谱用612     bgCLst = ["green","red","blue","green","pink","orange","yellow","gray"],613     fontCLst = ["yellow","yellow","white","white","blue","white","black","yellow"],614     // 被打击对象平移更新时间615     bdjTime = 100,616     // 被打击对象平移速度617     bdjPX = 5,618     // 被打击对象最左端619     bdjLeft = 0,620     // 被打击对象半径621     r = 0,622     // 唱名打击用623     // 唱名button列表624     djBtnLst = [],625     // 被打击对象初期数626     bdjInitCount = 5,627     // 提示颜色628     alertColor = "rgba(102,0,255,0.5)",629     // 提示时间630     alertTime = 500,631     // 五线谱音符最左边632     wxpDoLeft = 0,633     scoreOne=50,634     scoreFu = 0.1;635     score=0,636     wrong=0,637     maxWrong = 10,638     picsLst=[],639     goOn = goOn640     ;641 642     this.init = function () {643     mode = this.mode;644     goOn = this.goOn;645         //*********load images*********646         loadPics();647         //*********init params*******648         doVarInit();649         //*********init size and vars*******650         doSize();651         //*********product bell and rabit*******652         for(var i = 0;i<bdjInitCount;i++)653             if(mode==0){654                 gen("circleDo");655             }else{656                 gen("wxpDo");657             }658         //*********Event***********659         eventBund();660         //*********Gen***********661         //*********animate***********662         animate();663     }664 }665 666 /*667 * 五线谱 object668 */669 function wxp(caH,caW,buttonH,gyj,dyj,gy,dy,doo,allLine,allGap,lineW,gapW,mode,picLst) {670     this.mode = mode; //0: 打谱,1: 打唱名671     this.caH = caH; // 画面高度672     this.caW = caW; // 画面宽度673     this.buttonH=buttonH; // 打击区高度674     this.gyj=gyj; // 高音上675     this.dyj=dyj; // 低音下676     this.gy=gy; // 高音677     this.dy=dy; // 低音678     this.doo=doo; // 中间do679     this.allLine=allLine; // 总线680     this.allGap=allGap; // 总间681     this.lineW=lineW; // 线高682     this.gapW=gapW; // 间高683     this.picLst = picLst;684 }685 wxp.prototype.clearCircleDo = function (context) {686     // 打谱用687     var circleDoH = this.caH - (this.lineW * this.allLine + this.gapW * this.allGap) + 0.5;688     context.clearRect(0,0,this.caW,circleDoH);689     /*context.save();690     context.fillStyle = ‘white‘;691     context.fillRect(0,0,this.caW,circleDoH);692     context.restore();*/693 }694 wxp.prototype.clearWXPDo = function (context) {695     // 打唱名用696     context.clearRect(0,0,this.caW,this.buttonH);697     this.draw(context);698     /*context.save();699     context.fillStyle = ‘white‘;700     context.fillRect(0,0,this.caW,circleDoH);701     context.restore();*/702 }703 wxp.prototype.drawOne = function (context,top,high,color) {704     context.save();705     context.beginPath();706     context.fillStyle = color;707     context.fillRect(0,top,this.caW,high);708     context.closePath();709     context.restore();710 }711 wxp.prototype.drawText = function (context,x,y,size,text,color) {712     context.save();713     context.beginPath();714     context.fillStyle = color;715     context.font = parseInt(size)+"pt Calibri";716     context.textBaseline = ‘middle‘;717     context.textAlign=‘center‘;718     context.fillText(text,x,y);719     context.closePath();720     context.restore();721 }722 wxp.prototype.draw = function (context) {723     var gyphT = 0,gyphH = (this.gapW+this.lineW) * 6,gyphW = this.gapW * 3;724     var dyphT = 0,dyphH = (this.gapW+this.lineW) * 3,dyphW = this.gapW * 3;725     /*画线*/726     var nowTop = 0;727     if(this.mode==0){728         nowTop = this.caH - (this.lineW * this.allLine + this.gapW * this.allGap) + 0.5;729     }730     context.save();731     for(var i=1;i<=this.gyj.x;i++){732         context.beginPath();733         context.lineWidth = this.lineW/2;734         context.fillStyle = "gray";735         context.strokeStyle = "gray";736         context.moveTo(0,nowTop+this.lineW/2);737         context.lineTo(this.caW,nowTop+this.lineW/2);738         context.stroke();739         context.fill();740         nowTop += this.lineW + this.gapW;741     }742     for(var i=1;i<=this.gy.x;i++){743         if(i==1)gyphT = nowTop - this.gapW * 2; 744         context.beginPath();745         context.lineWidth = this.lineW/2;746         context.fillStyle = "black";747         context.strokeStyle = "black";748         context.moveTo(0,nowTop+this.lineW/2);749         context.lineTo(this.caW,nowTop+this.lineW/2);750         context.stroke();751         context.fill();752         nowTop += this.lineW + this.gapW;753     }754     for(var i=1;i<=this.doo.x;i++){755         context.beginPath();756         context.lineWidth = this.lineW/2;757         context.fillStyle = "red";758         context.strokeStyle = "red";759         context.moveTo(0,nowTop+this.lineW/2);760         context.lineTo(this.caW,nowTop+this.lineW/2);761         context.stroke();762         context.fill();763         nowTop += this.lineW + this.gapW;764     }765     for(var i=1;i<=this.dy.x;i++){766         if(i==1)dyphT = nowTop + this.gapW * 0;767         context.beginPath();768         context.lineWidth = this.lineW/2;769         context.fillStyle = "black";770         context.strokeStyle = "black";771         context.moveTo(0,nowTop+this.lineW/2);772         context.lineTo(this.caW,nowTop+this.lineW/2);773         context.stroke();774         context.fill();775         nowTop += this.lineW + this.gapW;776     }777     for(var i=1;i<=this.dyj.x;i++){778         context.beginPath();779         context.lineWidth = this.lineW/2;780         context.fillStyle = "gray";781         context.strokeStyle = "gray";782         context.moveTo(0,nowTop+this.lineW/2);783         context.lineTo(this.caW,nowTop+this.lineW/2);784         context.stroke();785         context.fill();786         nowTop += this.lineW + this.gapW;787     }788     context.closePath();789     context.restore();790     /*画谱号*/791     /*var gImg = new Image();792     var dImg = new Image();793     gImg.src = http://www.mamicode.com/‘img/gyph.png‘;>794     dImg.src = http://www.mamicode.com/‘img/dyph.png‘;>795     gImg.onload = function(){context.drawImage(gImg,10,gyphT,gyphW,gyphH);}796     dImg.onload = function(){context.drawImage(dImg,10,dyphT,dyphW,dyphH);}*/797     798     context.drawImage(this.picLst[0],10,gyphT,gyphW,gyphH);799     context.drawImage(this.picLst[1],10,dyphT,dyphW,dyphH);800 }801 802 /*803 * 五线谱用 被打击对象 object804 */805 function circleDo(bgC,fontC,value,name,top,r,left) {806     this.bgC = bgC; // 背景颜色807     this.fontC = fontC; // 字体颜色808     this.value=http://www.mamicode.com/value; // 音值809     this.name=name; // 显示文字810     this.left=left; // r,left811     this.top=top; // top812     this.r=r; // 半径813 }814 circleDo.prototype.draw = function (context) {815     context.save();816     context.fillStyle = this.bgC;817     context.beginPath();818     context.arc(this.left/* + 75*/,this.top/* +75*/,this.r,0,2*Math.PI);819     context.closePath();820     context.fill();821     822     context.fillStyle = this.fontC;823     context.font = parseInt(this.r/2)+"pt Calibri";824     context.textBaseline = ‘middle‘;825     context.textAlign=‘center‘;826     context.fillText(this.name, this.left/* + 75*/,this.top/* +75*/);827     context.restore();828 }829 830 /*831 * 唱名用 唱名button object832 */833 function djBtn(bgC,fontC,value,name,top,r,left) {834     this.bgC = bgC; // 背景颜色835     this.fontC = fontC; // 字体颜色836     this.value=http://www.mamicode.com/value; // 音值837     this.name=name; // 显示文字838     this.left=left; // r,left839     this.top=top; // top840     this.r=r; // 半径841 }842 djBtn.prototype.draw = function (context) {843     context.save();844     context.fillStyle = this.bgC;845     context.beginPath();846     context.arc(this.left/* + 75*/,this.top/* +75*/,this.r,0,2*Math.PI);847     context.closePath();848     context.fill();849     850     context.fillStyle = this.fontC;851     context.font = parseInt(this.r/2)+"pt Calibri";852     context.textBaseline = ‘middle‘;853     context.textAlign=‘center‘;854     context.fillText(this.name, this.left/* + 75*/,this.top/* +75*/);855     context.restore();856 }857 /*858 * 唱名用 被打击对象 object859 */860 function wxpDo(bgC,fontC,value,name,top,r,left) {861     this.bgC = bgC; // 背景颜色862     this.fontC = fontC; // 字体颜色863     this.value=http://www.mamicode.com/value; // 音值864     this.name=name; // 显示文字865     this.left=left; // left866     this.top=top; // top867     this.r=r; // 半径868 }869 wxpDo.prototype.draw = function (context) {870     context.save();871     context.strokeStyle = this.bgC;872     context.lineWidth = this.r*0.5;873     this.ParamEllipse(context,this.left,this.top,this.r*1.5,this.r);874     875     var lineLeft1 = 0;876     var lineTop1 = 0;877     var lineLeft2 = 0;878     var lineTop2 = 0;879     if(this.value>=6){880         //第三线以上,下尾巴881         lineLeft1=lineLeft2=-1*this.r*1.4;882         lineTop1=0;883         lineTop2=this.r*5;884     }else{885         lineLeft1=lineLeft2=this.r*1.4;886         lineTop1=0;887         lineTop2=-1*this.r*5;888     }889     context.beginPath();890     context.moveTo(lineLeft1,lineTop1);891     context.lineTo(lineLeft2,lineTop2);892     context.stroke();893     context.closePath();894 895     context.restore();896 }897 //---------使用三次贝塞尔曲线模拟椭圆1---------------------898 //此方法也会产生当lineWidth较宽,椭圆较扁时,899 //长轴端较尖锐,不平滑的现象900 wxpDo.prototype.ParamEllipse = function(context, x, y, a, b){901   //关键是bezierCurveTo中两个控制点的设置902    //0.5和0.6是两个关键系数(在本函数中为试验而得)903    var ox = 0.5 * a,904        oy = 0.6 * b;905    //context.save();906    context.translate(x, y);907    context.beginPath();908    //从椭圆纵轴下端开始逆时针方向绘制909    context.moveTo(0, b); 910    context.bezierCurveTo(ox, b, a, oy, a, 0);911    context.bezierCurveTo(a, -oy, ox, -b, 0, -b);912    context.bezierCurveTo(-ox, -b, -a, -oy, -a, 0);913    context.bezierCurveTo(-a, oy, -ox, b, 0, b);914    context.closePath();915    context.stroke();916    //context.restore();917 };918 /*example of object*/919 /*920 * bell object921 */922 /*function bell(top, left, width, height, si, maxSI) {923     this.t = top; // 高度924 }925 bell.prototype.disappear = function (speed) {926     this.a -= speed;927     return this.a <= 0 ? true : false;928 }*/929 930 /*example of extends*/931 /*932 * bird object933 */934 /*function bird(top, left, width, height, si, maxSI, direction) {935     this.t = top; // 高度936 }937 bird.prototype = new bell;938 */939 940 var gameWorldObj = null;941 onl oad = function () {942     document.getElementsByTagName(‘title‘)[0].innerHTML = "[WXS]五线谱游戏";943     /*gameWorldObj = new gameWorld(0);944     gameWorldObj.init();*/945 }946 function staffGameGo(mode,goOn){947     if(gameWorldObj == null)948         gameWorldObj = new gameWorld(mode,goOn);949     gameWorldObj.goOn = goOn;950     gameWorldObj.mode = mode;951     gameWorldObj.init();    952     document.getElementById("btn_start").style.display="none";953     if(!goOn){954         document.getElementById("scoreC").style.display="block";955         document.getElementById("lx").style.display="none";}956     else{957         document.getElementById("lx").style.display="block";958         document.getElementById("scoreC").style.display="none";959     }960 }

---

CSDN下载:

http://download.csdn.net/detail/wangxsh42/8391847

[原创]html5游戏_五线谱打音符