2016-12-22 3 views
9

私は、あるモルのゲームにhtmlのヒットを作成しようとしていました。あるモルのゲームに一定の間隔でクラスが追加され、別のタイムアウト関数がトリガーされ、チェックが実行される前にモルをクリックしてクラスを削除し、モルにまだクラスが添付されているかどうかを判断します。Javascript settimeouts on html hack a moleゲーム

ここは私のゲームのjsfiddleです:https://jsfiddle.net/gko9puqf/1/以下は私のjavascriptです。タイムアウトが(40のスコアを中心に)大幅に短くなるまで予想され、タイムアウトが無視されたかのようにモルが出てグリッチとして

var score = 0; 
var numberofpipes = 9; 
var lastnum = 0; 
var intervalseconds; 
var interval; 
var haslost = false; 
var checkpipetimer; 
var timeoutfunc; 
var timeoutinit; 
var timers = []; 
var burstingpipes = {}; 
var timeoutinit = setTimeout(startaburst, 3000); 
$('#scorecontainer').text(score); 
//starts a bursting pipe 
function startaburst() { 
    clearTimeout(timeoutinit); 
    if (score < 10) { 
    intervalseconds = 2; 
    } else if (score >= 10 && score < 25) { 
    intervalseconds = 1.5; 
    } else if (score >= 25 && score < 40) { 
    intervalseconds = 1; 
    } else if (score >= 40 && score < 60) { 
    intervalseconds = 0.5; 
    } else if (score >= 60) { 
    intervalseconds = 0.25; 
    } else if (score > 100) { 
    intervalseconds = 0.1; 
    } 
    interval = intervalseconds * 1000; 
    burstingpipe(); 
    //creating a loop with the new timeout value as the game gets harder. 
    //also assigning it to the timeoutfunc variable so i can cancel the loop later. 
    timeoutfunc = setTimeout(startaburst, interval); 
} 

//adds the bursting pipe attributes to the pipe intersections 
function burstingpipe() { 
    randomnum = Math.floor(Math.random() * 9) + 1; 
    //cant be the same twice in case of overlapping 
    if ((randomnum == lastnum) || $("." + randomnum).hasClass("burstingpipe")) { 
    //if the random num is still valid after -1, -1 
    if (((randomnum - 1) >= 0) && !($("." + (randomnum - 1)).hasClass("burstingpipe"))) { 
     randomnum = (randomnum - 1); 
     //add one to the random number 
    } else if (((randomnum + 1) <= (numberofpipes)) && !($("." + (randomnum + 1)).hasClass("burstingpipe"))) { 
     randomnum = (randomnum + 1); 
    } else { 
     burstingpipe(); 
    } 
    } 
    //make the lastnum the current number so we dont get 2 in a row 
    lastnum = randomnum; 
    randomdiv = $("." + randomnum); 
    console.log(randomdiv.hasClass("burstingpipe")); 
    //adds shake animation and red glow 
    console.log(randomnum); 
    randomdiv.addClass("burstingpipe"); 

    //setting a timeout of 3 seconds, so th user has 3 seconds to press each 
    //bursting pipe before it bursts. 
    checkpipetimer = setTimeout(haspipeburst.bind(this, randomdiv), 3000); 
} 

//function to check if the pipe has burst. 
function haspipeburst(pipecheck) { 
    console.log(pipecheck); 
    console.log(pipecheck.hasClass("burstingpipe")); 
    //checking to see if the pipe still has the class attached after 3 seconds 
    //and if the user has already lost. 
    if (pipecheck.hasClass("burstingpipe")) { 
    //if the pipe still has the class attached - game over. 
    haslost = true; 
    $("#result").text("you have lost"); 
    //stopping the loop. 
    clearTimeout(timeoutfunc); 
    //changing the background color to make it look like the pipe has broken. 
    //(will possibly change to image in future) 
    //$(".hitpoint").removeClass("burstingpipe"); 
    $(pipecheck).css("background-color", "#49c1e2"); 
    } 
} 

//when the user clicks a hitpoint the class is removed and they gain a point. 
$(document).on('click', '.hitpoint', function() { 
    if ($(this).hasClass("burstingpipe") && haslost == false) { 
    $(this).removeClass("burstingpipe"); 
    score++; 
    $("#scorecontainer").text(score); 
    } 
}); 

は、それが動作します。

私は今何時間もコードを注視しており、少し進歩したので、私があなたを助けてくれることを願っています!私はタイムアウトが適切に完了していないことと関係していると信じています。

ご協力いただきありがとうございます。

+2

'settimeout'あなたはそれがバグだらけ – Mairaj

+0

そうだろう使用してきた道をバギーされていない申し訳ありませんが、これは、スタックオーバーフローの私の最初の投稿です合意された、私は意味ですか私がそれらを使用している方法は、明らかにどこかに欠陥があります。 –

