GAME MAKER 강좌
KAYAN
◈ 그리드 기반의 길찾기(Path finding) 응용편1
이번 강좌에서는 길찾기를 직접 구성해봅시다.
강좌에서는 마우스를 클릭하면 그 위치로 플레이어가 이동하도록 만들 거에요.
(▲ 마우스를 클릭하면 이동)
먼저 룸 시작시 그리드와 패스를 만들어야 합니다.
그리드와 패스를 만들 오브젝트( obj_system )를 하나 추가하고 [Room Start 이벤트]를 추가합니다.
//● obj_system - Room Start 이벤트 global.grid=32; global.move_grid=mp_grid_create(0,0,ceil(room_width/global.grid),ceil(room_height/global.grid),global.grid,global.grid); global.move_path=path_add( ); |
그리드는 룸의 크기 만큼 셀을 만듭니다.
그러면 룸 내의 그리드 크기만큼 좌표를 사용할 수 있게 됩니다.
강좌에서는 그리드의 크기를 32X32 정도의 크기로 설정했습니다만, 크기가 크면 좀 더
간결하게 이동할 수 있고, 작으면 정교하게 패스를 만들 수 있습니다.
다만, 이동하는 오브젝트의 이미지 크기를 고려해 그리드의 크기를 결정하는 것이 좋습니다.
그리드를 사용하는 모든 룸의 크기가 동일하다면 한 번만 만들어도 되지만, 룸마다 크기가 다를 수
있으므로 룸 시작시 다시 만드는 방법을 사용하는 것이 좋습니다.
다만, 패스 같은 경우는 변경할 부분이 없기 때문에 룸 시작시 만들어도 되지만, 게임 시작시 한 번만
만들어도 됩니다.
일단 강좌에서는 룸 시작시에 만드는 것으로 하겠습니다.
그리고 룸 종료시 그리드와 패스를 파기하도록 합니다.
//● obj_system - Room End 이벤트 mp_grid_destroy(global.move_grid); path_delete(global.move_path); |
이와 같이 하면 룸 시작시에 룸에 사용할 그리드와 패스를 만들고, 다음 룸으로 갈 때,
현재 룸에서 사용한 그리드와 패스를 파기하고 이동합니다.
물론 다음 룸에도 그리드를 사용한다면 다시 새로 만들고, 파기하게되는 것이죠. 단순합니다.
플레이어 오브젝트( obj_player )를 하나 만듭니다.
플레이어의 이미지는 그리드 셀 중심에 위치하도록 중심점을 맞춰주세요.
(▲ 플레이어의 이미지는 그리드 셀 중심에 위치하도록 설정)
오브젝트에 [Create 이벤트]를 추가하고 이동에 관련된 변수를 선언해줍니다.
이벤트를 구성하다 필요한 변수가 있다면 하나씩 추가해주면 됩니다.
//● obj_player - Create 이벤트 move_on=0; |
[Step 이벤트]를 추가하고, 여기서 패스 이동을 구성하겠습니다.
먼저, 마우스 좌표를 만들어 봅시다.
패스는 그리드 셀 중심을 지나가기 때문에 마우스 좌표는 그리드 셀 중심에 위치하도록 마우스 좌표 값을 변환합니다.
그래야 패스를 구성할 때, 정확한 위치가 구성되기 때문이죠.
//● obj_player - Step 이벤트 var mx,my; mx=(floor(mouse_x/global.grid)*global.grid)+floor(global.grid/2); my=(floor(mouse_y/global.grid)*global.grid)+floor(global.grid/2); |
마우스 좌표를 그리드 셀 크기만큼 나누고, 소수점을 버린 후, 다시 곱해주면
셀 좌측 상단의 좌표를 얻을 수 있습니다. 여기에 다시 그리드 셀 크기의 반을 더해주면
셀의 중심 좌표를 얻을 수 있습니다.
다음은 마우스를 클릭 했을 때, 패스를 작성하기 전에 장애물을 먼저 추가해줍니다.
장애물을 추가하기전에 mp_grid_clear_all 함수를 사용하여 모든 장애물을 클리어해주고,
mp_grid_add_instances 함수로 간단하게 장애물 오브젝트를 추가해주면 됩니다.
장애물이 추가된 셀은 패스를 생성할 수 없기 때문에, 마우스를 클릭할 때 장애물을
미리 체크하도록 합니다.
//● obj_player - Step 이벤트 var _x,_y,_break; _break=0; if move_on==0{ if position_meeting(mx,my,obj_block){ _break=1; }//장애물 체크 if mouse_check_button_pressed(mb_left) && _break==0{//마우스 클릭 mp_grid_clear_all(global.move_grid);//장애물 위치 클리어 mp_grid_add_instances(global.move_grid,obj_block,0);//장애물을 그리드에 마킹 } } |
이제 패스를 생성하도록 합니다.
패스는 현재 위치를 시발점으로 마우스 위치까지 이동시키도록 설정합니다.
//● obj_player - Step 이벤트 var _break; _break=0; if move_on==0{ if position_meeting(mx,my,obj_block){ _break=1; } if mouse_check_button_pressed(mb_left) && _break==0{ mp_grid_clear_all(global.move_grid); mp_grid_add_instances(global.move_grid,obj_block,0); //--------- ▼ 추가 x=(floor(x/global.grid)*global.grid)+floor(global.grid/2); y=(floor(y/global.grid)*global.grid)+floor(global.grid/2); mp_grid_path(global.move_grid,global.move_path,x,y,mx,my,0);//패스 생성 //--------- ▲ 추가 } } |
강좌에서는 패스의 대각선을 허용하지 않고, 직선으로만 구성하도록 설정하겠습니다.
이동할 수 있는 패스는 포인트 구간이 최소 2개 이상이어야 합니다.
(▲ 패스 포인트가 2개 이상일 경우 이동함)
따라서 패스 포인트가 2개 이상일 때, path_start 함수를 사용하여 이동시키도록 합니다.
//● obj_player - Step 이벤트 var _break; _break=0; if move_on==0{ if position_meeting(mx,my,obj_block){ _break=1; } if mouse_check_button_pressed(mb_left) && _break==0{ mp_grid_clear_all(global.move_grid); mp_grid_add_instances(global.move_grid,obj_block,0); x=(floor(x/global.grid)*global.grid)+floor(global.grid/2); y=(floor(y/global.grid)*global.grid)+floor(global.grid/2); mp_grid_path(global.move_grid,global.move_path,x,y,mx,my,0); //--------- ▼ 추가 if path_get_number(global.move_path)>=2{ pspeed=2; path_start(global.move_path,pspeed,0,1);//패스를 따라 이동 move_on=1; } //--------- ▲ 추가 } } |
마지막으로 플레이어가 패스의 도착지점에 이동해 있다면, 패스를 완전히 종료 하도록 합니다.
여기서는 현재 좌표를 갱신하거나, 다른 변수들을 초기화시키면 됩니다.
//● obj_player - 이벤트 if move_on==1{ 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); move_on=0;//이동 초기화 path_clear_points(global.move_path);//패스 클리어 } } |
완성되었네요.
패스로 이동하는 오브젝트를 룸에 배치시 그리드 셀 중심에 위치하도록 배치하세요.
배치가 끝났다면 잘 되는지 테스트 해봅시다.
※ 패스가 잘 구성되는지 확인하고 싶을 때는 [Draw 이벤트] 에서 draw_path 함수를 사용하면
사용중인 패스를 간단하게 표시할 수 있습니다.
예)
//● obj_system - Draw 이벤트 draw_path(global.move_path,0,0,1); |
(▲ 테스트)
이 방식은 그리드 기반으로는 가장 기본적인 이동방식입니다.
패스를 오브젝트에서 단일 방식으로 공유하여 고정적인 패스를 사용하기 때문에 오브젝트를
한번에 한개만 이동시킬 수 있습니다.
'GameMaker강좌[GMS2] > 기타장르강좌' 카테고리의 다른 글
[게임메이커 강좌-기타][GMS2]그리드 기반의 길찾기-6 A Star 알고리즘 (2) | 2023.01.29 |
---|---|
[게임메이커 강좌-기타][GMS2]그리드 기반의 길찾기-5 이동 거리 제한 (0) | 2023.01.18 |
[게임메이커 강좌-기타][GMS2]그리드 기반의 길찾기-4 응용편3 (0) | 2023.01.13 |
[게임메이커 강좌-기타][GMS2]그리드 기반의 길찾기-3 응용편2 (0) | 2023.01.12 |
[게임메이커 강좌-기타][GMS2]그리드 기반의 길찾기-1 기초 (4) | 2023.01.11 |
댓글