본문 바로가기
GameMaker강좌[GMS2]/기타장르강좌

[게임메이커 강좌-기타][GMS2]미니맵 만들기

by 타락카얀 2023. 3. 12.
728x90

 

 

GAME MAKER 강좌

 

KAYAN

 

 

 

 

 

◈ 미니맵 만들기

 

 

이번 강좌에서는 미니맵을 만들어 봅시다.

 

(▲ 미니맵)

 

우선 미니맵 구성을 하기위해 미니맵에 표시할 유닛 오브젝트를 만들고 룸에 배치합시다.

플레이어 오브젝트는 obj_player, 적 오브젝트는 obj_enemy 으로 합니다.

 

(▲ 배치할 플레이어 유닛)

 

(▲ 배치할 적 유닛)

 

어차피 테스트용이기 때문에 대충 만드셔도 됩니다.

다음은 룸을 추가하여 룸의 크기를 설정하고, 유닛 오브젝트들을 배치합니다.

강좌에서는 프로젝트를 생성했을 때 기본적으로 생성된 룸을 활용하여 룸의 크기는 2000 x 2000 으로 설정하겠습니다.

 

(▲ 룸에 유닛 배치)

 

그리고 카메라 뷰를 설정합니다.

카메라 뷰 활성화는 Enable Viewports 를 체크하고, 사용할 뷰에서 Visible을 체크하면 됩니다.

 

(▲ 카메라 설정)

 

카메라 뷰는 룸의 크기보다 작은 800 x 600 으로 설정해봅시다.

 

이제 본격적으로 만들 미니맵을 표시/제어할 오브젝트를 하나 만들고, 룸에 배치해둡니다.

이름은 간단하게 obj_minimap 로 하겠습니다.

 

(▲ 미니맵 오브젝트)

 

먼저 [Create 이벤트]를 추가하고, 필요한 변수를 만들거에요.

강좌에서는 대충 미니맵의 기본 위치, 미니맵 크기, 미니맵에 필요한 변수를 만듭니다.

 


   //● obj_minimap 오브젝트 - Create 이벤트
   
   
   minimap_x=16;//미니맵 기본 위치
   minimap_y=16;//미니맵 기본 위치
   
   minimap_width=160;//미니맵 가로 크기
   minimap_height=120;//미니맵 세로 크기
   
   minimap_click=0;//미니맵 내부에 마우스 포인터가 있을 때=1, 밖에 있을 때=0


 

이와 같이 여러 곳에서 공유되는 중요한 값들을 미리 만들어두면 나중에 수정하기가 매우 편합니다.

 

미니맵은 [Draw GUI 이벤트]에서 표시할 거에요.

[Draw GUI 이벤트][Draw 이벤트]보다 상위에 표시되는 이벤트로 카메라 좌표에 영향을 받지 않는 특별한 이벤트입니다.

일반적으로 사용자 인터페이스를 구성할 때 사용합니다.

 

미니맵 오브젝트에 [Draw GUI 이벤트]를 추가하고, 미니맵 틀을 구성합니다.

미니맵을 만들기 위해서 카메라의 좌표와 미니맵의 좌표를 알고 있어야 합니다.

 


   //● obj_minimap 오브젝트 - Draw GUI 이벤트
   
   
   //카메라 좌표
   var _w,_h,vx,vy,vw,vh;
   vx=camera_get_view_x(view_camera[0]);//카메라 x 좌표
   vy=camera_get_view_y(view_camera[0]);//카메라 y 좌표
   vw=camera_get_view_width(view_camera[0]);//카메라 너비
   vh=camera_get_view_height(view_camera[0]);//카메라 높이
   
   
   //미니맵의 좌표와 크기
   var map_x,map_y,map_w,map_h;
   map_x=minimap_x;//미니맵 x 좌표
   map_y=minimap_y;//미니맵 y 좌표
   map_w=minimap_width;//미니맵 너비
   map_h=minimap_height;//미니맵 높이



 

대충 위와 같이, 임시변수에 필요한 값을 할당해두면 활용하기가 좋겠죠.

이 좌표를 사용하여 미니맵을 표시할 거에요.

강좌에서 미니맵은 화면의 왼쪽 상단에 표시하겠습니다.