答えて

4

ビットが、これでは、間に他のタスクに少し働いていました。前述のように、複数のタイマーを起動する際の問題は、最後のタイマーだけでなく、特定のタイマーを覚えておく必要があることです。以下のコードでは、独自のタイマーを使用して単一のクラス(関数)内に '破裂パイプ'を保持することによって行われます。

おそらく私は少し船外に行ったかもしれませんが、ほかの人からも言われたように、あなたが作ったゲームが気に入っています:)変更の1つは、破裂しないパイプを得るためにすべてのパイプをループするのではなく、一度それが爆発するパイプ。これによりdivの番号を付ける必要もなくなります。コードコメントの詳細。もちろん、あなたはこのコードを完全に無視することは自由ですが、私はそれが完了してから、とにかく投稿しています。

Fiddle

var score = 24; //set higher for testing purposes 
 
var pipes = $('.hitpoint').toArray() , 
 
\t last = null, 
 
    haslost = false, 
 
\t interval = 2, //start interval 
 
\t thresholds = {10: 1.5, 25: 1 , 40: 0.5, 60:0.25, 100 :1}; //interval thresholds 
 
setTimeout(startaburst, 3000); //intial timeout (doesn't need to be cleared, because it's fired once) 
 

 
$('#scorecontainer').text(score); 
 
//starts a bursting pipe 
 
