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

[게임메이커 강좌-기타][GMS2]그리드 기반의 길찾기-1 기초

by 타락카얀 2023. 1. 11.
728x90

 

 

GAME MAKER 강좌

 

KAYAN

 

 

 

 

 

 

◈ 그리드 기반의 길찾기(Pathfinding)

 

 

게임메이커는 그리드 기반의 길찾기 기능이 제공됩니다.

 

(▲ 그리드 기반의 길찾기)

 

이 방식은 장애물을 인식시키고 원하는 위치를 향해 이동 경로를 패스로 그려 오브젝트를 이동

시키는 기능입니다.

 

(▲ 길찾기)

 

사용하기가 좀 까다로울 수 있지만, 규칙만 알면 쉽게 적용할 수 있습니다.

 

이 기능을 사용하기 위해서 먼저 패스가 필요합니다.

 


   ◎ path_add( ) : 패스를 생성합니다.

   ◎ path_delete(ind) : 패스를 메모리에서 제거합니다.


 

이제 그리드 기반의 길찾기 기능을 사용해봅시다.

처음 해야할 일은 길찾기에 필요한 그리드를 만들어야 합니다.

 


   ◎ mp_grid_create(left,top,hcells,vcells,cellwidth,cellheight) : 길찾기 그리드를 생성합니다.

      - left,top : 그리드가 시작되는 위치
      - hcells,vcells : 그리드 셀 수
      - cellwidth,cellheight : 그리드 셀의 크기


   ◎ mp_grid_destroy(id) : 길찾기 그리드를 파기합니다.


 

여기서 매우 중요한 부분인데, 그리드 셀이 있으면 셀 가운데를 중심으로 패스가 생성됩니다.

 

(▲ 패스 포인트 구간은 셀 가운데를 지나감)

 

따라서 오브젝트가 패스를 따라 이동하므로 오브젝트의 이미지를 셀 중심에 맞게

구성하는 것이 좋습니다.

 

패스를 만들 때 오브젝트의 위치 역시 셀 중심에 위치하도록 배치해야합니다.

그래야 패스의 이동 경로가 올바르게 설정될 수 있습니다.

 

 

장애물, 즉, 이동금지지역을 설정할 수 있습니다.

 

   ● 이동 금지 지역을 마킹


   ◎ mp_grid_add_cell(id,h,v) : 셀 단위로 이동 금지 지역을 마킹

   ◎ mp_grid_add_rectangle(id,left,top,right,bottom) : 위치를 지정하여 마킹
      - 지정한 위치가 포함된 셀들을 마킹합니다.


   ◎ mp_grid_add_instances(id,obj,prec) : 오브젝트 마스크 범위로 마킹


 

이동 금지 지역은 오브젝트를 지정해서 mp_grid_add_instances 함수로 마킹하는 것이 간편합니다.

마킹은 어떤 형태로든 셀 단위로 처리됩니다.

 

(▲ 셀 단위)

 

장애물을 클리어 또는, 초기화 할 때는 아래 함수를 사용합니다.

 

   ● 이동 금지 지역을 클리어


   ◎ mp_grid_clear_all(id) : 마킹한 지역을 모두 클리어

   ◎ mp_grid_clear_cell(id,h,v) : 마킹한 셀을 클리어

   ◎ mp_grid_clear_rectangle(id,left,top,right,bottom) : 지정한 위치에 있는 셀들을 클리어


 

이 함수들은 일반적으로 이동 금지 지역을 변경하거나, 이동 경로를 갱신할 때 사용합니다.

 

장애물 설치가 끝났다면 이제 이동 경로를 만들어야 합니다.

 


   ◎ mp_grid_path(id,path,xstart,ystart,xgoal,ygoal,allowdiag)


      - id : 사용할 그리드 ID
      - path : 적용할 패스 ID
      - xstart,ystart : 패스 출발 지점
      - xgoal,ygoal : 패스 도착 지점
      - allowdiag: 대각선 허용 여부. 대각선 허용 = 1, 직각만 허용 = 0


 

사용할 패스를 지정하고, 출발 지점과 도착 지점를 지정하면 됩니다.