먼저, 미니맵 외형을 만들어 보아요.

 


   //● obj_minimap 오브젝트 - Draw GUI 이벤트
   
   
   //카메라 좌표
   var _w,_h,vx,vy,vw,vh;
   vx=camera_get_view_x(view_camera[0]);
   vy=camera_get_view_y(view_camera[0]);
   vw=camera_get_view_width(view_camera[0]);
   vh=camera_get_view_height(view_camera[0]);
   
   
   //미니맵의 좌표와 크기
   var map_x,map_y,map_w,map_h;
   map_x=minimap_x;
   map_y=minimap_y;
   map_w=minimap_width;
   map_h=minimap_height;
   
   
   //--------------------- ▼ 이어서 추가
   
   //미니맵 UI
   var c;
   c=c_dkgray;draw_rectangle_color(map_x,map_y,map_x+map_w,map_y+map_h,c,c,c,c,0);//배경
   c=c_gray;draw_rectangle_color(map_x,map_y,map_x+map_w,map_y+map_h,c,c,c,c,1);//외곽선




 

이와 같이 해서 테스트해보면 짙은 회색에 밝은 회색선의 미니맵이 아래와 같이 표시될 겁니다.

 

(▲ 테스트 화면)

 

어...음... 뭔가 썰렁하네요. ㅎㅎ

어째든 다음은 현재 화면을 비추고 있는 카메라 뷰의 위치를 표시해 볼거에요.

 

미니맵에 카메라 뷰를 표시하려면, 먼저 카메라의 좌표를 미니맵의 좌표로 변환한 값을 알아야 합니다.

 

(▲ 룸의 좌표를 미니맵 크기로 축소)

 

      미니맵좌표 = 카메라좌표 x 미니맵크기 / 룸크기

 

이와 같은 식으로 각각 미니맵에 표시할 x,y 좌표를 구하면, 아래와 같이 얻을 수 있습니다.

 


   //카메라의 좌표
   x=(vx*map_w)/room_width;
   y=(vy*map_h)/room_height
   
   //카메라의 크기
   w=(vw*map_w)/room_width;
   h=(vh*map_h)/room_height;


 

이것을 응용하여 미니맵 좌표를 더해 표시하면 됩니다.

 


   //● obj_minimap 오브젝트 - Draw GUI 이벤트
   
   
   //--------------------- ▼ 이어서 추가
   
   //미니맵에서 뷰의 위치 표시
   var _x,_y,_px,_py,_pw,_ph;
   _px=map_x+((vx*map_w)/room_width);
   _py=map_y+((vy*map_h)/room_height);
   _pw=(vw*map_w)/room_width;
   _ph=(vh*map_h)/room_height;
  

   c=c_white;draw_rectangle_color(_px,_py,_px+_pw,_py+_ph,c,c,c,c,1);



 

테스트해보면 흰색의 사각형이 미니맵 위에 표시될 거에요. 이것이 현재 카메라 뷰의 위치가 됩니다.

 

(▲ 테스트 화면)

 

어우~ 여전히 먼가 허전합니다. ㅎㅎ

강좌에서는 단순하게 표시했지만, 여러분은 원하시는 형태로 구성하시면 됩니다.

 

다음은 아래와 같이 룸에 배치한 유닛 오브젝트들을 표시해봅시다.

플레이어 유닛은 노란색, 적 유닛은 빨간색으로 표시할 거에요.

 

(▲ 미니맵에 유닛 표시)

 

좌표는 미니맵의 표시한 방식과 같습니다.

 


   with(obj_player){
   _x=map_x+((x*map_w)/room_width);
   _y=map_y+((y*map_h)/room_height);
   }


 

이것을 응용하여 룸 안에 있는 유닛을 표시한다면 아래와 같습니다.

 


   //● obj_minimap 오브젝트 - Draw GUI 이벤트
   
   
   var _w,_h,vx,vy,vw,vh;
   vx=camera_get_view_x(view_camera[0]);
   vy=camera_get_view_y(view_camera[0]);
   vw=camera_get_view_width(view_camera[0]);
   vh=camera_get_view_height(view_camera[0]);
   
   
   var map_x,map_y,map_w,map_h;
   map_x=minimap_x;
   map_y=minimap_y;
   map_w=minimap_width;
   map_h=minimap_height;
   
   //미니맵 UI
   var c;
   c=c_dkgray;draw_rectangle_color(map_x,map_y,map_x+map_w,map_y+map_h,c,c,c,c,0);//배경
   c=c_gray;draw_rectangle_color(map_x,map_y,map_x+map_w,map_y+map_h,c,c,c,c,1);//외곽선
   
   
   //미니맵에서 뷰의 위치 표시
   var _x,_y,_px,_py,_pw,_ph;
   _px=map_x+((vx*map_w)/room_width);
   _py=map_y+((vy*map_h)/room_height);
   _pw=(vw*map_w)/room_width;
   _ph=(vh*map_h)/room_height;
   c=c_white;draw_rectangle_color(_px,_py,_px+_pw,_py+_ph,c,c,c,c,1);
   
   //--------------------- ▼ 이어서 추가
   
   //유닛의 위치 표시
   
   //플레이어 오브젝트
   with(obj_player){
   if x>0 && y>0 && x<room_width && y<room_height{
   _x=map_x+((x*map_w)/room_width);
   _y=map_y+((y*map_h)/room_height);
   draw_circle_color(_x,_y,2,c_yellow,c_yellow,0);
   }}
   
   //적 오브젝트
   with(obj_enemy){
   if x>0 && y>0 && x<room_width && y<room_height{
   _x=map_x+((x*map_w)/room_width);
   _y=map_y+((y*map_h)/room_height);
   draw_circle_color(_x,_y,2,c_red,c_red,0);
   }}
   


 

