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

1.[用五线谱打唱名]

2.[用唱名打五线谱]

3.[无限练习模式]

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

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

效果图:

---

在线地址:

http://wangxinsheng.herokuapp.com/staffgame

---

代码:

index.html

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="html5 staff game">
<meta name="keywords" content="staff,html5,canvas,web,game">
<meta name="author" content="WangXinsheng">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport" id="viewport" content="width = device-width, initial-scale = 1, minimum-scale = 1, maximum-scale = 1, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta equiv="Expires" content="0">
<meta http-equiv="content-script-type" content="text/javascript">
<link type="image/x-icon" rel="shortcut icon" href="img/staffFavicon.ico" />
<title>CopyRight&copy;WangXinsheng</title>
<script src="requestNextAnimationFrame.js"></script>
<style type="text/css">
html {color:#000;background:#fff;margin:0px;}
body {-webkit-user-select:none;margin:0px;}
#gameWorld{cursor:pointer;}
#btn_start{color:red;font-size:40px;font-weight:bold;z-index:999;background:#fff;text-align:center;overflow:hidden;}
#btn_start p {vertical-align:middle;cursor:pointer;background:yellow;margin:20px 0px;}
#scoreC,#lx{width:100%;color:red;font-size:20px;font-weight:bold;z-index:999;display:none;cursor:pointer;}
#btn_start #copy {font-size:15px;vertical-align:middle;cursor:pointer;background:white;color:blue;}
</style>
</head>
<body>
<section>
<div style='position:absolute;left:0px;top:0px;width:100%;height:100%' id='btn_start'>
<p id='s1' onclick='javascript:staffGameGo(0,false);'>五线谱打唱名</p>
<p id='s2' onclick='javascript:staffGameGo(1,false);'>唱名打五线谱</p>
<p id='s3' onclick='javascript:staffGameGo(0,true);'>无限练习<br />五线谱打唱名</p>
<p id='s4' onclick='javascript:staffGameGo(1,true);'>无限练习<br />唱名打五线谱</p>
<p id='copy'>powered by 王欣盛<br />2015/01/22+1+1<br />wangxsh42@126.com</p>
</div>
<div style='position:absolute;left:0px;top:0px;' id='scoreC'>
</div>
<div style='position:absolute;left:0px;top:0px;' id='lx'>
</div>
<canvas id="gameWorld" style="position: absolute; left: 0px; top: 0px;">
<p>You need a modern browser to view this.</p>
</canvas>
<canvas id="gameWorldTouch" style="position: absolute; left: 0px; top: 0px;display:none;">
</canvas>
</section>
</body>
<script src="staffGame.js"></script>
</html>

staffGame.js

 ;
var debug = true;
var gameWorld = function (mode,goOn) {
//this.mode = mode;
/*function init params*/
function doVarInit() {
//总线数
allLine = gyj.x + dyj.x + gy.x + dy.x + doo.x;
//总间数
allGap = gyj.j + dyj.j + gy.j + dy.j + doo.j;
if(debug)
console.log("总线数 "+allLine,"总间数 "+allGap);
jxObjLst=[];
djBtnLst=[];
circleDoLst=[];
wxpDoLst=[];
}
/*function on resize the window*/
function doSize() {
if(!picIsLoaded()){setTimeout(doSize,200);}
document.getElementById("gameWorldTouch").style.display="block";
caW = window.innerWidth;
caH = window.innerHeight;
caObj.width = caW;
caObj.height = caH;
caObj.style.width = caW + "px";
caObj.style.height = caH + "px";
caTObj.width = caW;
caTObj.height = caH;
caTObj.style.width = caW + "px";
caTObj.style.height = caH + "px";
bdjPX =Math.floor( caW / 80);
lastFpsUpdateTime = new Date;
lastFpsUpdateTimeBDJ = new Date;
score = 0;
wrong = 0;
/*线宽,间宽计算*/
//1/3为五线谱,或按钮
buttonH = parseInt(caH / 3);
if(mode==0){
//五线谱 高度
buttonH = parseInt(caH / 3 * 2);
//线宽为间宽的0.5
lineW = parseInt(buttonH / (allGap*2+allLine));
//间宽
gapW = lineW * 2;
/*线等高于间 补丁,线太细就太难点中了*/
lineW = parseInt(buttonH / (allGap+allLine));
gapW = lineW;
//最高音
highest = gyj.x + gyj.j + gy.x + gy.j;
//最低音
low = dyj.x + dyj.j + dy.x + dy.j; if(debug)
console.log("线宽 "+lineW,"间宽 "+gapW);
wxpO = new wxp(caH,caW,buttonH,gyj,dyj,gy,dy,doo,allLine,allGap,lineW,gapW,mode,picsLst);
wxpO.draw(caCt);
//gen("circleDo"); /*生成间线对象列表*/
if(debug)console.log("线间对象列表---Start");
var nowTop = caH - (lineW * allLine + gapW * allGap) + 0.5;
var high = 0;
// 高音谱上加
var base = gy.x + gy.j;
for(i=gyj.x+gyj.j;i>=1;i--){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("gyj: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
// 高音谱
base = 0;
for(i=gy.x+gy.j;i>=1;i--){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("gy: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
// doo
jxObjLst.push({"v":0,"top":nowTop,"high":lineW,"type":"Line"});
if(debug)console.log("doo: v "+0,"top "+nowTop,"high "+lineW,"type "+"Line");
nowTop += lineW;
// 低音谱
base = 0;
for(i=1;i<=dy.x+dy.j;i++){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("dy: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
// 低音谱下加
base = -dy.x-dy.j;
for(i=1;i<=dyj.x+dyj.j;i++){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("dyj: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
if(debug)console.log("线间对象列表---End"); }else if(mode==1){
/*五线谱*/
//五线谱 高度
buttonH = parseInt(caH / 3 * 2);
//线宽为间宽的0.5
lineW = parseInt(buttonH / (allGap*2+allLine));
//间宽
gapW = lineW * 2;
/*线等高于间 补丁,线太细就太难点中了*/
lineW = parseInt(buttonH / (allGap+allLine));
gapW = lineW;
//最高音
highest = gyj.x + gyj.j + gy.x + gy.j;
//最低音
low = dyj.x + dyj.j + dy.x + dy.j;
//五线谱最左边
wxpDoLeft = gapW * 6; if(debug)
console.log("线宽 "+lineW,"间宽 "+gapW);
wxpO = new wxp(caH,caW,buttonH,gyj,dyj,gy,dy,doo,allLine,allGap,lineW,gapW,mode,picsLst);
wxpO.draw(caCt);
//gen("circleDo"); /*生成间线对象列表*/
if(debug)console.log("线间对象列表---Start");
var nowTop = 0;
var high = 0;
// 高音谱上加
var base = gy.x + gy.j;
for(i=gyj.x+gyj.j;i>=1;i--){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("gyj: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
// 高音谱
base = 0;
for(i=gy.x+gy.j;i>=1;i--){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("gy: v "+(base+i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
// doo
jxObjLst.push({"v":0,"top":nowTop,"high":lineW,"type":"Line"});
if(debug)console.log("doo: v "+0,"top "+nowTop,"high "+lineW,"type "+"Line");
nowTop += lineW;
// 低音谱
base = 0;
for(i=1;i<=dy.x+dy.j;i++){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("dy: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
// 低音谱下加
base = -dy.x-dy.j;
for(i=1;i<=dyj.x+dyj.j;i++){
if(i%2==0){
high = lineW;
}else{
high = gapW;
}
jxObjLst.push({"v":(base-i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"});
if(debug)console.log("dyj: v "+(base-i),"top "+nowTop,"high "+high,"type "+(i%2==0?"Line":"gap"));
nowTop += high;
}
if(debug)console.log("线间对象列表---End");
/*唱名按钮*/
var rw = Math.floor(caW / 8);
var rh = Math.floor((caH - Math.ceil(buttonH)) / 4);
var r = rw<rh?rw:rh;
if(debug)console.log("唱名打击按钮半径: ",rw,rh,r);
for(var i=0;i<7;i++){
var name = ((i==0)?"do":(i==1)?"re":(i==2)?"mi":(i==3)?"fa":(i==4)?"so":(i==5)?"la":(i==6)?"si":"do");
var diff = Math.floor(caH - Math.ceil(buttonH));
var top = 0;
var left = 0;
if(i<3){
top = Math.ceil(buttonH) + Math.floor(diff / 4);
left = (caW / 3) * (0.5 + i%3);
}else{
top = Math.ceil(buttonH) + Math.floor(diff / 4 * 3);
left = (caW / 4) * (0.5 + (i-3)%4);
}
djBtnLst.push(new djBtn(bgCLst[i],fontCLst[i],name,name,top,r,left));
djBtnLst[i].draw(caCt);
}
} }
function gen(name) {
/*product object*/
switch(name){
case "circleDo":
//音值
var v = parseInt(
Math.random()>0.34
?Math.random()*(highest)
:-1*low+Math.random()*(low)
);
//唱名
var vT = Math.abs(v % 7);
vT = v<0?7-vT:vT;
//音阶
var yj = (v / 7)>0?Math.floor(v / 7):Math.ceil(v / 7);
var name2 =
v<0?((yj-1)+'').replace('-','↓'):((yj>=1&&v!=6)?"↑":'')
+((yj-((v+7)%7==0?1:0))+'').replace("0",'').replace("-1",'');
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;
r = Math.floor((caH - buttonH)/4);
cy = Math.floor(r + Math.random()*(caH - buttonH - 2*r));
if(debug)console.log("音值 "+v,"唱名 "+name,"音阶 "+yj,"唱名值 "+vT);
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);
circleDoLst.push(cDo);
//cDo.draw(caCt);
break;
case "wxpDo":
//音值
var v = parseInt(
Math.random()>0.34
?Math.random()*(highest)
:-1*low+Math.random()*(low)
);
//唱名
var vT = Math.abs(v % 7);
vT = v<0?7-vT:vT;
//音阶
var yj = (v / 7)>0?Math.floor(v / 7):Math.ceil(v / 7);
var name2 =
v<0?((yj-1)+'').replace('-','↓'):((yj>=1&&v!=6)?"↑":'')
+((yj-((v+7)%7==0?1:0))+'').replace("0",'').replace("-1",'');
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;
r = Math.floor(gapW*1);
var cy = 0;
for(var j=0;j<jxObjLst.length;j++){
if(jxObjLst[j].v==v){
cy = jxObjLst[j].top+jxObjLst[j].high*0.5;
break;
}
}
if(debug)console.log("音值 "+v,"唱名 "+name,"音阶 "+yj,"唱名值 "+vT);
var cDo =new wxpDo('blue','white',v,name,cy,r,wxpDoLst.length>0?wxpDoLst[wxpDoLst.length-1].left+gapW*4:caW-gapW*2);
wxpDoLst.push(cDo);
cDo.draw(caCt);
//cDo.draw(caCt);
break;
default:
}
}
function picIsLoaded() {
return toLoadPicCount <= loadPicCount ? true : false;
}
function loadPics() {
/*load pic to objectList*/
for (var i = 0; i < pics.length; i++) {
var imgTmp = new Image();
imgTmp.src = pics[i];
imgTmp.onload = loadedImg;
picsLst.push(imgTmp);
}
}
function loadedImg() {
//console.log(loadPicCount, toLoadPicCount);
return ++loadPicCount;
}
function animate(time) {
if (picIsLoaded()) {
if(!goOn && (wrong>=maxWrong || score<=-100 || score>15000)){
var s = Math.floor(score);
var name="";
if(s<=-50){
name='音盲';
}else if(s<500){
name='普通人'
}else if(s<5000){
name='识音达人'
}else if(s<10000){
name='识音天才'
}else{
name='绝对音感?'
}
document.getElementById("scoreC").innerHTML = "称号: "+name +",得分: "+s+" 【游戏结束】"; document.getElementsByTagName('title')[0].innerHTML = name+",得分【"+Math.floor(score)+"】";
document.getElementById("btn_start").style.display="block";
document.getElementById("gameWorldTouch").style.display="none";
return;
}
var now = (+new Date);
if (mode == 0 && now - lastFpsUpdateTimeBDJ > bdjTime) {
bdjLeft = circleDoLst.length>0?circleDoLst[0].left:r*2;
if(bdjLeft>=r){
lastFpsUpdateTimeBDJ = now;
wxpO.clearCircleDo(caCt);
for(var i=0;i<circleDoLst.length;i++){
circleDoLst[i].left -= bdjPX;
circleDoLst[i].draw(caCt);
}
bdjLeft = circleDoLst.length>0?circleDoLst[0].left:r*2;
if(circleDoLst.length>0 && (circleDoLst[circleDoLst.length-1].left+r)<= caW){
gen("circleDo");
}
/*draw canvas*/
//caCt.save();
//caCt.beginPath();
//caCt.restore();
}else{
if(!goOn)score-=scoreFu;
}
}
if (mode == 1 && now - lastFpsUpdateTimeBDJ > bdjTime) {
bdjLeft = wxpDoLst.length>0?wxpDoLst[0].left:wxpDoLeft;
if(bdjLeft>=wxpDoLeft){
lastFpsUpdateTimeBDJ = now;
wxpO.clearWXPDo(caCt);
for(var i=0;i<wxpDoLst.length;i++){
wxpDoLst[i].left -= bdjPX;
wxpDoLst[i].draw(caCt);
}
bdjLeft = wxpDoLst.length>0?wxpDoLst[0].left:wxpDoLeft;
if(wxpDoLst.length>0 && wxpDoLst[wxpDoLst.length-1].left<= caW){
gen("wxpDo");
if(debug){console.log('a');}
}
/*draw canvas*/
//caCt.save();
//caCt.beginPath();
//caCt.restore();
}else{
if(!goOn)score-=scoreFu;
}
} /*score*/
if(!goOn){
document.getElementById("scoreC").innerHTML = "得分: "+Math.floor(score)+" 错误: "+wrong+" / "+maxWrong;
}else{
document.getElementById("lx").innerHTML = "无限练习模式,点击此处返回菜单";
document.getElementById("lx").addEventListener("click", backMenu, false);
document.getElementById("lx").addEventListener("touchstart", backMenu, false);
}
}
window.requestNextAnimationFrame(animate);
/*if (isStop) {
isStart = false;
btn_start.innerHTML += "<br />游戏结束,马上重新开始";
reStart();
return;
}
if (isStart) {
//var pastTime = Math.round(((new Date).getTime() - startTime) / 1E3 * 100) / 100;
btn_start.innerHTML = pastTime;
btn_start.innerHTML = "分数: " + goodPass + " <br />用时: " + pastTime + " 秒";
var now = (+new Date);
if (now - lastFpsUpdateTime > 100) {
lastFpsUpdateTime = now;
goOn();
caCt.fillStyle = "#fff";
caCt.fillRect(0, 0, caObj.width, caObj.height);
caCt.fillStyle = "#000";
//caCt.clearRect(0, 0, caObj.width, caObj.height);
drawBird();
drawZALst();
doJudge();
}
} else {
caCt.clearRect(0, 0, caObj.width, caObj.height);
drawBird();
drawZALst();
}*/
}
function backMenu(){
document.getElementById("btn_start").style.display= "block";
document.getElementById("gameWorldTouch").style.display="none";
return;
}
function eventBund(){
if(!v){
//caTObj.addEventListener("mousemove", onMouseMove, false);
caTObj.addEventListener("click", onMouseClick, false);
}else{
caTObj.addEventListener("touchstart", onTouchStart, false);
caTObj.addEventListener("touchmove", onTouchMove, false);
caTObj.addEventListener("touchend", stopEvent, false);
caTObj.addEventListener("touchcancel", stopEvent, false);
caTObj.addEventListener("gesturestart", stopEvent, false);
caTObj.addEventListener("gesturechange", stopEvent, false);
caTObj.addEventListener("gestureend", stopEvent, false);
}
//document.getElementById("s1").addEventListener("click", onStart, false);
//document.getElementById("s2").addEventListener("click", onStart, false);
}
function onStart(e){
document.getElementById("btn_start").style.display="none";
if(!goOn){
document.getElementById("scoreC").style.display="block";
}else{
document.getElementById("lx").style.display="block";
}
}
function onMouseMove(e){
//mouseTObj.x = e.pageX;
//mouseTObj.y = e.pageY;
}
function onTouchMove(e){
e.preventDefault();
var touch = e.touches[0];
//mouseTObj.x = touch.pageX;
//mouseTObj.y = touch.pageY;
return false;
}
function onTouchStart(e){
e.preventDefault();
var touch = e.touches[0];
touched({"x":touch.pageX,"y":touch.pageY});
//mouseTObj.x = touch.pageX;
//mouseTObj.y = touch.pageY;
return false;
}
function onMouseClick(e){
touched({"x":e.pageX,"y":e.pageY});
}
function touched(pos){
if(mode==0){
// 五线谱
if(debug){console.log("click: ",pos);}
/*判断哪个线间被点中*/
//jxObjLst item: {"v":(base+i),"top":nowTop,"high":high,"type":i%2==0?"Line":"gap"}
var value = null;
for(i=0;i<jxObjLst.length;i++){
//if(debug){console.log("loop: ",jxObjLst[i].top,jxObjLst[i].high);}
if(pos.y>jxObjLst[i].top){
if(pos.y<=jxObjLst[i].top + jxObjLst[i].high){
value = jxObjLst[i];
break;
}
}
}
if(value==null)return;
if(debug){console.log("poisiton,value",pos,value);}
/*判断正确与否,并消除被打击对象*/
if(debug)console.log('被打击对象列表: ',circleDoLst);
/*高亮提示当前所点线间*/
if(value!=null){
//唱名
var vT = Math.abs(value.v % 7);
vT = value.v<0?7-vT:vT;
var name = ((vT==0)?"do":(vT==1)?"re":(vT==2)?"mi":(vT==3)?"fa":(vT==4)?"so":(vT==5)?"la":(vT==6)?"si":"do");
// 画图
caTCt.clearRect(0,0,caW,caH);
wxpO.drawOne(caTCt,value.top,value.high,alertColor);
wxpO.drawText(caTCt,caW/2,caH/2,caW/5,name,alertColor);
setTimeout(clearTouchCanvas,alertTime);
}
if(circleDoLst.length>0 && value!=null && circleDoLst[0].value == value.v){
if(debug)console.log("%cclick right!!!","color:green");
if(debug)console.log('被打击对象列表: ',circleDoLst);
circleDoLst.splice(0,1);
gen("circleDo");
bdjLeft = circleDoLst.length>0?circleDoLst[0].left:2*r;
if(!goOn)score+=scoreOne;
//wxpO.clearCircleDo(caCt);
//gen("circleDo"); // temp
}else{
if(debug)console.log("%cclick wrong!!!","color:red");
if(!goOn)wrong++;
if(debug)console.log("error",wrong);
}
}else if(mode==1){
// 五线谱
if(debug){console.log("click: ",pos);}
/*判断哪个按钮点中*/
//djBtnLst item: (bgC,fontC,value,name,top,r,left)
var value = null;
for(i=0;i<djBtnLst.length;i++){
//if(debug){console.log("loop: ",jxObjLst[i].top,jxObjLst[i].high);}
//var distance = Math.abs(((pos.x-djBtnLst[i].left)^2 + (pos.y-djBtnLst[i].top)^2)^0.5);
var calX = pos.x - djBtnLst[i].left;
var calY = pos.y - djBtnLst[i].top;
var distance = Math.pow((calX *calX + calY * calY), 0.5); console.log(distance,djBtnLst[i].r);
if(distance<=djBtnLst[i].r){
value = djBtnLst[i];
break;
}
}
if(value==null)return;
if(debug){console.log("poisiton,value",pos,value);}
/*判断正确与否,并消除被打击对象*/
if(debug)console.log('被打击对象列表: ',wxpDoLst);
/*高亮提示当前点击的所有线间*/
caTCt.clearRect(0,0,caW,caH);
if(value!=null){
//线间list
//var indexLst = [];
for(var i = 0;i<jxObjLst.length;i++){
var vT = Math.abs(jxObjLst[i].v % 7);
vT = jxObjLst[i].v<0?7-vT:vT;
var name = ((vT==0)?"do":(vT==1)?"re":(vT==2)?"mi":(vT==3)?"fa":(vT==4)?"so":(vT==5)?"la":(vT==6)?"si":"do");
if(name==value.name){
wxpO.drawOne(caTCt,jxObjLst[i].top,jxObjLst[i].high,alertColor);
}
//if(name==value.name){indexLst.push(i);}
}
// 清空画图
setTimeout(clearTouchCanvas,alertTime);
}
if(wxpDoLst.length>0 && value!=null && wxpDoLst[0].name.indexOf(value.name)!=-1){
if(debug)console.log("%cclick right!!!","color:green");
if(debug)console.log('被打击对象列表: ',circleDoLst);
wxpDoLst.splice(0,1);
gen("wxpDo");
bdjLeft = wxpDoLst.length>0?wxpDoLst[0].left:wxpDoLeft;
if(!goOn)score+=scoreOne;
//wxpO.clearCircleDo(caCt);
//gen("circleDo"); // temp
}else{
if(debug)console.log("%cclick wrong!!!","color:red");
if(!goOn)wrong++;
if(debug)console.log("error",wrong);
}
}
}
function clearTouchCanvas(){
caTCt.clearRect(0,0,caW,caH);
if(debug)console.log('clear');
}
function stopEvent(e) { e.preventDefault(); e.stopPropagation(); }
var v = navigator.userAgent.toLowerCase().indexOf("android") != -1 || navigator.userAgent.toLowerCase().indexOf("iphone") != -1 || navigator.userAgent.toLowerCase().indexOf("ipad") != -1,
caW = window.innerWidth,
caH = window.innerHeight,
caObj = document.getElementById("gameWorld"),
caCt = caObj.getContext("2d"),
caTObj = document.getElementById("gameWorldTouch"),
caTCt = caTObj.getContext("2d"),
//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"],
//rabitPicOLst = [],
pics = ['img/gyph.png','img/dyph.png'],
loadPicCount = 0,
toLoadPicCount = 2,
/*线与间*/
//高音普上加线,3线,2间,上下无间
gyj = {x:2,j:2,up:0,down:0},
//低音普上加线,2线,1间,上下无间
dyj = {x:0,j:0,up:0,down:0},
//高音普线,5线,6间,上下有间
gy = {x:5,j:5,up:1,down:1},
//低音普线,5线,6间,上下有间
dy = {x:5,j:5,up:1,down:1},
//高音低音间do
doo = {x:1,j:1,up:0,down:0},
//最高音 五线谱用
highest = 0,
//最低音 五线谱用
low = 0,
//被打击对象列表 五线谱用
circleDoLst = [],
//被打击对象列表 唱名用
wxpDoLst = [],
//总线数
allLine = 0,
//总间数
allGap = 0,
//线宽
lineW = 0,
//间宽
gapW = 0,
//打击区总高度
buttonH = 0,
//五线谱object
wxpO = null,
//唱名object
cmO = null,
//模式 0:五线谱打,1:唱名打
mode = mode,
//间线对象列表
jxObjLst = [],
//颜色 五线谱用
bgCLst = ["green","red","blue","green","pink","orange","yellow","gray"],
fontCLst = ["yellow","yellow","white","white","blue","white","black","yellow"],
// 被打击对象平移更新时间
bdjTime = 100,
// 被打击对象平移速度
bdjPX = 5,
// 被打击对象最左端
bdjLeft = 0,
// 被打击对象半径
r = 0,
// 唱名打击用
// 唱名button列表
djBtnLst = [],
// 被打击对象初期数
bdjInitCount = 5,
// 提示颜色
alertColor = "rgba(102,0,255,0.5)",
// 提示时间
alertTime = 500,
// 五线谱音符最左边
wxpDoLeft = 0,
scoreOne=50,
scoreFu = 0.1;
score=0,
wrong=0,
maxWrong = 10,
picsLst=[],
goOn = goOn
; this.init = function () {
mode = this.mode;
goOn = this.goOn;
//*********load images*********
loadPics();
//*********init params*******
doVarInit();
//*********init size and vars*******
doSize();
//*********product bell and rabit*******
for(var i = 0;i<bdjInitCount;i++)
if(mode==0){
gen("circleDo");
}else{
gen("wxpDo");
}
//*********Event***********
eventBund();
//*********Gen***********
//*********animate***********
animate();
}
} /*
* 五线谱 object
*/
function wxp(caH,caW,buttonH,gyj,dyj,gy,dy,doo,allLine,allGap,lineW,gapW,mode,picLst) {
this.mode = mode; //0: 打谱,1: 打唱名
this.caH = caH; // 画面高度
this.caW = caW; // 画面宽度
this.buttonH=buttonH; // 打击区高度
this.gyj=gyj; // 高音上
this.dyj=dyj; // 低音下
this.gy=gy; // 高音
this.dy=dy; // 低音
this.doo=doo; // 中间do
this.allLine=allLine; // 总线
this.allGap=allGap; // 总间
this.lineW=lineW; // 线高
this.gapW=gapW; // 间高
this.picLst = picLst;
}
wxp.prototype.clearCircleDo = function (context) {
// 打谱用
var circleDoH = this.caH - (this.lineW * this.allLine + this.gapW * this.allGap) + 0.5;
context.clearRect(0,0,this.caW,circleDoH);
/*context.save();
context.fillStyle = 'white';
context.fillRect(0,0,this.caW,circleDoH);
context.restore();*/
}
wxp.prototype.clearWXPDo = function (context) {
// 打唱名用
context.clearRect(0,0,this.caW,this.buttonH);
this.draw(context);
/*context.save();
context.fillStyle = 'white';
context.fillRect(0,0,this.caW,circleDoH);
context.restore();*/
}
wxp.prototype.drawOne = function (context,top,high,color) {
context.save();
context.beginPath();
context.fillStyle = color;
context.fillRect(0,top,this.caW,high);
context.closePath();
context.restore();
}
wxp.prototype.drawText = function (context,x,y,size,text,color) {
context.save();
context.beginPath();
context.fillStyle = color;
context.font = parseInt(size)+"pt Calibri";
context.textBaseline = 'middle';
context.textAlign='center';
context.fillText(text,x,y);
context.closePath();
context.restore();
}
wxp.prototype.draw = function (context) {
var gyphT = 0,gyphH = (this.gapW+this.lineW) * 6,gyphW = this.gapW * 3;
var dyphT = 0,dyphH = (this.gapW+this.lineW) * 3,dyphW = this.gapW * 3;
/*画线*/
var nowTop = 0;
if(this.mode==0){
nowTop = this.caH - (this.lineW * this.allLine + this.gapW * this.allGap) + 0.5;
}
context.save();
for(var i=1;i<=this.gyj.x;i++){
context.beginPath();
context.lineWidth = this.lineW/2;
context.fillStyle = "gray";
context.strokeStyle = "gray";
context.moveTo(0,nowTop+this.lineW/2);
context.lineTo(this.caW,nowTop+this.lineW/2);
context.stroke();
context.fill();
nowTop += this.lineW + this.gapW;
}
for(var i=1;i<=this.gy.x;i++){
if(i==1)gyphT = nowTop - this.gapW * 2;
context.beginPath();
context.lineWidth = this.lineW/2;
context.fillStyle = "black";
context.strokeStyle = "black";
context.moveTo(0,nowTop+this.lineW/2);
context.lineTo(this.caW,nowTop+this.lineW/2);
context.stroke();
context.fill();
nowTop += this.lineW + this.gapW;
}
for(var i=1;i<=this.doo.x;i++){
context.beginPath();
context.lineWidth = this.lineW/2;
context.fillStyle = "red";
context.strokeStyle = "red";
context.moveTo(0,nowTop+this.lineW/2);
context.lineTo(this.caW,nowTop+this.lineW/2);
context.stroke();
context.fill();
nowTop += this.lineW + this.gapW;
}
for(var i=1;i<=this.dy.x;i++){
if(i==1)dyphT = nowTop + this.gapW * 0;
context.beginPath();
context.lineWidth = this.lineW/2;
context.fillStyle = "black";
context.strokeStyle = "black";
context.moveTo(0,nowTop+this.lineW/2);
context.lineTo(this.caW,nowTop+this.lineW/2);
context.stroke();
context.fill();
nowTop += this.lineW + this.gapW;
}
for(var i=1;i<=this.dyj.x;i++){
context.beginPath();
context.lineWidth = this.lineW/2;
context.fillStyle = "gray";
context.strokeStyle = "gray";
context.moveTo(0,nowTop+this.lineW/2);
context.lineTo(this.caW,nowTop+this.lineW/2);
context.stroke();
context.fill();
nowTop += this.lineW + this.gapW;
}
context.closePath();
context.restore();
/*画谱号*/
/*var gImg = new Image();
var dImg = new Image();
gImg.src = 'img/gyph.png';
dImg.src = 'img/dyph.png';
gImg.onload = function(){context.drawImage(gImg,10,gyphT,gyphW,gyphH);}
dImg.onload = function(){context.drawImage(dImg,10,dyphT,dyphW,dyphH);}*/ context.drawImage(this.picLst[0],10,gyphT,gyphW,gyphH);
context.drawImage(this.picLst[1],10,dyphT,dyphW,dyphH);
} /*
* 五线谱用 被打击对象 object
*/
function circleDo(bgC,fontC,value,name,top,r,left) {
this.bgC = bgC; // 背景颜色
this.fontC = fontC; // 字体颜色
this.value=value; // 音值
this.name=name; // 显示文字
this.left=left; // r,left
this.top=top; // top
this.r=r; // 半径
}
circleDo.prototype.draw = function (context) {
context.save();
context.fillStyle = this.bgC;
context.beginPath();
context.arc(this.left/* + 75*/,this.top/* +75*/,this.r,0,2*Math.PI);
context.closePath();
context.fill(); context.fillStyle = this.fontC;
context.font = parseInt(this.r/2)+"pt Calibri";
context.textBaseline = 'middle';
context.textAlign='center';
context.fillText(this.name, this.left/* + 75*/,this.top/* +75*/);
context.restore();
} /*
* 唱名用 唱名button object
*/
function djBtn(bgC,fontC,value,name,top,r,left) {
this.bgC = bgC; // 背景颜色
this.fontC = fontC; // 字体颜色
this.value=value; // 音值
this.name=name; // 显示文字
this.left=left; // r,left
this.top=top; // top
this.r=r; // 半径
}
djBtn.prototype.draw = function (context) {
context.save();
context.fillStyle = this.bgC;
context.beginPath();
context.arc(this.left/* + 75*/,this.top/* +75*/,this.r,0,2*Math.PI);
context.closePath();
context.fill(); context.fillStyle = this.fontC;
context.font = parseInt(this.r/2)+"pt Calibri";
context.textBaseline = 'middle';
context.textAlign='center';
context.fillText(this.name, this.left/* + 75*/,this.top/* +75*/);
context.restore();
}
/*
* 唱名用 被打击对象 object
*/
function wxpDo(bgC,fontC,value,name,top,r,left) {
this.bgC = bgC; // 背景颜色
this.fontC = fontC; // 字体颜色
this.value=value; // 音值
this.name=name; // 显示文字
this.left=left; // left
this.top=top; // top
this.r=r; // 半径
}
wxpDo.prototype.draw = function (context) {
context.save();
context.strokeStyle = this.bgC;
context.lineWidth = this.r*0.5;
this.ParamEllipse(context,this.left,this.top,this.r*1.5,this.r); var lineLeft1 = 0;
var lineTop1 = 0;
var lineLeft2 = 0;
var lineTop2 = 0;
if(this.value>=6){
//第三线以上,下尾巴
lineLeft1=lineLeft2=-1*this.r*1.4;
lineTop1=0;
lineTop2=this.r*5;
}else{
lineLeft1=lineLeft2=this.r*1.4;
lineTop1=0;
lineTop2=-1*this.r*5;
}
context.beginPath();
context.moveTo(lineLeft1,lineTop1);
context.lineTo(lineLeft2,lineTop2);
context.stroke();
context.closePath(); context.restore();
}
//---------使用三次贝塞尔曲线模拟椭圆1---------------------
//此方法也会产生当lineWidth较宽,椭圆较扁时,
//长轴端较尖锐,不平滑的现象
wxpDo.prototype.ParamEllipse = function(context, x, y, a, b){
//关键是bezierCurveTo中两个控制点的设置
//0.5和0.6是两个关键系数(在本函数中为试验而得)
var ox = 0.5 * a,
oy = 0.6 * b;
//context.save();
context.translate(x, y);
context.beginPath();
//从椭圆纵轴下端开始逆时针方向绘制
context.moveTo(0, b);
context.bezierCurveTo(ox, b, a, oy, a, 0);
context.bezierCurveTo(a, -oy, ox, -b, 0, -b);
context.bezierCurveTo(-ox, -b, -a, -oy, -a, 0);
context.bezierCurveTo(-a, oy, -ox, b, 0, b);
context.closePath();
context.stroke();
//context.restore();
};
/*example of object*/
/*
* bell object
*/
/*function bell(top, left, width, height, si, maxSI) {
this.t = top; // 高度
}
bell.prototype.disappear = function (speed) {
this.a -= speed;
return this.a <= 0 ? true : false;
}*/ /*example of extends*/
/*
* bird object
*/
/*function bird(top, left, width, height, si, maxSI, direction) {
this.t = top; // 高度
}
bird.prototype = new bell;
*/ var gameWorldObj = null;
onload = function () {
document.getElementsByTagName('title')[0].innerHTML = "[WXS]五线谱游戏";
/*gameWorldObj = new gameWorld(0);
gameWorldObj.init();*/
}
function staffGameGo(mode,goOn){
if(gameWorldObj == null)
gameWorldObj = new gameWorld(mode,goOn);
gameWorldObj.goOn = goOn;
gameWorldObj.mode = mode;
gameWorldObj.init();
document.getElementById("btn_start").style.display="none";
if(!goOn){
document.getElementById("scoreC").style.display="block";
document.getElementById("lx").style.display="none";}
else{
document.getElementById("lx").style.display="block";
document.getElementById("scoreC").style.display="none";
}
}

---

CSDN下载:

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

[原创]html5游戏_五线谱打音符的更多相关文章

  1. [原创]html5游戏_贪吃蛇

    代码随便写写,尚有许多不足,PC与手机端皆可运行 手机端滑屏操作,PC端方向键操作 疑问: 生成食物,与判断是否可以移动方面 有两种实现方式, 1.使用js内存,数组循环判断 2.使用dom的quer ...

  2. [原创]html5_PC游戏_图片俄罗斯方块

    PC游戏_图片俄罗斯方块 以前的了,快一年了... 使用了离线canvas复制的方法,启动预览效果需要服务器支持 另外,AC娘图片可以自己做加载功能,这样游戏图片显示更顺畅 效果: --- 代码: h ...

  3. JS开发HTML5游戏《神奇的六边形》(一)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  4. HTML5游戏开发引擎,初识CreateJS

    CreateJS为CreateJS库,可以说是一款为HTML5游戏开发的引擎.打造 HTML5 游戏,构建新游戏,提供构建最新 HTML5 的技术.你可以通过这个网站学习如何构建跨平台和跨终端游戏.这 ...

  5. JS开发HTML5游戏《神奇的六边形》(二)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  6. 2016年 最火的 15 款 HTML5 游戏引擎

    HTML5游戏从2014年Egret引擎开发的神经猫引爆朋友圈之后,就开始一发不可收拾,今年<传奇世界>更是突破流水2000万!从两年多的发展来看,游戏开发变得越来越复杂,需要制作各种炫丽 ...

  7. 开源免费的HTML5游戏引擎

    青瓷引擎的成长 青瓷引擎自2015年4月项目启动开始,7月首次亮相2015年ChinaJoy,便得到业界的极大关注,随后开启限量测试,收到数百个开发者团队的试用申请及反馈,期间经历了18个内测版本,完 ...

  8. CutJS – 用于 HTML5 游戏开发的 2D 渲染引擎

    CutJS 是轻量级的,快速的,基于 Canvas 开发的 HTML5  2D 渲染引擎,可以用于游戏开发.它是开源的,跨平台的,与现代的浏览器和移动设备兼容.CutJS 提供了一个类似 DOM 树的 ...

  9. Molecule – 帮助你构建跨平台的 HTML5 游戏

    Molecule 框架由拥有超过五年手机游戏开发经验的游戏开发者开发.由于移动浏览器与实际的 HTML5 规范的兼容性的改进和内部硬件的自然进化,HTML5 手机游戏真正有可能流行起来. 您可能感兴趣 ...

随机推荐

  1. Linux中vi显示中文乱码的问题

    由于在windows下默认是gb编码,而我的vim默认是utf-8(gedit默认也是utf-8),所以打开会成乱码.修改了一下配置文件,使vi支持gb编码就好了.$vi ~/.vimrclet &a ...

  2. 解决在IE下LABEL中IMG图片无法选中RADIO的几个方法

    转http://www.cnblogs.com/chenxianbin89/archive/2012/11/25/2787258.html . 方法三,THML代码控制: 在IMG中加一个属性,dis ...

  3. 解决clone问题之外的体会

    adlnkoh.sh started at Thu Aug 25 15:42:51 CST 2016 Log file located at /u02/db/testdb/11.1.0/appsuti ...

  4. Android Material Design控件学习(一)——TabLayout的用法

    前言 Google官方在14年Google I/O上推出了全新的设计语言--Material Design.一并推出了一系列实现Material Design效果的控件库--Android Desig ...

  5. osgi:设置httpservice端口号

    使用osgi开发http类的Service,在启动时默认端口是80.但有可能这个端口已经被本机上的其他程序占用.那么解决问题的方法有两种:1)关闭或修改占用程序的端口: 2)修改osgi启动时的端口. ...

  6. 蓝凌表单的表体调用Javascript

    应用场景:像请假类表单会在从表输入开始时间.结束时间等字段 需求1:客户希望根据开始.结束时间自动计算小时数 解决方法: 1.主表单增加一行,设三个字段[开始时间合计].[结束时间合计].[开始结束时 ...

  7. Java Annotation认知(包括框架图、详细介绍、示例说明)

    摘要 Java Annotation是JDK5.0引入的一种注释机制. 网上很多关于Java Annotation的文章,看得人眼花缭乱.Java Annotation本来很简单的,结果说的人没说清楚 ...

  8. Android manifest之系统自带的permission

    Android manifest之系统自带的permission 本文描述Android系统自带的permission.点击查看:“关于permission的原始定义和说明”.点击查看:“Androi ...

  9. Hadoop第10周练习—Mahout部署及进行20newsgroup数据分析例子

    :搭建Mahout环境 :运行20newsgroup 内容 运行环境说明 1.1 硬软件环境 线程,主频2.2G,6G内存 l  虚拟软件:VMware® Workstation 9.0.0 buil ...

  10. [Node.js] BDD和Mocha框架

    原文地址:http://www.moye.me/2014/11/22/bdd_mocha/ 引子 今天造了个轮子:写了个深拷贝任意JavaScript对象的模块(事实上npm上已经有类似的模块,纯造轮 ...