function startaburst() { 
 
\t if(haslost)return; //already lost 
 
    
 
    if(pipes.length>0){ //pick a pipe to burst unless all pipes allready bursting 
 
    var i; 
 
    while(true){ 
 
     var p = pipes[i = Math.floor(Math.random() * pipes.length)]; //get random element from the available pipes 
 
     if(p!==last || pipes.length === 1)break; 
 
    } 
 
    pipes.splice(i,1); //remove pipe from available pipes 
 
    last = p; //remember last to prevent reusing the same pipe twice 
 
    new burstingPipe(p); 
 
\t } 
 
    
 
    setTimeout(startaburst, interval * 1000); //wait until staring the new burst. interval is increased inside backInGame if the score increases 
 
} 
 

 
function burstingPipe(pipe){ 
 
\t this.pipe = $(pipe); 
 
    this.pipe.addClass("burstingpipe"); 
 
    
 
    function checkBurst(){ 
 
    \t this.dispose(); 
 
    \t if(haslost)return; //already lost on other pipe 
 
    haslost = true; 
 
    $("#result").text("you have lost"); 
 
    //changing the background color to make it look like the pipe has broken. 
 
    //(will possibly change to image in future)  \t \t 
 
    this.pipe.css("background-color", "#49c1e2"); 
 
    }; 
 
    
 
    this.dispose=function(){ 
 
    \t this.pipe.off('click'); //unbind click (no longer bursting or already burst) 
 
    \t this.pipe.removeClass("burstingpipe");  
 
    } 
 
    
 
    function backInGame(){ \t 
 
    \t clearTimeout(this.timer); //clear the burst timeout (specific for this pipe) 
 
    this.dispose(); 
 
    pipes.push(this.pipe[0]); //make pipe available again (NB, because the array contains of DOM elements and not jquery objects, [0] is needed) 
 
    var int = thresholds[++score]; //increase the score and check if interval should be increased for the new score 
 
    if(int && int < interval){ 
 
    \t //optional: some message or css that interval is increased 
 
    \t interval =int; 
 
    } 
 
    $("#scorecontainer").text(score); 
 
    } 
 
    
 
    this.pipe.click(backInGame.bind(this)); //bind the click 
 
    this.timer =setTimeout(checkBurst.bind(this), 3000); 
 
}
@keyframes shake { 
 
    5%, 
 
    15%, 
 
    25%, 
 
    35%, 
 
    45%, 
 
    55%, 
 
    65%, 
 
    75%, 
 
    85%, 
 
    95% { 
 
    left: 0; 
 
    right: 1vh; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
    10%, 
 
    20%, 
 
    30%, 
 
    40%, 
 
    50%, 
 
    60%, 
 
    70%, 
 
    80%, 
 
    90%, 
 
    100% { 
 
    left: 1vh; 
 
    right: 0; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
} 
 

 
@-webkit-keyframes shake { 
 
    5%, 
 
    15%, 
 
    25%, 
 
    35%, 
 
    45%, 
 
    55%, 
 
    65%, 
 
    75%, 
 
    85%, 
 
    95% { 
 
    left: 0; 
 
    right: 1vh; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
    10%, 
 
    20%, 
 
    30%, 
 
    40%, 
 
    50%, 
 
    60%, 
 
    70%, 
 
    80%, 
 
    90%, 
 
    100% { 
 
    left: 1vh; 
 
    right: 0; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
} 
 

 
@-moz-keyframes shake { 
 
    5%, 
 
    15%, 
 
    25%, 
 
    35%, 
 
    45%, 
 
    55%, 
 
    65%, 
 
    75%, 
 
    85%, 
 
    95% { 
 
    left: 0; 
 
    right: 1vh; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
    10%, 
 
    20%, 
 
    30%, 
 
    40%, 
 
    50%, 
 
    60%, 
 
    70%, 
 
    80%, 
 
    90%, 
 
    100% { 
 
    left: 1vh; 
 
    right: 0; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
} 
 

 
@-o-keyframes shake { 
 
    5%, 
 
    15%, 
 
    25%, 
 
    35%, 
 
    45%, 
 
    55%, 
 
    65%, 
 
    75%, 
 
    85%, 
 
    95% { 
 
    left: 0; 
 
    right: 1vh; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
    10%, 
 
    20%, 
 
    30%, 
 
    40%, 
 
    50%, 
 
    60%, 
 
    70%, 
 
    80%, 
 
    90%, 
 
    100% { 
 
    left: 1vh; 
 
    right: 0; 
 
    outline: none; 
 
    border-color: red; 
 
    box-shadow: 0 0 10px red; 
 
    } 
 
} 
 

 
html { 
 
    height: 100%; 
 
    width: 100%; 
 
} 
 

 
* { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 

 
body { 
 
    height: 100%; 
 
    width: 100%; 
 
} 
 

 
#gamecontainer { 
 
    height: 100%; 
 
    width: 100%; 
 
    background-color: #49c1e2; 
 
} 
 

 
#gameinformation { 
 
    height: 10%; 
 
    display: flex; 
 
    flex-direction: row; 
 
    align-items: center; 
 
    padding-left: 10%; 
 
} 
 

 
#pipecontainer { 
 
    height: 80%; 
 
    width: 100%; 
 
    display: flex; 
 
    flex-direction: column; 
 
    justify-content: space-around; 
 
} 
 

 
.pipe { 
 
    height: 8vh; 
 
    width: 100vw; 
 
    background-color: #a5a5a5; 
 
    display: flex; 
 
    flex-direction: row; 
 
    justify-content: space-around; 
 
} 
 

 
.hitpoint { 
 
    height: 10vh; 
 
    width: 10vh; 
 
    background-color: #6d6d6d; 
 
    border-radius: 2vh; 
 
    position: relative; 
 
    bottom: 1vh; 
 
    cursor: pointer; 
 
} 
 

 
#scoretext { 
 
    color: #fff; 
 
    font-size: 6vh; 
 
} 
 

 
#scorecontainer { 
 
    color: #fff; 
 
    font-size: 6vh; 
 
} 
 

 
#statusupdate { 
 
    color: #fff; 
 
    font-size: 6vh; 
 
} 
 

 
.burstingpipe { 
 
    animation-name: shake; 
 
    animation-duration: 3s; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="gamecontainer"> 
 
    <div id="gameinformation"> 
 
    <p id="scoretext">Score:&nbsp;</p> 
 
    <div id="scorecontainer"> 
 
    </div> 
 
    </div> 
 
    <div id="pipecontainer"> 
 
    <div class="pipe"> 
 
     <div class="hitpoint"></div> 
 
     <div class="hitpoint"></div> 
 
     <div class="hitpoint"></div> 
 
    </div> 
 
    <div class="pipe"> 
 
     <div class="hitpoint"></div> 
 
     <div class="hitpoint"></div> 
 
     <div class="hitpoint"></div> 
 
    </div> 
 
    <div class="pipe"> 
 
     <div class="hitpoint"></div> 
 
     <div class="hitpoint"></div> 
 
     <div class="hitpoint"></div> 
 
    </div> 
 
    </div> 
 
    <div id="statusupdate"> 
 
    <p id="result"></p> 
 
    </div> 
 
</div>

+0

こんにちは、私の問題の解決策を見つけるのに時間をかけてくれてありがとう!私は、個々のパイプにユニークなタイムアウトを与えるための別の解決策を見つけました。これは、タイムアウトを動的変数(2つの変数を使用して作成)に保存することでした。このようにして、パイプがクリックされたときに個々のタイムアウトをクリアすることができました。あなたがそれをやったやり方は、はるかにきれいに見えるし、コードを少なくするので、私は私のソリューションをリファクタリングする必要があるかもしれません! 私はあなたが私のゲームを楽しんでうれしく思います:)もう一度解決策を提供する時間をとっていただきありがとうございます。 –

3

私は

:)あなたのゲームが好きで、ここにあなたの問題がある:とき、スコアの増加、あなたは、同時に複数の振盪ゾーンを持つようにタイムアウト間隔を減少しています。ユーザーが緩んでいる場合は、すべてのタイマーを停止するには、次の行を使用しています。

timeoutfunc = setTimeout(startaburst、interval);

、次いで

てclearTimeout(timeoutfunc)。

timeoutfuncのみすべての立ち上げタイムアウト(チェックが各3秒に行われている間、揺れタイムアウトが複数回実行されます、覚えておいてください)最後に起動タイムアウトが含まれておりませんので、これは動作しません。したがって、すべての間隔を保ち、すべての間隔をクリアするための配列が必要です。

私はあなたのフィドルを更新(また、いくつかの不要な行を削除)後半追加の

var score = 0; 
var numberofpipes = 9; 
var lastnum = 0; 
var intervalseconds; 
var interval; 
var haslost = false; 
var checkpipetimer; 
var timeoutfunc = []; 
var timers = []; 
var burstingpipes = {}; 
setTimeout(startaburst, 3000); 
$('#scorecontainer').text(score); 
//starts a bursting pipe 
function startaburst() { 
    if (score < 10) { 
    intervalseconds = 2; 
    } else if (score >= 10 && score < 25) { 
    intervalseconds = 1.5; 
    } else if (score >= 25 && score < 40) { 
    intervalseconds = 1; 
    } else if (score >= 40 && score < 60) { 
    intervalseconds = 0.5; 
    } else if (score >= 60) { 
    intervalseconds = 0.25; 
    } else if (score > 100) { 
    intervalseconds = 0.1; 
    } 
    interval = intervalseconds * 1000; 
    burstingpipe(); 
    //creating a loop with the new timeout value as the game gets harder. 
    //also assigning it to the timeoutfunc variable so i can cancel the loop later. 

    timeoutfunc.push(setTimeout(startaburst, interval)); 
} 

//adds the bursting pipe attributes to the pipe intersections 
function burstingpipe() { 
    randomnum = Math.floor(Math.random() * 9) + 1; 
    //cant be the same twice in case of overlapping 
    if ((randomnum == lastnum) || $("." + randomnum).hasClass("burstingpipe")) { 
    //if the random num is still valid after -1, -1 
    if (((randomnum - 1) >= 0) && !($("." + (randomnum - 1)).hasClass("burstingpipe"))) { 
     randomnum = (randomnum - 1); 
     //add one to the random number 
    } else if (((randomnum + 1) <= (numberofpipes)) && !($("." + (randomnum + 1)).hasClass("burstingpipe"))) { 
     randomnum = (randomnum + 1); 
    } else { 
     burstingpipe(); 
    } 
    } 
    //make the lastnum the current number so we dont get 2 in a row 
    lastnum = randomnum; 
    randomdiv = $("." + randomnum); 
    console.log(randomdiv.hasClass("burstingpipe")); 
    //adds shake animation and red glow 
    console.log(randomnum); 
    randomdiv.addClass("burstingpipe"); 

    //setting a timeout of 3 seconds, so th user has 3 seconds to press each 
    //bursting pipe before it bursts. 
    checkpipetimer = setTimeout(haspipeburst.bind(this, randomdiv), 3000); 
} 

//function to check if the pipe has burst. 
function haspipeburst(pipecheck) { 
    console.log(pipecheck); 
    console.log(pipecheck.hasClass("burstingpipe")); 
    //checking to see if the pipe still has the class attached after 3 seconds 
    //and if the user has already lost. 
    if (pipecheck.hasClass("burstingpipe")) { 
    //if the pipe still has the class attached - game over. 
    haslost = true; 
    $("#result").text("you have lost"); 
    //stopping the loop. 
    for (var i = timeoutfunc.length - 1; i >= 0; i--) { 
     clearTimeout(timeoutfunc[i]); 
    } 
    //changing the background color to make it look like the pipe has broken. 
    //(will possibly change to image in future) 
    //$(".hitpoint").removeClass("burstingpipe"); 
    $(pipecheck).css("background-color", "#49c1e2"); 
    } 
} 

//when the user clicks a hitpoint the class is removed and they gain a point. 
$(document).on('click', '.hitpoint', function() { 
    if ($(this).hasClass("burstingpipe") && haslost == false) { 
    $(this).removeClass("burstingpipe"); 
    score++; 
    $("#scorecontainer").text(score); 
    } 
}); 
+0

こんにちは、見ていただきありがとうございます!バーストパイプ関数の2回目のタイムアウト関数も配列として格納する必要があるため、問題は解決されません。 –

+0

は、タイマーの2番目のロットを配列に追加するように見えますが、それを修正しました!ご協力ありがとうございました !!!!! –

+0

あなたの歓迎です:) –

関連する問題