여기까지 해보면 우리가 원했던 표시가 이루어질 거에요.

 

이제 미니맵 위에 있는 카메라를 드래그하여 화면을 움직여봅시다.

 

강좌에서는 사용자 이벤트에 드래그 이벤트를 구성하여 [Step 이벤트]에서 호출할 거에요.

[User Defined 0 이벤트]를 추가합니다.

 

우선 마우스 포인터가 미니맵 안에 있는지 체크해야합니다.

 


   //● obj_minimap 오브젝트 - User Defined 0 이벤트
   
   
   var _w,_h,vx,vy,vw,vh,mx,my;
   vx=camera_get_view_x(view_camera[0]);
   vy=camera_get_view_y(view_camera[0]);
   vw=camera_get_view_width(view_camera[0]);
   vh=camera_get_view_height(view_camera[0]);
   mx=mouse_x;
   my=mouse_y;
   
   var map_x,map_y,map_w,map_h;
   map_x=vx+minimap_x;
   map_y=vy+minimap_y;
   map_w=minimap_width;
   map_h=minimap_height;
   
   //마우스 포인터가 미니맵에 있는지 체크
   if mx>map_x && my>map_y && mx<map_x+map_w && my<map_y+map_h{
   minimap_click=1;//미니맵 내부에 마우스 포인터가 있을 때
   }
   else{
   //미니맵 밖에 있고, 마우스를 클릭하지 않았다면 변수를 초기화
   if !(mouse_check_button(mb_left)){minimap_click=0;}
   }
   


 

그리고 마우스 포인터가 미니맵 안에 있을 때, 마우스를 클릭하면 마우스 포인터 위치를 중심으로 카메라를 이동시킬 겁니다.

카메라의 위치는 아래의 함수를 사용하여 설정할 수 있습니다.

 

      camera_set_view_pos(camera, x, y)

 

 

미니맵 좌표를 룸의 좌표를 변환하려면, 룸 좌표를 미니맵 좌표로 변환한 식을 반대로 응용하시면 됩니다.

 

(▲ 미니맵 좌표를 룸의 좌표로 확대)

 

      카메라좌표 = (마우스좌표-(미니맵좌표 + 카메라좌표)) x 룸크기 / 미니맵크기

 

기본식을 그대로 사용하면 마우스 포인터 위치가 카메라 왼쪽 상단으로 정렬 될 겁니다.

따라서 기본식으로 얻은 값에 카메라 크기의 절반을 각각 x,y 위치에서 빼주면 카메라 가운데로 정렬할 수 있습니다.

이것을 응용하면 아래와 같이 할 수 있습니다.

 


   //● obj_minimap 오브젝트 - User Defined 0 이벤트
   
   
   var _w,_h,vx,vy,vw,vh,mx,my;
   vx=camera_get_view_x(view_camera[0]);
   vy=camera_get_view_y(view_camera[0]);
   vw=camera_get_view_width(view_camera[0]);
   vh=camera_get_view_height(view_camera[0]);
   mx=mouse_x;
   my=mouse_y;
   
   var map_x,map_y,map_w,map_h;
   map_x=vx+minimap_x;
   map_y=vy+minimap_y;
   map_w=minimap_width;
   map_h=minimap_height;
   
   //마우스 포인터가 미니맵에 있는지 체크
   if mx>map_x && my>map_y && mx<map_x+map_w && my<map_y+map_h{
   minimap_click=1;//미니맵 내부에 마우스 포인터가 있을 때
   }
   else{
   //미니맵 밖에 있고, 마우스를 클릭하지 않았다면 변수를 초기화
   if !(mouse_check_button(mb_left)){minimap_click=0;}
   }
  

   //--------------------- ▼ 이어서 추가
   
   //미니맵을 통해 뷰 이동
   var _x,_y;
   if minimap_click==1{
   _x=floor(((mx-map_x)*room_width)/map_w);
   _y=floor(((my-map_y)*room_height)/map_h);
   
   if mouse_check_button(mb_left){//마우스를 클릭하면 카메라를 이동
   
   //변환한 마우스 포인터 위치가 카메라의 가운데로 위치하도록 설정
   vx=max(0,min(_x-(vw/2),room_width-vw));
   vy=max(0,min(_y-(vh/2),room_height-vh));
   camera_set_view_pos(view_camera[0],vx,vy);
   
   }
   
   }
   


 

