2012-04-04 7 views
0

クリックするたびにバウンスボックスを生成するHTML5キャンバスがあります。ボックス配列は、作成された各ボックスのx値、y値、x速度、およびy速度を格納します。ボックスは最初はランダムな方向に移動し、キャンバスの辺をバウンスしますが、コーナーに当たった場合、バウンスする代わりにボックスが消えます。編集:soundYとsoundX関数が問題を引き起こしていたことに気づいた私自身の質問に答えました。HTML5キャンバスのバウンスチェック機能がコーナーで失敗する

var box = new Array(); 
var width = window.innerWidth; 
var height = window.innerHeight; 
var field = document.getElementById('canvas'); 

field.width = width; 
field.height = height; 
field.ctx = field.getContext('2d'); 
field.ctx.strokeStyle = 'rgba(255,255,255,1)'; 
setInterval('redraw()', 200); 
addEventListener('click', createBox, false); 

function createBox(e) { // this box will always fail collision detection at the upper-left corner 
    box.push(100); // x-value is normally mouse position 
    box.push(100); // y-value is normally mouse position 
    box.push(-5); // x-speed is normally random 
    box.push(-5); // y-speed is normally random 
} 

function redraw() { 
    field.ctx.clearRect(0,0,width,height); 

    for(var i = 0; i < box.length; i+=4) { 
     if(box[i] < 0)  { box[i+2] *= -1; soundY(box[i+1]); } // parameter of soundY is less than 0 
    else if(box[i] > width) { box[i+2] *= -1; soundY(box[i+1]); } // which is invalid and causes this to break 

     if(box[i+1] < 0)  { box[i+3] *= -1; soundX(box[i]); } 
    else if(box[i+1] > height) { box[i+3] *= -1; soundX(box[i]); } 

    box[i] += box[i+2]; 
    box[i+1] += box[i+3]; 
    field.ctx.strokeRect(box[i], box[i+1], 4, 4); 
    } 
} 

function soundX(num) { 
    // play a sound file based on a number between 0 and width 
} 

function soundY(num) { 
    // play a sound file based on a number between 0 and height 
} 
+0

これに対応するHTMLはありますか? – joeschmidt45

答えて

0

これは、問題とは無関係であると仮定して追加したコード(編集を参照)ですが、コードを削除すると、このユースケースのように問題が解決され、コードのこの部分に無効な入力が発生します。

1

I、問題を再現できた唯一の方法は、右のxとyの速度でボックスが最初にキャンバスの境界の外側に作成されたように、コーナーの一つにボックスを生成することでした。それが起こると、ベロシティの逆転はアイテムを境界に戻すのに十分ではないので、次のフレームではベロシティが再び反転されます(など)。

私はこれがあなたの問題を解決するかもしれないと思う:

 var boxes = []; 
     var boxSize = 4; 
     var width = window.innerWidth; 
     var height = window.innerHeight; 
     var field = document.getElementById('canvas'); 

     function redraw() { 
      field.ctx.clearRect(0, 0, width, height); 
      var box; 
      for (var i = 0; i < boxes.length; i++) { 

       box = boxes[i]; 
       field.ctx.strokeRect(box.x, box.y, boxSize, boxSize); 

       if (box.x < 0) { 
        box.x = 0; 
        box.dx *= -1; 
       } else if (box.x > width - boxSize) { 
        box.x = width - boxSize; 
        box.dx *= -1; 
       } 

       if (box.y < 0) { 
        box.y = 0; 
        box.dy *= -1; 
       } else if (box.y > height - boxSize) { 
        box.y = height - boxSize; 
        box.dy *= -1; 
       } 

       box.x += box.dx; 
       box.y += box.dy; 
      } 
     } 

     field.width = width; 
     field.height = height; 
     field.ctx = field.getContext('2d'); 
     field.ctx.strokeStyle = 'rgba(0,0,0,1)'; 

     setInterval(redraw, 200); 
     addEventListener('click', createBox, false); 

     function createBox(e) { 
      boxes.push({ 
       x: e.clientX - 10, 
       y: e.clientY - 10, // arbitrary offset to place the new box under the mouse 
       dx: Math.floor(Math.random() * 8 - boxSize), 
       dy: Math.floor(Math.random() * 8 - boxSize) 
      }); 
     } 

私はあなたのコード内のいくつかのエラーを修正して(私は願って)それは少し読みやすくするためにいくつかの変更を加えました。最も重要なのは、あなたの衝突検出を拡張して、速度が外に出てもキャンバスの境界にボックスの座標をリセットするようにしました。

jsfiddleが作成されました。これ以上の説明が必要な場合は便利です。

+0

私は、衝突後に座標をリセットすることが役立つことに同意します。私はなぜそれが必要であるかわかりません。速度が一定であるため、座標がしきい値を超えて1ステップバックアップされ、逆になった場合、両方の座標に影響がある場合にのみ失敗するのはなぜですか? – kanoko

+0

setInterval呼び出しの最初の(関数)パラメータを変更しました。これは、文字列でそれを参照するとjsfiddleでエラーが発生していたためですが、それ以外はテストコードです[http://jsfiddle.net/nhyQH/2/] (私が言ったように、私はこのような問題を再現することはできませんでした)。この問題には関係しませんが、あなたの箱のデータを配列に格納する方法を見てください。オブジェクトを使用して各ボックスを表現すると、読みやすく保守性が向上します。 –

+0

私はそれが問題を引き起こしていた実際に他のコードであることを発見しました(上記参照)。私は、xが範囲外であったときにy値に基づいてサウンドを再生していました。私はxまたはyの無効な値にアクセスしている場合、境界のチェックと更新コードが壊れる可能性があります。あなたの提案は役に立ちました。 – kanoko