지난 시간 엄청난 기술들을 선보이며 1위 자리를 다시 탈환한 미니 자동차,
https://itadventure.tistory.com/697
우리의 NPC군도 가만 있을순 없다고 하네요. 그러면서 본인의 이름을 밝히는데요..
본 게시글은 바빌론 공식 튜토리얼로 시작했다가 점점 안드로메다로 가는 크레이의 입맛에 맞는 게시글입니다 :)
관심받고 싶은 NPC
미니자동차의 활약에 NPC군, 카메라의 주도권을 본인도 갖고 싶다고 합니다.
하지만 미니 자동차도 그것만은 양보할 수 없다고 하네요. 이것 참 난감합니다.
옆에서 지켜보던 PD, 한가지 아이디어를 제안하는데요.
버튼을 2개 만들어 누를때마다 카메라를 전환하는건 어떠냐고 하네요.
사실 NPC에게 카메라를 붙이는건 간단합니다.
아래 자동차 모델을 불러오는 함수 안에서
BABYLON.SceneLoader.ImportMeshAsync(
"",
"./",
"car.glb").then((result) => {
카메라의 대상이 되는 코드를 삭제하고
camera.lockedTarget = mesh;
캐릭터 모델을 불러오는 쪽으로 옮기면 그만이거든요.
하지만 버튼 2개를 만드려면 UI를 준비해야 합니다.
UI를 먼저 붙이는 부분을 살펴보겠습니다:)
패널과 버튼 추가
제일 먼저 GUI 를 붙이겠습니다. ( 그래픽 유저 인터페이스의 준말입니다 )
아래 코드를 찾아,
var scene = new BABYLON.Scene(engine);
GUI 를 총괄하는 코드를 추가합니다.
이제 advencedTexture 가 모든 GUI의 제어도구가 되는 거지요.
// GUI
const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
그리고 버튼 2개를 추가하면 되는데요.
미리 함수화 코드를 추가하도록 하겠습니다.
아래 코드를 찾아
// 씬 리턴
return scene;
그 위에 ui를 준비할 함수 코드를 추가해 주세요.
GUISystem(camera, advancedTexture);
그리고 UI준비 함수는 그 아랫 부분에 다음 코드를 찾아
// 씬 리턴
return scene;
};
그 아래 함수코드를 추가하면 됩니다.
function GUISystem(camera, advancedTexture)
{
// 패널 UI 추가
const panel = new BABYLON.GUI.StackPanel();
// 가로 중앙 정렬
panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
// 세로 하단 정렬
panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;
// 하단 여백
panel.paddingBottom = 20;
// 패널을 UI 시스템에 붙임
advancedTexture.addControl(panel);
// 버튼1 추가
const button = BABYLON.GUI.Button.CreateSimpleButton("btnpc", "Follow NPC");
button.width = 0.1; // 가로폭 10%
button.height = "40px"; // 세로높이 40픽셀
button.color = "white"; // 글자섹
button.background = "green"; // 배경색
button.cornerRadius = 5; // 버튼 모서리 둥근 정도
panel.addControl(button); // 버튼을 패널에 붙임
// 버튼2 추가
const button2 = BABYLON.GUI.Button.CreateSimpleButton("btnCar", "Follow Car");
button2.width = 0.1; // 0.2 = 20%
button2.height = "40px";
button2.cornerRadius = 5;
button2.color = "white";
button2.background = "blue";
panel.addControl(button2);
}
화면이 이렇게 보이실텐데요.
하단에 버튼 2개가 보이실 겁니다. 아직 눌러도 아무 작동은 안 합니다.
카메라 코드 함수화
이제 카메라 코드를 함수화해서 버튼 누를때마다 전천후로 쓸 수 있도록 하겠습니다.
이렇게 생긴 코드가 있을텐데요.
// 팔로우 카메라
const camera = new BABYLON.FollowCamera(
"FollowCam",
new BABYLON.Vector3(-6, 0, 0),
scene
);
// 대상과의 거리
camera.radius = -1;
// 카메라의 높이
camera.heightOffset = 0.5;
// 카메라 가속도
camera.cameraAcceleration = 0.005
//최대 가속도
camera.maxCameraSpeed = 10
camera.wheelDeltaPercentage = 0.01; // 마우스휠 속도
camera.minZ = 0; // 근거리 커팅 X
// 카메라 캔버스 연결
camera.attachControl(canvas, true);
이와 같이 코드를 변경해 주세요.
// 팔로우 카메라
const camera = new BABYLON.FollowCamera(
"FollowCam",
new BABYLON.Vector3(-6, 0, 0),
scene
);
followCam(camera, null);
그리고 금방 GUISystem 함수를 정의한 아랫 부분에 카메라 함수를 추가합니다.
function followCam(camera, mesh){
if(mesh!=null)camera.lockedTarget = mesh;
// 대상과의 거리
camera.radius = -1;
// 카메라의 높이
camera.heightOffset = 0.5;
// 카메라 가속도
camera.cameraAcceleration = 0.005
//최대 가속도
camera.maxCameraSpeed = 10
camera.wheelDeltaPercentage = 0.01; // 마우스휠 속도
camera.minZ = 0; // 근거리 커팅 X
// 카메라 캔버스 연결
camera.attachControl(canvas, true);
}
아직 기능상의 변화는 없지만 이로써 카메라를 자유롭게 전환할수 있는 기반이 마련되었습니다.
버튼 클릭하여 카메라 전환하기
카메라가 NPC, 차를 따라가게 하려면
NPC, 차 모델 glb 파일을 받아올 때 mesh를 함수 내부가 아닌 외부에 저장해야 합니다.
// 이 상태로를 쓸수 없어...
BABYLON.SceneLoader.ImportMeshAsync(
"",
"./", "character01.glb", scene).then((result) => {
var mesh = result.meshes[0];
아래 코드를 찾아
var createScene = function () {
그 위 변수를 선언합니다. 각각 미니자동차, 캐릭터 메쉬를 저장할 변수입니다.
let mesh_car = null;
let mesh_npc = null;
자동차 모델 불러오는 아래 코드를 찾아
// 자동차 부르기
BABYLON.SceneLoader.ImportMeshAsync(
"",
"./",
"car.glb").then((result) => {
// 로딩 후 실행할 코드
var mesh = result.meshes[0];
아래 코드를 추가합니다.
mesh_car = mesh;
역시 캐릭터 모델을 불러오는 코드를 찾아
BABYLON.SceneLoader.ImportMeshAsync(
"",
"./", "character01.glb", scene).then((result) => {
var mesh = result.meshes[0];
아래 코드를 추가합니다.
mesh_npc = mesh;
자, 거의 다 왔습니다. 마지막으로 버튼을 누르면 카메라를 바꾸는 코드입니다.
GUISystem() 함수 안에서 아래 코드를 찾아,
panel.addControl(button); // 버튼을 패널에 붙임
버튼1 클릭시 작동할 코드를 추가합니다. mesh_npc 를 카메라가 따라가는 코드입니다.
// 버튼 클릭 이벤트
button.onPointerClickObservable.add(() => {
followCam(camera, mesh_npc);
});
버튼2 도 마찬가지로 추가해주죠.
아래 코드를 찾아
panel.addControl(button2);
아래 코드를 추가해 주세요.
button2.onPointerClickObservable.add(() => {
followCam(camera, mesh_car);
});
이것으로 끝입니다.
이제 Follow NPC 버튼을 누르면 카메라가 NPC 를 따라가고
Follow Car 버튼을 누르면 카메라가 미니자동차를 따라갑니다.
내 이름은 케이!
NPC 군이 이걸로 끝낼수 없다고 하네요.
뭔가 특별한 걸 보여줘야 한다며 자신의 이름을 공개한다고 합니다.
GUI 시스템에는 NPC 머리 위에 이름을 뛰우는 기능이 있는데요.
코드가 간단하더라구요.
금방 추가한 mesh_npc 코드를 찾아
mesh_npc = mesh;
그 아래 코드를 추가해 주세요.
// NPC 이름
// 검정 배경
const rect1 = new BABYLON.GUI.Rectangle();
rect1.width = "100px";
rect1.height = "40px";
rect1.cornerRadius = 5;
rect1.color = "White";
rect1.thickness = 0;
rect1.background = "black";
rect1.alpha = 0.5; // 투명도
advancedTexture.addControl(rect1);
// 글자
var label = new BABYLON.GUI.TextBlock();
label.text = "NPC 케이";
rect1.addControl(label);
rect1.linkWithMesh(mesh_npc); // 메시에 붙이기
rect1.linkOffsetY = -50; // 메시 위로 띄우는 간격
그러면 이렇게 NPC 위에 이름 태그가 붙습니다. 한글도 되더라구요.
전체 소스가 궁금하거나 실습이 어려우신 분은 아래 크레이가 준비한 URL을 참조해 주세요.
http://dreamplan7.cafe24.com/babylon/ex15/
마무~리
미니자동차와 NPC의 불꽃튀는 신경전, 다음에는 또 어떤 이야기가 기다리고 있을까요?
필요하신 분에게 도움이 되시길 바랍니다 :)
오늘도 방문해주신 모든 분들께 감사드립니다.
다음 게시글 : https://itadventure.tistory.com/699
'자바스크립트와 캔버스' 카테고리의 다른 글
바빌론JS - 비를 피하고 싶어! (0) | 2024.07.29 |
---|---|
바빌론JS - 내 진짜 정체를 알려주지. (0) | 2024.07.26 |
바빌론JS - 미니자동차의 마을 탐방 (3) | 2024.07.22 |
바빌론JS - 경로 우대? 경로 따라 걷는 NPC (2) | 2024.07.21 |
바빌론JS - 이동하는 NPC (4) | 2024.07.21 |