이것은 마우스 왼쪽 버튼을 누를 떄, 미니맵 위에 마우스 위치를 룸의 실제 좌표로 변환하여 카메라 뷰의 위치를 갱신하는 것입니다.

 

후우~ 끝났네요.

[Step 이벤트]를 추가하고, 이 이벤트를 호출하면 됩니다.

 


   //● obj_minimap 오브젝트 - Step 이벤트
   
   
   //미니맵 드래그
   event_user(0);
   


 

잘 이동하는지 테스트 해봅시다.

 

(▲ 미니맵 드래그하여 카메라 이동)

 

이번에는 미니맵 안에 마우스 오른쪽 버튼을 클릭했을 때, 오브젝트를 생성해봅시다.

강좌에서는 생성할 오브젝트는 플레이어 오브젝트입니다.

 

(▲ 미니맵을 통해 오브젝트 생성)

 

미니맵 드래그 이벤트와 마찬가지로 사용자 이벤트를 활용하겠습니다.

[User Defined 1 이벤트]를 추가하고, 이벤트를 구성합니다.

미니맵에서의 마우스 좌표를 룸의 좌표로 변환하려면 아래의 식으로 얻을 수 있습니다.

카메라 뷰 이동했을 때와 같죠.

 

      룸 좌표 변환 = (마우스좌표- (미니맵좌표 + 카메라좌표)) x 룸크기 / 미니맵크기

 

이 식을 응용하여 마우스 오른쪽 버튼을 클릭했을 때 오브젝트를 생성해봅시다.

 


   //● obj_minimap 오브젝트 - User Defined 1 이벤트
   
   
   //--------------- 미니맵을 통해 룸 좌표를 제어 시작
   
   var _w,_h,vx,vy,vw,vh,mx,my;
   vx=camera_get_view_x(view_camera[0]);
   vy=camera_get_view_y(view_camera[0]);
   vw=camera_get_view_width(view_camera[0]);
   vh=camera_get_view_height(view_camera[0]);
   mx=mouse_x;
   my=mouse_y;
   
   var map_x,map_y,map_w,map_h;
   map_x=minimap_x;
   map_y=minimap_y
   map_w=minimap_width;
   map_h=minimap_height;
   
   
   //룸 내에서의 미니맵 위치(카메라 위치 기준)
   var cx,cy;
   cx=vx+map_x;
   cy=vy+map_y;
   
   //미니맵에서의 마우스 위치를 룸의 좌표로 환산
   var map_mouse_x,map_mouse_y;
   map_mouse_x=((mx-cx)*room_width)/map_w;
   map_mouse_y=((my-cy)*room_height)/map_h;
   
   
   //오브젝트 생성 테스트
   if minimap_click==1{
   if mouse_check_button_pressed(mb_right){
   instance_create_depth(map_mouse_x,map_mouse_y,0,obj_player);
   }}
   
   //--------------- 미니맵을 통해 룸 좌표를 제어 끝
   


 

이렇게 하면, 미니맵 위에서 마우스 오른쪽 버튼을 눌렀을 때, 미니맵 위의 마우스 위치를 룸의 좌표로 변환한 위치에 플레이어 유닛을 생성하게 됩니다.

이제 구성한 사용자 이벤트를 [Step 이벤트]에서 호출하면 됩니다.

 


   //● obj_minimap 오브젝트 - Step 이벤트
   
   
   //미니맵 드래그
   event_user(0);
   
   //------------------- ▼ 이어서 추가
   
   //미니맵을 통해 룸 좌표를 제어
   event_user(1);



 

여기까지~!

잘 작동하는지 테스트해봅시다.

강좌는 단순히 원리 위주로 설명했지만, 여러분은 더 멋진 UI를 구성하실 거라 생각합니다.

 

 

 

 

minimap_example_1.yyz
0.03MB

 

 

 

 

 

300x250

댓글