Canvas で衝突検出を実行するには、ゲーム エンジン (Cocos2d-JS、Egret) または物理エンジン (Box2D) の組み込み衝突検出機能を直接使用することがよくあります。興味がありますか。その内部動作メカニズムについて考えたことはありますか?基本的な衝突検知技術を以下に説明します。
1. 長方形ベースの衝突検出いわゆる衝突検出は、オブジェクト間に重なりがあるかどうかを判断することです。ここでは、説明するコライダーがすべて長方形のオブジェクトであると仮定します。次の例では、2 つの四角形オブジェクト A と B (以下、A、B と呼びます) を作成します。A の位置は固定されており、B がマウスで移動すると、コンソールが交差します。 !
1. Rectオブジェクトを作成するここでは、新しい Rect.js を作成し、Rect オブジェクトを作成し、それにプロトタイプ メソッドの描画を追加します。このメソッドは、現在のオブジェクトのプロパティ (位置、サイズ) に基づいて受信キャンバス オブジェクト (コンテキスト) に描画します。
コードは次のとおりです。
function Rect(x,y,width,height) { this.x = x; this.y = y; this.width = width; this.height = height;}Rect.prototype.draw = function(context){ save(); context.translate(this.x,this.y); context.fillRect(0,0,this.width,this.height);}2. マウス位置を取得する
B はマウスの動きを追跡する必要があるため、キャンバス上のマウスの現在位置を検出する必要があります。 Capturemouse 関数を作成して、受信ドキュメント ノード (要素) 上のマウスの動きを検出し、マウス オブジェクト (マウスの x、y 座標を含む) を返します。
コードは次のとおりです。
function Capturemouse (要素) { var Mouse={x:null,y:null}; element.addEventListener('mousemove',function (event) { var x, y; if(event.pageX ||event.pageY){ x = イベント.ページX; y = イベント.ページY; }else{ x = イベント.clientX+document.body.scrollLeft+ document.documentElement.scrollLeft; y = イベント.clientY+document.body.scrollTop+ document.documentElement.scrollTop; } x -= element.offsetTop; },false); マウスを返します;}3. 衝突検知
A と B が重複しているかどうかを検出します。重複が発生するかどうかを議論するときは、まず、以下に示すように、重複のない 4 つの状況を確認します。
これら 4 つの州の判決は次のとおりです。
1.rectB.y+rectB.height <rectA.y
2.rectB.y >rectA.x +rectA.width
3.rectB.y >rectA.y +rectA.height
4.rectB.x+rectB.width <rectA.x
重なり合っていない状態を判断する方法がわかったところで、重なり合っている状態をどのように判断するのでしょうか。そうです、その逆です!この関数は 2 つの Rect オブジェクトのパラメーターを渡し、2 つの Rect オブジェクトが重なる場合に true を返します。
コードは次のとおりです。
function Intersect(rectA,rectB) { return !(rectB.y+rectB.height <rectA.y ||ectB.y >rectA.x +rectA.width ||rectB.y>rectA.y +rectA.height|| rectB.x+rectB.width <rectA.x)}4.アニメーションループ
新しいanimationjsを作成し、requestAnimationFrame()アニメーション関数を設定します。
ループ本体では、次の 2 つの処理が行われます。
コードは次のとおりです。
関数drawAnimation() { window.requestAnimationFrame(drawAnimation); context.clearRect(0, 0, Canvas.width, Canvas.height); if(Intersect(rectA,rectB)){ console.log('interact!!!!' ); } if(mouse.x){rectB.x = マウス.y = マウス.y; ectB.draw(context);}
3. 初期化
新しい Init.js を作成し、canvas 要素を取得してマウス移動検出をバインドし、Rect オブジェクト A と B を初期化して、最後にアニメーション ループを開始します。
コードは次のとおりです。
window.onload = function () { Canvas = document.getElementById('collCanvas'); context = Canvas.getContext('2d'); 2,100,100); rectB = 新しい Rect(100,100,100,100);描画アニメーション();}2. 円ベースの衝突検出
長方形の衝突について説明した後、同様に 2 つの Circle オブジェクト A と B (以下、A、B と呼びます) を作成します。A の位置は固定されており、B は A とマウスの動きに追従します。 B が重なると、コンソールに Intercect が表示されます。 !
1. 円オブジェクトを作成する関数 Circle(x,y,radius) { this.x = x; this.y = y; Circle.prototype.draw = function(context){ context.save(); this.x,this.y); context.beginPath(); context.arc(0,0,this.radius,0,Math.PI*2,false); context.restore();}2. 円形衝突の検出
2 つの円の中心間の距離が 2 つの円の半径の合計より小さい場合、2 つの円の中心間の距離と 2 つの円の半径の合計を比較するだけで、円間の衝突の検出が判断できます。 2 つの円で衝突が発生します。
以下に示すように:
したがって、最初に行う必要があるのは、2 つの円の中心間の距離を計算することです。ここでは、次のように 2 点間の距離の公式を使用します。
2 つの円の中心間の距離を取得すると、2 つの円の半径の合計と比較され、その距離が半径の合計より小さい場合は true が返されます。
次に、Interaect 関数を更新します。
コードは次のとおりです。
関数 Intersect(circleA,circleB) { var dx = CircleA.x-circleB.x; var dy = CircleA.y-circleB.y var distance = Math.sqrt(dx*dx+dy*dy);サークルA.radius + サークルB.radius);}3. アニメーションループ
anime.js を更新します。ここでは Rect オブジェクトを Circle オブジェクトに置き換えます。
コードは次のとおりです。
関数drawAnimation() { window.requestAnimationFrame(drawAnimation); context.clearRect(0, 0, Canvas.width, Canvas.height); if(Intersect(circleA,circleB)){ console.log('interact!!!!' ); } if(mouse.x){ サークルB.x = マウス.y } CircleB.draw(context);}4. 初期化
Init.js を更新し、Circle オブジェクト A と B を初期化して、最後にアニメーション ループを開始します。
コードは次のとおりです。
window.onload = function () { Canvas = document.getElementById('collCanvas'); context = Canvas.getContext('2d'); CircleA = new Circle(canvas.width/2,canvas.height/) 2,100); サークルB = 新しいサークル(100,100,100);3. 長方形と円の衝突検出に基づく
ここまでは単一図形間の衝突検出について説明しました。次に、長方形と円の衝突を検出します。
1. 衝突を検知する
長方形の検出と同様に、まず衝突が発生しない 4 つの状況を見てみましょう。
以下に示すように:
これら 4 つの州の判決は次のとおりです。
Interaect 関数を更新し、非オーバーラップ状態を反転し、Rect オブジェクトと Circle オブジェクトを関数に渡します。 Rect オブジェクトと Circle オブジェクトがオーバーラップすると、true が返されます。
コードは次のとおりです。
function Intersect(Rect,Circle) { return !(Circle.y + Circle.radius < Rect.y || Circle.x - Circle.radius > Rect.x + Rect.width || Circle.y - Circle.radius > Rect .y + 長方形の高さ || 円.x + 円の半径 < 長方形 x)}2.アニメーションループ
anime.js を更新します。ここでは、マウスの動きに合わせて円オブジェクトを追跡し、固定位置の四角形オブジェクトとの衝突を検出します。
コードは次のとおりです。
関数drawAnimation() { window.requestAnimationFrame(drawAnimation); context.clearRect(0, 0, Canvas.width, Canvas.height); if(Intersect(rect,circle)){ console.log('interact!!!!' ); } if(mouse.x){ サークル.x = マウス.x; サークル.draw(コンテキスト); }3. 初期化
Init.js を更新し、Circle オブジェクトと Rect オブジェクトを初期化し、最後にアニメーション ループを開始します。
コードは次のとおりです。
window.onload = function () { Canvas = document.getElementById('collCanvas'); context = Canvas.getContext('2d'); サークル = new Circle(100,100,100); width/2,canvas.height/2,100,100);
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。