2022. 2. 23. 19:22ㆍTechnology[Front]
저번 게시글에 이어 이번 게시글에서는 캐릭터에 물질을 부여하여 바닥과 벽의 물질과 충돌되게 만들어서 물리충돌을 구현하는 방법에 대해 알아보겠습니다.
(1) test.js
let objectShape;
let objectBody;
let controlObject;
objectShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
objectBody = new CANNON.Body({
mass : 0.1,
position : new CANNON.Vec3(0, 1, 0),
shape : objectShape,
material: plasticMaterial,
});
world.addBody(objectBody);
Update(timeInSeconds) {
if (this._input._keys.forward) {
objectBody.velocity.x = this._camera.getWorldDirection(cameraDirection).x*speed;
objectBody.velocity.z = this._camera.getWorldDirection(cameraDirection).z*speed;
objectBody.position.x += objectBody.velocity.x;
objectBody.position.z += objectBody.velocity.z;
}
if (this._input._keys.backward) {
let vector = new THREE.Vector3(this._camera.getWorldDirection(cameraDirection).x, this._camera.getWorldDirection(cameraDirection).y, this._camera.getWorldDirection(cameraDirection).z);
let axis = new THREE.Vector3(0, 1, 0);
let angle = Math.PI;
vector.applyAxisAngle(axis, angle);
objectBody.velocity.x = vector.x*speed;
objectBody.velocity.z = vector.z*speed;
objectBody.position.x += objectBody.velocity.x;
objectBody.position.z += objectBody.velocity.z;
controlObject.rotateY(-Math.PI);
}
if (this._input._keys.left) {
let vector = new THREE.Vector3(this._camera.getWorldDirection(cameraDirection).x, this._camera.getWorldDirection(cameraDirection).y, this._camera.getWorldDirection(cameraDirection).z);
let axis = new THREE.Vector3(0, 1, 0);
let angle = Math.PI / 2;
vector.applyAxisAngle(axis, angle);
objectBody.velocity.x = vector.x*speed;
objectBody.velocity.z = vector.z*speed;
objectBody.position.x += objectBody.velocity.x;
objectBody.position.z += objectBody.velocity.z;
controlObject.rotateY(Math.PI/2);
}
if (this._input._keys.right) {
let vector = new THREE.Vector3(this._camera.getWorldDirection(cameraDirection).x, this._camera.getWorldDirection(cameraDirection).y, this._camera.getWorldDirection(cameraDirection).z);
let axis = new THREE.Vector3(0, 1, 0);
let angle = -Math.PI / 2;
vector.applyAxisAngle(axis, angle);
objectBody.velocity.x = vector.x*speed;
objectBody.velocity.z = vector.z*speed;
objectBody.position.x += objectBody.velocity.x;
objectBody.position.z += objectBody.velocity.z;
controlObject.rotateY(-Math.PI/2);
}
controlObject.position.x = objectBody.position.x;
controlObject.position.y = objectBody.position.y - 1;
controlObject.position.z = objectBody.position.z;
};
위의 코드는 실제 프로젝트에서 일부 발췌한 것으로 실제 사용시 일부 수정해서 사용하시면 됩니다. Three.js에서의 scene에 추가되어있는 캐릭터 controlObject를 Cannon.js에서의 world에도 추가하기 위해 Box형태의 객체 objectShape를 정의하고 Cannon의 Body에서 mass를 0.1로 정의해서 물리충돌이 발생했을 때 밀려날 수 있도록 질량을 0보다 크게 설정했고 물질은 plasticMaterial로 설정해서 앞선 게시글에서 물리충돌을 정의했을 때 concreteMaterial과 plasticMaterial이 만났을 때 충돌이 일어나도록 설정했고 바닥과 벽을 concreteMaterial로 설정했기 때문에 캐릭터는 plasticMaterial로 설정해서 둘이 만났을 때 충돌이 일어나도록 구현했습니다. 이후 world에 addBody를 이용해 추가하고나서 계속 업데이트되는 Update 메서드에 WASD로 사용자가 캐릭터를 움직이려고 시도 시 objectBody의 velocity를 이용해 속도를 부여하고 position으로 최종적으로 움직일 위치를 정한 뒤 해당 위치로 움직이게 하고 만약 뒤나 왼쪽, 오른쪽으로 이동 시 캐릭터의 방향을 조정해야하기 때문에 이를 위해 angle 변수를 이용하여 controlObject를 rotateY를 이용해 회전시키고 있습니다. objectBody를 이동시킨 후 controlObject의 위치 x,y,z 좌표를 objectBody의 위치를 따라가게 만들어서 만약 objectBody의 위치변동 시 바닥이나 벽과 충돌되면 밀려나고 이 위치를 controlObject가 따라가기 때문에 결국 벽을 뚫지 못하게 구현할 수 있습니다.
이번 게시글에서는 캐릭터를 Cannon.js의 world에 Box 형태로 add해서 바닥 및 벽과 물리충돌을 구현하고 이로써 캐릭터가 바닥 및 벽을 뚫지 못하게 구현하는 방법에 대해서 알아보았습니다.
'Technology[Front]' 카테고리의 다른 글
3D맵 구현하기 - light 제어하기 (1) | 2022.02.28 |
---|---|
3D맵 구현하기 - 유리재질 벽 구현하기 (1) | 2022.02.25 |
3D맵 구현하기 - cannon.js로 물리엔진 구현하기(1) (1) | 2022.02.22 |
3D맵 구현하기 - 캐릭터가 움직일 때 fbx 파일로 움직임 구현하기 (1) | 2022.02.21 |
3D맵 구현하기 - 3인칭 카메라 구현하기(카메라 조종, 캐릭터가 카메라를 따라서 이동, 카메라가 보는 방향을 캐릭터가 응시) (1) | 2022.02.20 |