여기서 주의해야 할 것은 이동 좌표는 무조건 그리드 셀 중심이어야 정확한 경로를 만들 수 있어요.

또한, 좌표는 mp_grid_create 함수로 설정한 그리드 내의 좌표로만 작동하고, 그리드 밖의 좌표는

작동하지 않습니다.

 

allowdiag 는 대각선을 허용할 지, 아니면 직각 경로만 허용할 지를 선택하면 됩니다.

 

(▲ 직각만 허용)

 

참고로 대각선을 허용한 방식과 직각 방식은 최단 거리를 측정하는 과정에서 이동 경로

결과가 다를 수 있습니다.

 

(▲ 대각선 허용)

 

mp_grid_path 함수가 패스를 성공적으로 만든다면 true 를 반환하고, 그렇지 않으면 false를 반환합니다.

즉, 도착 지점으로 이동할 수 있는 경우는 패스를 만들고, 도착 지점으로 이동할 수 없는

경우(장애물, 그리드 바깥)는 패스를 만들지 않는 것입니다.

 

현재 좌표를 시점으로 마우스 좌표로 경로를 만든다면 아래와 같이 할 수 있습니다.

 

예)


   global.grid=32;


   var mx, my, _x, _y;
   
   mx=(floor(mouse_x/global.grid)*global.grid)+floor(global.grid/2);
   my=(floor(mouse_y/global.grid)*global.grid)+floor(global.grid/2);
   
   _x=(floor(x/global.grid)*global.grid)+floor(global.grid/2);
   _y=(floor(y/global.grid)*global.grid)+floor(global.grid/2);
   
   mp_grid_clear_all(global.move_grid);
   mp_grid_add_instances(global.move_grid,obj_block,0);
   
   mp_grid_path(global.move_grid,global.move_path,_x,_y,mx,my,0);


 

패스의 패스 포인트가 몇개인지 확인하고 싶다면 path_get_number(path) 를 사용하세요.

 

패스가 성공적으로 만들어졌는지는 아래 함수로 확인할 수 있습니다.

 

   ※ 디버그 전용


   ◎ draw_path(path,x,y,absolute) : 지정한 패스를 표시


      - path : 패스 ID
      - x,y : 위치
      - absolute : 절대좌표 = 1, 상대좌표 = 0


 

패스 표시는 디버그 전용으로 패스가 만들어지면 아래와 같이 표시할 수 있습니다.

 

(▲ 디버그- 패스)

 

그리드가 정상적으로 만들어졌는지는 아래 함수로 확인할 수 있습니다.

 

   ※ 디버그 전용


   ◎ mp_grid_draw(id) : 지정한 그리드를 표시


      - 이동 금지 : 빨간색, 이동 가능 : 녹색


 

이 함수는 이동 가능한 그리드는 녹색으로 표시되고, 이동할 수 없는 곳은 빨간색으로 표시됩니다.

 

(▲ 디버그 - 그리드)

 

 

마지막으로 패스를 따라 이동 시키려면 아래 함수를 사용하면 됩니다.


   ◎ path_start(path,speed,endaction,absolute)


      - path : 패스 ID
      - speed : 이동 속도(음수로 지정할 경우 반대 방향)


      - endaction :
            0 : 패스를 정지
            1: 시작 위치에서 계속 추종. 만약 패스가 닫히지 않았다면 시작 위치로 점프.
            2: 현재 위치에서 계속 추종.
            3: 속도의 부호를 변경해 패스의 반대방향으로 이동.


      - absolute : 절대 좌표로 이동(true), 상대 좌표로 이동(false)


 

패스의 끝에 도달했는지 여부는 path_position 변수로 확인할 수 있습니다.

시작 위치는 0, 끝에 도달했다면 1이 됩니다.

 

예)


   global.grid=32;

   
   
   if path_position==1{

   path_end( );

   x=(floor(x/global.grid)*global.grid)+floor(global.grid/2);
   y=(floor(y/global.grid)*global.grid)+floor(global.grid/2);
   path_clear_points(global.move_path);

   }

 

 

 

 

 

 

 

300x250

댓글