どうもです、タドスケです。
【Three.js】ベクトルの内積を表示するアニメーション | しぬまでワクワクしていたい
どうもです、タドスケです。 こちらの記事で、Three.js を使ってブログ記事上で軽量な 3D コンテンツを扱えることを知りました。 前回は行列計算をやったので、今回はベク…
Three.js を使ったサンプル作りが楽しい今日この頃。
今回は矩形(四角)同士の当たり判定を実装してみました。
- マウスカーソルに合わせて矩形Aが移動します
- 矩形Bに当たると、矩形Aの色が緑色に変わります
- 矩形A, B の上端(Top)、左端(Left)、下端(Bottom)、右端(Right)の値が表示されます
コードは以下です。
(ChatGPT を利用しています)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>矩形の当たり判定</title>
<style>
body { margin: 0; }
canvas { display: block; }
#info { position: absolute; top: 10px; left: 10px; color: white; }
table { border-collapse: collapse; }
th, td { border: 1px solid white; padding: 5px; }
</style>
</head>
<body>
<div id="info">
<table>
<tr>
<th>矩形</th>
<th>Top</th>
<th>Bottom</th>
<th>Left</th>
<th>Right</th>
</tr>
<tr>
<td>A</td>
<td id="aTop"></td>
<td id="aBottom"></td>
<td id="aLeft"></td>
<td id="aRight"></td>
</tr>
<tr>
<td>B</td>
<td id="bTop"></td>
<td id="bBottom"></td>
<td id="bLeft"></td>
<td id="bRight"></td>
</tr>
</table>
</div>
<script src="https://threejs.org/build/three.js"></script>
<script>
// Three.js の設定
let scene = new THREE.Scene();
let camera = new THREE.OrthographicCamera(window.innerWidth / -2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / -2, 1, 1000);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 矩形AとBの作成
let geometryA = new THREE.PlaneGeometry(100, 100);
let geometryB = new THREE.PlaneGeometry(100, 100);
let materialA = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.5 });
let materialB = new THREE.MeshBasicMaterial({ color: 0x0000ff, transparent: true, opacity: 0.5 });
let rectangleA = new THREE.Mesh(geometryA, materialA);
let rectangleB = new THREE.Mesh(geometryB, materialB);
scene.add(rectangleA);
scene.add(rectangleB);
// 矩形Bの位置設定
rectangleB.position.set(0, 0, 0);
camera.position.z = 500;
// マウス移動イベント(矩形A用)
document.addEventListener('mousemove', (event) => {
let rect = renderer.domElement.getBoundingClientRect();
let mouseX = event.clientX - rect.left - window.innerWidth / 2;
let mouseY = - (event.clientY - rect.top - window.innerHeight / 2);
rectangleA.position.set(mouseX, mouseY, 0);
updateInfo();
});
// 衝突検出
function checkCollision() {
let boundsA = new THREE.Box3().setFromObject(rectangleA);
let boundsB = new THREE.Box3().setFromObject(rectangleB);
if (boundsA.intersectsBox(boundsB)) {
materialA.color.set(0x00ff00);
} else {
materialA.color.set(0xff0000);
}
}
// 位置情報の更新
function updateInfo() {
let boundsA = new THREE.Box3().setFromObject(rectangleA);
let boundsB = new THREE.Box3().setFromObject(rectangleB);
document.getElementById("aTop").innerText = boundsA.max.y.toFixed(2);
document.getElementById("aLeft").innerText = boundsA.min.x.toFixed(2);
document.getElementById("aBottom").innerText = boundsA.min.y.toFixed(2);
document.getElementById("aRight").innerText = boundsA.max.x.toFixed(2);
document.getElementById("bTop").innerText = boundsB.max.y.toFixed(2);
document.getElementById("bLeft").innerText = boundsB.min.x.toFixed(2);
document.getElementById("bBottom").innerText = boundsB.min.y.toFixed(2);
document.getElementById("bRight").innerText = boundsB.max.x.toFixed(2);
}
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
checkCollision();
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
コード内では intersectsBox という関数一つでやってしまっていますが、内部では
- Aの右端が Bの左端よりも右にある(大きい)
- Aの左端が Bの右端よりも左にある(小さい)
- Aの下端が Bの上端よりも下にある(小さい)
- Aの上端が Bの下端よりも上にある(大きい)
というような判定を行っています。
(2D と 3D でやり方は違いますが、基本的な考えは同じです)
以上、矩形同士の当たり判定のサンプルでした。
コメント
コメント一覧 (1件)
[…] 【Three.js】矩形同士の当たり判定 | しぬまでワクワクしていたい どうもです、タドスケです。 Three.js […]