html5游戏_五线谱打音符

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

1.[用五线谱打唱名]

2.[用唱名五线谱]

3.[无限练习模式]

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

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

效果图:

html5游戏_五线谱打音符

html5游戏_五线谱打音符

html5游戏_五线谱打音符

---

在线地址:

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 />[email protected]</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

你可能感兴趣的:(html5)