Skip to content

Instantly share code, notes, and snippets.

@hakatashi
Created June 22, 2014 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakatashi/02b0717e27e422d72cb9 to your computer and use it in GitHub Desktop.
Save hakatashi/02b0717e27e422d72cb9 to your computer and use it in GitHub Desktop.
var YouTyping=function(){function ぴ(ぴ){var ょ=new Date,ぴょ=ん(ょ.getHours(),2),ょょ=ん(ょ.getMinutes(),2),んょ=ん(ょ.getSeconds(),2),ぴん=ん(ょ.getMilliseconds(),3);$("#debug").append("["+ぴょ+":"+ょょ+":"+んょ+"."+ぴん+"] "+ぴ+"\n"),console.log(ぴ)}function ょ(ぴ){ぴ=ぴ.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var ょ=new RegExp("[\\?&]"+ぴ+"=([^&#]*)"),ん=ょ.exec(location.search);return null===ん?"":decodeURIComponent(ん[1].replace(/\+/g," "))}function ん(ぴ,ょ){return ぴ=ぴ.toString(),ぴ.length<ょ?ん("0"+ぴ,ょ):ぴ}var ぴょ=function(ん,ぴょ){var んょ=this;this.noteState={WAITING:0,HITTING:1,CLEARED:2,HITTINGFAILED:3,FAILED:4};var ょん,んん=function(){ょん=$.Deferred(),ぴ("Setting Player Up...");var ょ=document.createElement("script");ょ.src="https://www.youtube.com/iframe_api";var ん=document.getElementsByTagName("script")[0];return ん.parentNode.insertBefore(ょ,ん),ょん.promise()};window.onYouTubeIframeAPIReady=function(){var ん=んょ.settings;ぴ("Player API is Ready."),"true"===ょ("sandbox")&&this.DOM.player.setAttribute("sandbox","allow-same-origin allow-scripts"),んょ.player=new YT.Player("youtyping-player",{height:ん.height,width:ん.width,videoId:ん.videoId,playerVars:{rel:0,start:ん.offset,controls:0,showinfo:0,modestbranding:1,wmode:"opaque"},events:{onReady:んぴょ,onStateChange:ぴょょ,onError:ょょょ}})};var ぴぴょ,ょぴょ,んぴょ=function(){ぴ("Player is Ready."),んょ.player.setVolume(んょ.settings.volume),んょ.player.setPlaybackQuality(んょ.settings.playbackQuality),ょん.resolve()},ぴょょ=function(ょ){switch(ぴょん.onPlayerStateChange&&ぴょん.onPlayerStateChange.call(ぴょん,ょ),ょ.data){case YT.PlayerState.ENDED:ぴ("Player Ended.");break;case YT.PlayerState.PLAYING:ぴ("Player Started.");break;case YT.PlayerState.PAUSED:ぴ("Player Paused.");break;case YT.PlayerState.BUFFERING:ぴ("Player Buffering.");break;case YT.PlayerState.CUED:ぴ("Player Cued.")}},ょょょ=function(ょ){switch(ょ.data){case 2:ぴ("ERROR: The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.");break;case 5:ぴ("ERROR: The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.");break;case 100:ぴ("ERROR: The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.");break;case 101:ぴ("ERROR: The owner of the requested video does not allow it to be played in embedded players.");break;case 150:ぴ("ERROR: The owner of the requested video does not allow it to be played in embedded players.")}ょん.reject()},んょょ=function(){return ぴぴょ=$.Deferred(),$.ajax({url:んょ.settings.dataFile,type:"get",datatype:"xml",timeout:1e3,success:function(ょ){んょ.dataXML=$(ょ).find("data").first();var ん=んょ.dataXML.find("roll > item");んょ.roll=[],$(ん).each(function(){var ぴ={time:1e3*parseFloat($(this).attr("time")),type:$(this).attr("type")};$(this).has("text")&&(ぴ.text=ぴ.remainingText=$(this).children("text").text()),"note"===ぴ.type&&(ぴ.state=んょ.noteState.WAITING),んょ.roll.push(ぴ)}),んょ.nextLyricIndex=んんょ(-1),ぴ("Loaded XML File."),ぴぴょ.resolve()},error:function(ょ,ん,ぴょ){ぴ("ERROR: XML File Loading Failed: "+ぴょ),ぴぴょ.reject()}}),ぴぴょ.promise()},ぴんょ=function(){return ょぴょ=$.Deferred(),$.ajax({url:んょ.settings.tableFile,type:"get",datatype:"xml",timeout:1e3,success:function(ょ){try{んょ.table=[],$(ょ).find("table").find("rule").each(function(ぴ){if(んょ.table.push({before:$(this).attr("before"),after:$(this).attr("after"),next:$(this).attr("next")}),$(this).attr("next")&&1!==$(this).attr("next").length)throw"Rule "+ぴ+": next string must be one character"}),ぴ("Loaded Table File."),ょぴょ.resolve()}catch(ん){ぴ("ERROR: Table File Parsing Failed: "+ん),ょぴょ.reject()}},error:function(ょ,ん,ぴょ){ぴ("ERROR: Table File Loading Failed: "+ぴょ),ょぴょ.reject()}}),ょぴょ.promise()},ょんょ=function(ぴ){for(var ょ=null,ん=ぴ+1;ん<んょ.roll.length;ん++){var ぴょ=んょ.roll[ん];if("stop"===ぴょ.type){ょ=null;break}if("note"===ぴょ.type){ょ=ん;break}}return ょ},んんょ=function(ぴ){for(var ょ=null,ん=ぴ+1;ん<んょ.roll.length;ん++){var ぴょ=んょ.roll[ん];if("lyric"===ぴょ.type){ょ=ん;break}}return ょ},ぴぴん=function(){var ぴ=んょ.player.getCurrentTime(),ょ=んょ.now;if(ぴ===んょ.settings.offset)んょ.zeroTimePad=ょ-1e3*んょ.settings.offset+んょ.correction,んょ.zeroTime=ょ-1e3*んょ.settings.offset+んょ.correction;else if(んょ.currentTime!==ぴ&&ぴ>んょ.settings.offset){んょ.currentTime=ぴ,んょ.estimatedZero=ょ-1e3*んょ.currentTime,んょ.estimateSamples.push(んょ.estimatedZero),んょ.estimateSamples.length>んょ.settings.zeroEstimateSamples&&んょ.estimateSamples.shift();var ん=んょ.estimateSamples.reduce(function(ぴ,ょ){return ぴ+ょ});んょ.zeroTimePad=ん/んょ.estimateSamples.length+んょ.correction,んょ.zeroCallFPS++}んょ.zeroTime=.9*(んょ.zeroTime-んょ.zeroTimePad)+んょ.zeroTimePad;var ぴょ=ょ-んょ.zeroTime,ょょ=null,ぴん=null;んょ.roll.forEach(function(ぴ,ょ){"note"===ぴ.type&&ぴ.time+んょ.settings.failureSuspension<ぴょ?(ぴ.state===んょ.noteState.WAITING||ぴ.state===んょ.noteState.HITTING)&&(ょょ&&(ょぴん(ょょ),ぴん===んょ.currentNoteIndex&&(んょ.currentNoteIndex=null,んょ.inputBuffer="")),ょょ=ぴ,ぴん=ょ):"lyric"===ぴ.type&&ぴ.time<ぴょ?んょ.currentLyricIndex<ょ&&(んょ.currentLyricIndex=ょ,んょ.nextLyricIndex=んんょ(ょ)):"stop"===ぴ.type&&ぴ.time<ぴょ&&(んょ.currentLyricIndex<ょ&&(んょ.currentLyricIndex=null),ょょ&&(ょぴん(ょょ),ぴん===んょ.currentNoteIndex&&(んょ.currentNoteIndex=null,んょ.inputBuffer="")),ょょ=null,ぴん=null)})},ょぴん=function(ぴ){ぴ.state===んょ.noteState.WAITING?ぴ.state=んょ.noteState.FAILED:ぴ.state===んょ.noteState.HITTING&&(ぴ.state=んょ.noteState.HITTINGFAILED),んょ.combo=0};this.startTime=Date.now(),this.dataXML=null,this.roll=null,this.player=null,this.settings={zeroEstimateSamples:16,videoId:"fQ_m5VLhqNg",dataFile:"data.utx",width:1120,height:630,hitPosition:.4,noteSize:50,speed:.5,rollYpos:.5,longLineHeight:150,lineHeight:120,screenPadding:30,bufferTextPosition:[.2,.8],currentLyricPosition:[.5,.25],nextLyricPosition:[.5,.3],kanaLyricPosition:[.5,.8],judges:[{name:"perfect",from:-50,to:50},{name:"great",from:-70,to:70},{name:"good",from:-100,to:100},{name:"bad",from:-1/0,to:150}],breakCombo:"bad",failureSuspension:100,correction:0,controlledCorrection:0,offset:0,volume:100,playbackQuality:"default",tableFile:"convert/romaji.xml"},this.zeroTime=0,this.zeroTimePad=0,this.currentTime=0,this.estimateSamples=[],this.estimatedZero=0,this.zeroCallFPS=0,Object.defineProperty(this,"now",{get:function(){return window.performance.now()}}),this.table=[],this.currentNoteIndex=null,this.inputBuffer="",this.currentLyricIndex=null,this.nextLyricIndex=null,this.combo=0,this.play=function(){んょ.player.playVideo(),setInterval(ぴぴん,10)},this.hit=function(ぴ,ょ,ん){ょ||(ょ=んょ.now-んょ.zeroTime);var ぴょ=function(ょ,ん){var ょょ=んょ.roll[ょ],ょん="";ょん=ょ===んょ.currentNoteIndex?んょ.inputBuffer+ぴ:ぴ,ん||(ん=ぴ);var んん=んょ.table.filter(function(ぴ){if(!ぴん(ぴ.before,ょん))return!1;if(!ぴん(ょょ.remainingText,ぴ.after))return!1;if(ぴ.next){var ん;if(null!==(ん=ょんょ(ょ))){var んょ=ぴょ(ん,ぴ.next);return んょ?!0:!1}return!1}return!0});if(0===んん.length)return!1;var ぴぴょ={noteIndex:ょ,forcedHit:null},ょぴょ=1/0,んぴょ=null;return んん.forEach(function(ぴ){ぴ.before.length<ょぴょ&&(ょぴょ=ぴ.before.length,んぴょ=ぴ)}),ぴぴょ.appliedRule=んぴょ,ょん.length===んぴょ.before.length?(ぴぴょ.remainingText=ょょ.remainingText.substr(んぴょ.after.length),ぴぴょ.inputBuffer="",んぴょ.next&&(ぴぴょ.forcedHit=んぴょ.next)):(ぴぴょ.remainingText=ょょ.remainingText,ぴぴょ.inputBuffer=ょん),ぴぴょ},ょょ=function(ぴ){var ん=んょ.roll[ぴ.noteIndex];んょ.currentNoteIndex=ぴ.noteIndex,""===ぴ.remainingText?(ん.state=んょ.noteState.CLEARED,ん.remainingText="",んょ.inputBuffer="",んょ.currentNoteIndex=null):(ん.state=んょ.noteState.HITTING,ん.remainingText=ぴ.remainingText,んょ.inputBuffer=ぴ.inputBuffer),んょ.roll.forEach(function(ぴ){"note"===ぴ.type&&ぴ.time<ん.time&&(ぴ.state===んょ.noteState.WAITING||ぴ.state===んょ.noteState.HITTING)&&ょぴん(ぴ)}),ぴ.forcedHit&&んょ.hit(ぴ.forcedHit,ょ,!0)};if(1===ぴ.length){if(null!==んょ.currentNoteIndex){var ょん=ぴょ(んょ.currentNoteIndex);if(ょん)return void ょょ(ょん)}var んん=null,ぴぴょ=null,ょぴょ=1/0;んょ.roll.forEach(function(ぴ,ん){if("note"===ぴ.type&&ん>んょ.currentNoteIndex&&ぴ.state===んょ.noteState.WAITING&&Math.abs(ぴ.time-ょ)<Math.abs(ょぴょ)){var ょょ=ぴょ(ん);ょょ&&(んん=ぴ,ぴぴょ=ょょ,ょぴょ=ぴ.time-ょ)}});var んぴょ=ょぴょ;if(null!==んん){var ぴょょ=null;if(んょ.settings.judges.some(function(ぴ){return ぴ.from<=んぴょ&&んぴょ<=ぴ.to?(ぴょょ=ぴ.name,!0):!1}),ん&&null===ぴょょ&&(ぴょょ=んょ.judges[んょ.judges.length-1].name),null!==ぴょょ){if(null!==んょ.currentNoteIndex){var ょょょ=んょ.roll[んょ.currentNoteIndex];ょぴん(ょょょ)}ょょ(ぴぴょ),ぴょょ===んょ.settings.breakCombo&&(んょ.combo=0),んょ.combo++,ぴょん.onJudgement({judgement:{distance:んぴょ,judge:ぴょょ,combo:んょ.combo}})}}}},this.getKanaLyric=function(ぴ){if("undefined"==typeof ぴ&&(ぴ=んょ.currentLyricIndex),null===ぴ)return null;for(var ょ="",ん=ぴ+1;ん<んょ.roll.length;ん++)if("note"===んょ.roll[ん].type)ょ+=んょ.roll[ん].text;else if("stop"===んょ.roll[ん].type||"lyric"===んょ.roll[ん].type)break;return ょ};for(var んぴん in ぴょ)ぴょ.hasOwnProperty(んぴん)&&(void 0===this.settings[んぴん]?this.settings[んぴん]=ぴょ[んぴん]:"number"==typeof this.settings[んぴん]?this.settings[んぴん]=parseFloat(ぴょ[んぴん],10):"string"==typeof this.settings[んぴん]&&(this.settings[んぴん]=ぴょ[んぴん]));this.correction=this.settings.correction+this.settings.controlledCorrection+1e3*this.settings.offset,this.zeroTimePad=this.correction-1e3*this.settings.offset,this.zeroTime=this.correction-1e3*this.settings.offset,this.DOM={wrap:ん.css({width:this.settings.width+"px",height:this.settings.height+"px",margin:"0 auto",position:"relative"}),player:$("<div/>",{id:"youtyping-player"}).appendTo(ん).css({width:this.settings.width+"px",height:this.settings.height+"px",display:"block","z-index":0}),screen:$("<canvas/>",{id:"youtyping-screen","data-paper-keepalive":"true",width:this.settings.width.toString(),height:this.settings.height.toString()}).appendTo(ん).css({width:this.settings.width+"px",height:this.settings.height+"px",position:"absolute",top:0,left:0,"z-index":100})},this.screen=new ょょ(document.getElementById("youtyping-screen"),this);var ぴょん=this.screen;$.when($.when(んょょ(),$.Deferred(this.screen.setup).promise()).done(this.screen.load),ぴんょ(),んん()).done(this.screen.ready).fail(function(){ぴ("ERROR: Initialization Failed...")})},ょょ=function(ょ,ん){var ぴょ=this,ょょ=0;this.canvas=ょ,this.items={},this.setup=function(ょ){paper.setup(ぴょ.canvas),ぴょ.cover=new paper.Path.Rectangle(paper.view.bounds),ぴょ.cover.fillColor="black",ぴょ.cover.fillColor.alpha=.7,ぴょ.debugTexts=[];for(var んょ=0;5>んょ;んょ++){var ぴん=ぴょ.debugTexts.push(new paper.PointText([20,20*(んょ+1)]));ぴょ.debugText=ぴょ.debugTexts[ぴん-1],ぴょ.debugText.justification="left",ぴょ.debugText.fillColor="white"}ぴょ.bufferText=new paper.PointText({point:paper.view.bounds.bottomRight.multiply(ん.settings.bufferTextPosition),content:"",fillColor:"white",justification:"left",fontSize:24}),ぴょ.currentLyric=new paper.PointText({point:paper.view.bounds.bottomRight.multiply(ん.settings.currentLyricPosition),content:"",fillColor:"white",justification:"center",fontSize:36}),ぴょ.nextLyric=new paper.PointText({point:paper.view.bounds.bottomRight.multiply(ん.settings.nextLyricPosition),content:"",fillColor:"white",justification:"center",fontSize:18}),ぴょ.kanaLyric=new paper.PointText({point:paper.view.bounds.bottomRight.multiply(ん.settings.kanaLyricPosition),content:"",fillColor:"white",justification:"center",fontSize:24}),ぴょ.judgeEffects=new paper.Group,setInterval(function(){ぴょ.debugTexts[0].content="FPS: "+ょょ,ょょ=0,ぴょ.debugTexts[2].content="Zerocall FPS: "+ん.zeroCallFPS,ん.zeroCallFPS=0},1e3),ぴ("Screen is Set."),ょ.resolve()},this.load=function(){var ょ=ん.settings,ょょ=ん.now,んょ=ょ.width*(1-ょ.hitPosition)+ょ.noteSize+ょ.screenPadding,ぴん=ょ.width*ょ.hitPosition+ょ.noteSize+ょ.screenPadding;try{ん.roll.forEach(function(ぴ){ぴ.emergeTime=(ょ.speed*ぴ.time-んょ)/ょ.speed,ぴ.vanishTime=(ょ.speed*ぴ.time+ぴん)/ょ.speed}),ぴ("Computed roll Parameters.")}catch(ょん){return ぴ("ERROR: Computing roll Parameters Faild: "+ょん),-1}ん.zeroTime=ょょ,ぴょ.update(),ぴょ.hitCircle=new paper.Path.Circle({center:paper.view.bounds.bottomRight.multiply([ょ.hitPosition,ょ.rollYpos]),radius:ょ.noteSize,strokeWidth:1,strokeColor:"white"})},this.ready=function(){ぴょ.pressEnter=new paper.PointText({point:paper.view.bounds.bottomRight.multiply([.5,.8]),content:"Press enter or click here.",justification:"center",fontSize:45,fillColor:"white"});var ょ=function(ぴ){("keydown"===ぴ.type&&"enter"===ぴ.key||"mousedown"===ぴ.type)&&(ぴょ.pressEnter.remove(),paper.tool.onKeyDown=null,ぴょ.start())};paper.tool.onKeyDown=ょ,ぴょ.pressEnter.onMouseDown=ょ,ぴ("Screen is Ready.")},this.start=function(){ぴ("Starting game."),paper.view.onFrame=ぴょ.onFrame,ん.play();var ょ=function(ぴ){1===ん.player.getPlayerState()&&"keydown"===ぴ.type&&(ぴ.preventDefault(),ん.hit(ぴ.key))};paper.tool.onKeyDown=ょ},this.update=function(){var ぴ=ん.settings,ょ=ぴょ.items,ょょ=ん.now,んょ=ょょ-ん.zeroTime;ん.roll.forEach(function(ぴょ,ょょ){var ぴん=(ぴょ.time-んょ)*ぴ.speed+ぴ.width*ぴ.hitPosition;if(ょょ in ょ){if(んょ<ぴょ.emergeTime||ぴょ.vanishTime<んょ)return ょ[ょょ].remove(),void delete ょ[ょょ]}else{if(!(ぴょ.emergeTime<=んょ&&んょ<=ぴょ.vanishTime))return;ょ[ょょ]=new paper.Group,"longline"===ぴょ.type&&(ょ[ょょ].longLine=ょ[ょょ].addChild(new paper.Path.Line({from:[ぴん,ぴ.rollYpos*ぴ.height-ぴ.longLineHeight/2],to:[ぴん,ぴ.rollYpos*ぴ.height+ぴ.longLineHeight/2],strokeColor:"white",strokeWidth:2}))),"line"===ぴょ.type&&(ょ[ょょ].smallLine=ょ[ょょ].addChild(new paper.Path.Line({from:[ぴん,ぴ.rollYpos*ぴ.height-ぴ.lineHeight/2],to:[ぴん,ぴ.rollYpos*ぴ.height+ぴ.lineHeight/2],strokeColor:"white",strokeWidth:1}))),"note"===ぴょ.type&&(ょ[ょょ].note=ょ[ょょ].addChild(new paper.Path.Circle({center:[ぴん,ぴ.rollYpos*ぴ.height],radius:ぴ.noteSize,strokeWidth:1,strokeColor:"#aaa"})),ょ[ょょ].lyric=ょ[ょょ].addChild(new paper.PointText({point:[ぴん,ぴ.rollYpos*ぴ.height+ぴ.noteSize+50],content:ぴょ.remainingText,fillColor:"white",justification:"center",fontSize:20,fontFamily:"sans-serif"}))),"stop"===ぴょ.type&&(ょ[ょょ].orderStop=ょ[ょょ].addChild(new paper.Path({segments:[[ぴん,ぴ.rollYpos*ぴ.height-ぴ.noteSize-30]],fillColor:"white"})),ょ[ょょ].orderStop.lineBy([10,-10]),ょ[ょょ].orderStop.lineBy([-20,0]),ょ[ょょ].orderStop.closed=!0)}"longline"===ぴょ.type&&(ょ[ょょ].position.x=ぴん),"line"===ぴょ.type&&(ょ[ょょ].position.x=ぴん),"stop"===ぴょ.type&&(ょ[ょょ].position.x=ぴん),"note"===ぴょ.type&&(ょ[ょょ].position.x=ぴん,ぴょ.state===ん.noteState.CLEARED?(ょ[ょょ].note.visible=!1,ょ[ょょ].lyric.visible=!1):(ょ[ょょ].note.style={fillColor:ぴょ.state===ん.noteState.WAITING||ぴょ.state===ん.noteState.HITTING?"red":"#aaa"},ょ[ょょ].note.opacity=ぴょ.state===ん.noteState.FAILED||ぴょ.state===ん.noteState.WAITING?1:.5,ょ[ょょ].lyric.content=ぴょ.remainingText))})},this.onFrame=function(){1===ん.player.getPlayerState()&&ぴょ.update(),ぴょ.debugTexts[1].content="Measured Zero: "+ん.estimatedZero.toFixed(2),ぴょ.debugTexts[3].content="Active Objects: "+paper.project.activeLayer.children.length,ぴょ.debugTexts[4].content="Zero Time: "+ん.zeroTime.toFixed(2),ぴょ.bufferText.content=ん.inputBuffer,ぴょ.currentLyric.content=ん.currentLyricIndex?ん.roll[ん.currentLyricIndex].text:"",ぴょ.nextLyric.content=ん.nextLyricIndex?ん.roll[ん.nextLyricIndex].text:"",ぴょ.judgeEffects.children.forEach(function(ぴ){ぴ.controller.onFrame()}),ょょ++},this.onPlayerStateChange=function(ぴ){ん.DOM.screen.css(ぴ.data===YT.PlayerState.PLAYING?{cursor:"none"}:{cursor:"auto"})},this.onJudgement=function(ぴ){var ょ=new んょ(ぴ.judgement);ょ.item.controller=ょ,ぴょ.judgeEffects.addChild(ょ.item)};var んょ=function(ぴ){var ょ=ん.settings;switch(this.item=new paper.Group,this.judgeColor="",ぴ.judge){case"perfect":this.judgeColor="yellow";break;case"great":this.judgeColor="#2d1";break;case"good":this.judgeColor="#19a";break;case"bad":this.judgeColor="#aaa"}this.judge=this.item.addChild(new paper.PointText({point:ぴょ.hitCircle.position.add([0,-ょ.noteSize-24]),content:ぴ.judge,fillColor:this.judgeColor,justification:"center",fontSize:24,fontFamily:"sans-serif"})),this.combo=this.item.addChild(new paper.PointText({point:ぴょ.hitCircle.position.add([0,-ょ.noteSize]),content:ぴ.combo,fillColor:"white",justification:"center",fontSize:15,fontFamily:"sans-serif"})),this.onFrame=function(){this.item.translate([0,-3]),this.item.opacity-=.02,this.item.opacity<0&&this.item.remove()}}};if("undefined"==typeof window.performance&&(window.performance={}),!window.performance.now){var んょ=Date.now();window.performance.now=function(){return Date.now()-んょ}}var ぴん=function(ぴ,ょ){return ぴ.length<ょ.length?!1:ぴ.substring(0,ょ.length)===ょ};return ぴょ}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment