zoukankan      html  css  js  c++  java
  • [原创]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;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.5
    124             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             // doo
    172             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.34
    230                 ?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.34
    253                 ?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 = 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", onMouseMove, false);
    412             caTObj.addEventListener("click", onMouseClick, 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 onMouseMove(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 onMouseClick(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 = 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 = jxObjLst[i];
    467                         break;
    468                     }
    469                 }
    470             }
    471             if(value==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 == 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"); // temp
    496             }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 = 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 = djBtnLst[i];
    517                     break;
    518                 }
    519             }
    520             if(value==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                 //线间list
    528                 //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"); // temp
    550             }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     //高音低音间do
    584     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     //五线谱object
    604     wxpO = null,
    605     //唱名object
    606     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 = goOn
    640     ;
    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 * 五线谱 object
    668 */
    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; // 中间do
    679     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 = 'img/gyph.png';
    794     dImg.src = '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 * 五线谱用 被打击对象 object
    804 */
    805 function circleDo(bgC,fontC,value,name,top,r,left) {
    806     this.bgC = bgC; // 背景颜色
    807     this.fontC = fontC; // 字体颜色
    808     this.value=value; // 音值
    809     this.name=name; // 显示文字
    810     this.left=left; // r,left
    811     this.top=top; // top
    812     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 object
    832 */
    833 function djBtn(bgC,fontC,value,name,top,r,left) {
    834     this.bgC = bgC; // 背景颜色
    835     this.fontC = fontC; // 字体颜色
    836     this.value=value; // 音值
    837     this.name=name; // 显示文字
    838     this.left=left; // r,left
    839     this.top=top; // top
    840     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 * 唱名用 被打击对象 object
    859 */
    860 function wxpDo(bgC,fontC,value,name,top,r,left) {
    861     this.bgC = bgC; // 背景颜色
    862     this.fontC = fontC; // 字体颜色
    863     this.value=value; // 音值
    864     this.name=name; // 显示文字
    865     this.left=left; // left
    866     this.top=top; // top
    867     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 object
    921 */
    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 object
    933 */
    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 onload = 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

  • 相关阅读:
    如何说明白代码评审
    面试感悟----一名3年工作经验的程序员应该具备的技能(转载自@五月的仓颉)
    根据ip地址从第三方接口获取详细的地理位置
    linux安装telnet遇到的问题
    redis脑图
    数据库相关面试题
    logback系列一:名词解释
    java并发编程系列一、多线程
    logback系列二:logback在项目中的应用
    rocketmq特性(features)
  • 原文地址:https://www.cnblogs.com/wangxinsheng/p/4261432.html
Copyright © 2011-2022 走看看