GAME MAKER 강좌
KAYAN
이번에는 화면 상단에 미니맵을 구성하는 것에 대해 알아 볼 것입니다.
(▲게임 화면)
◈미니맵 구성(obj_ctrl_sys)
간단하게 적의 위치와 지금 어느 위치를 보고 있는지 확인할 수 있는 미니맵을 구성해봅시다.
(▲이번 강좌에서 만들게 될 왼쪽 상단의 미니맵)
먼저 게임을 제어하는 시스템 오브젝트(obj_ctrl_sys)로 이동해서, [Create 이벤트]에 필요한 변수들을 추가해줍니다.
//● obj_ctrl_sys - Create 이벤트 minimap_x=0;//미니맵 x위치 minimap_y=0;//미니맵 y위치 minimap_width=160;//미니맵 가로 사이즈 minimap_height=120;//미니맵 세로 사이즈 minimap_click=0;//미니맵 안에 마우스 커서가 있을 때=1, 밖에 있으면=0 |
이것은 미니맵의 크기를 미리 정해주는 것입니다.
다음은 [Draw GUI 이벤트]에서, 아래와 같이 추가해 미니맵의 위치와 모양을 표시해주도록 해요.
//● obj_ctrl_sys - Draw GUI 이벤트 //------------------- 맵 마우스 드래그 표시 var 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 x1,y1,x2,y2,c; if pressed==1{ draw_set_alpha(0.8); x1=mouse_x-vx; y1=mouse_y-vy; x2=mouse_start_x-vx; y2=mouse_start_y-vy; c=c_red;draw_rectangle_color(x1,y1,x2,y2,c,c,c,c,1); draw_set_alpha(1); } //------------------ ▼ 이어서 추가 //------------------ 미니맵 var map_w,map_h,map_x,map_y; //미니맵 크기 map_w=minimap_width; map_h=minimap_height; //미니맵 위치 map_x=minimap_x; map_y=minimap_y; //미니맵 배경 var c; //미니맵 외곽선 c=c_gray;draw_rectangle_color(map_x-2,map_y-2,map_x+map_w+2,map_y+map_h+2,c,c,c,c,0); //미니맵 바탕 c=c_dkgray;draw_rectangle_color(map_x,map_y,map_x+map_w,map_y+map_h,c,c,c,c,0); |
이것은 어두운 회색 바탕의 약간 밝은 회색의 외곽선을 가진 사각형 모양의 미니맵입니다.
다음은 화면에 보이는 카메라 뷰의 현재 위치와 크기를 미니맵에 표시해볼까요.
마찬가지로 [Draw GUI 이벤트]에서, 위의 내용 밑에 아래와 같이 추가합니다.
//● obj_ctrl_sys - Draw GUI 이벤트 //------------------ ▼ 이어서 추가 var 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 _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); |
흰색의 사각형모양으로 뷰의 크기와 위치를 확인할 수 있게 만들었습니다.
뷰의 위치와 크기를 미니맵 크기로 환산하자면 아래와 같은 비율식으로 구할 수 있습니다.
값=(실제 변동하는 크기X환산할 최대치)/실제 최대 크기
예를 들면 미니맵의 넓이가 160일때 룸 넓이(room_width)를 기준으로 뷰의 x좌표를 미니맵 크기로 환산한다면
값=(camera_get_view_x(view_camera[0])*160)/room_width
이렇게 됩니다. 간단하죠?
이제 이 식으로 유닛의 위치도 표시해보도록 해요.
[Draw GUI 이벤트]에 아래와 같이 추가하여, 유닛들의 위치를 표시하도록 합니다.
//● obj_ctrl_sys - Draw GUI 이벤트 //유닛 위치 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);//적은 붉은 색 }} |
이것은 유닛이 룸 내에 있을 때만 위치를 표시하게 됩니다.
룸 밖에 있을 때도 표시한다면 미니맵에서 벗어나 보기에 안 좋겠지요.
표시색은 되도록이면 눈에 잘보이는 색으로 표시하도록 해요.
◈미니맵에서 드래그해 뷰를 이동시키기(obj_ctrl_sys)
다음은 미니맵에서 드래그해 뷰를 이동 시켜 보도록 만들어 보아요.
(▲ 미니맵에서 드래그해 뷰를 이동시키기)
이 이벤트는 [사용자 정의 이벤트](User Defined)를 이용해보도록 하겠습니다.
[사용자 정의 이벤트](User Defined)는 이벤트에서 직접 실행시키지 않으면, 이벤트가 발생되지 않지만,
이벤트를 호출하게 되면 바로 실행시킬 수 있는 이벤트입니다.
이벤트 메뉴-> Other -> User Defined -> [User 0 이벤트]를 추가하고, 아래와 같이 작성합니다.
//● obj_ctrl_sys - 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; //마우스 포인터가 미니맵에 있는지 체크 var _x,_y; if pressed==0{//미니맵 밖에서 먼저 클릭하지 않았을 때 작동 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;pressed=0;} } } //미니맵을 통해 뷰 이동 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); } } if (mx>map_x && my>map_y && mx<map_x+map_w && my<map_y+map_h){ with(obj_mouse_pointer){x=vx+(vw/2);y=vy+(vh/2);} } |
이것은 마우스 포인터가 미니맵 안에 있을 때, 그리고 유닛을 선택하려고 드래그 하지 않았을 때 발생하게 합니다.
그리고 뷰의 위치를 미니맵에서 실제 크기로 환산하여 재배치하게 됩니다.
이때 미니맵 안에 있을 때 필드의 상황에 영향을 주지 않도록 minimap_click변수의 값을 1로 만들 놓습니다.
강좌에서 미니맵이 왼쪽 상단에 있죠.
뷰의 가장자리는 뷰를 움직이는 마우스 포인터 오브젝트(obj_mouse_pointer)를 따라 뷰를 이동시킵니다.
미니맵의 위치가 가장자리에 위치한다면, 뷰를 움직이는 마우스 포인터 오브젝트(obj_mouse_pointer)에
의해 의도치 않게 뷰가 이동할 수 있죠.
(▲ 미니맵에서 마우스 포인터 위치에 따라 의도치않게 뷰가 이동할 수 있음)
이것을 막기 위해 아래와 같이 추가하여 미니맵 안에 있을 때는 마우스 포인터 오브젝트를 뷰 가운데로 정렬하도록 합니다.
//● obj_ctrl_sys - 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; //마우스 포인터가 미니맵에 있는지 체크 var _x,_y; if pressed==0{//미니맵 밖에서 먼저 클릭하지 않았을 때 작동 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;pressed=0;} } } //미니맵을 통해 뷰 이동 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); } } if (mx>map_x && my>map_y && mx<map_x+map_w && my<map_y+map_h){ with(obj_mouse_pointer){x=vx+(vw/2);y=vy+(vh/2);} } //------------------------ ▼ 이어서 추가 if (mx>map_x && my>map_y && mx<map_x+map_w && my<map_y+map_h){ with(obj_mouse_pointer){x=vx+(vw/2);y=vy+(vh/2);} } //END |
이제 이 이벤트를 [End Step 이벤트]에서 호출 시켜 봅시다.
[End Step 이벤트]에 아래와 같이 추가합니다.
//● obj_ctrl_sys - End Step 이벤트 //------------------------ ▼ 추가 event_user(0); //◀미니맵 이벤트 호출 //------------------------ ▲ 추가 var mx,my,mbc_L,mbp_L,mbc_R; mx=mouse_x; my=mouse_y; mbc_L=mouse_check_button(mb_left); mbp_L=mouse_check_button_pressed(mb_left); mbc_R=mouse_check_button(mb_right); var aa,bb; //------------------------ ▼ 수정 if mbp_L=1 && minimap_click==0{ //◀유닛 선택은 미니맵 밖에 있을 때 발생하도록 변경 //------------------------ ▲ 수정 with(obj_player){select=0;} aa=collision_point(mx,my,obj_player,1,1); if !(instance_exists(aa)){ mouse_start_x=mx; mouse_start_y=my; pressed=1; } else{with(aa){select=1;}} } //유닛 선택 var _x1,_y1,_x2,_y2,it; if pressed=1 && mbc_L==0{ _x1=mouse_start_x;_y1=mouse_start_y; _x2=mx;_y2=my; if mouse_start_x>mx{_x1=mx;_x2=mouse_start_x;} if mouse_start_y>my{_y1=my;_y2=mouse_start_y;} var _sel,_max; _sel=0;_max=12; with(obj_player){ if _sel<_max{ if x>_x1 && y>_y1 && x<_x2 && y<_y2{ select=1; it=instance_find(obj_unit_position,_sel); if instance_exists(it){it.target=id;} _sel+=1;}}} pressed=0;} //유닛 이동 //------------------------ ▼ 수정 if mbc_R=1 && minimap_click==0{ //◀유닛 선택은 미니맵 밖에 있을 때 발생하도록 변경 //------------------------ ▲ 수정 with(obj_player){if select==1{ aa=collision_point(mx,my,obj_player,1,1); bb=collision_point(mx,my,obj_enemy,1,1); if !(instance_exists(bb)){ if !(instance_exists(aa)){ move_on=1; move_x=mx;move_y=my; target=noone; alarm[5]=point_distance(x,y,move_x,move_y)/pspeed; } }else{ move_on=1; move_x=mx;move_y=my; target=bb; alarm[5]=point_distance(x,y,move_x,move_y)/pspeed; } }} } //---------------move pointer-------------- with(obj_unit_position){ if instance_exists(target){ if check==1{ with(target){if select==1{move_x=other.x;move_y=other.y;}} } } else{target=noone;} } //END |
으아아~ 이렇게 보니 복잡해보이네요.
이 설정, 저 설정 넣다보면 느는건 코드양입니다.
전략 게임을 만들다보면 어쩔 수 없는 부분이죠.
이것은 event_user(이벤트 번호)로 사용자 정의 이벤트를 호출할 수 있으며, 호출하는 즉시 이벤트가 발생하게 됩니다.
그리고 미니맵에서 뷰를 드래그하는 것은 유닛 선택부분보다 먼저 발생하도록 처리합니다.
이제 잘되는지 테스트 해봅시다.
◈미니맵을 통한 유닛의 이동(obj_ctrl_sys)
이번에는 유닛을 선택한 후, 미니맵을 클릭해 이동시켜 보도록 해요.
(▲ 미니맵을 통한 유닛의 이동)
마찬가지로 [사용자 정의 이벤트](User Defined)를 이용하도록 합시다.
이벤트 메뉴-> Other -> User Defined -> [User 1 이벤트]를 추가하고, 아래와 같이 작성합니다.
//● obj_ctrl_sys - 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=vx+minimap_x; map_y=vy+minimap_y; map_w=minimap_width; map_h=minimap_height; //유닛 이동 if minimap_click==1{//미니맵 안에 있고 if mouse_check_button_pressed(mb_right){//마우스 오른쪽 버튼을 눌렀을 때 발생 var _x,_y; _x=((mx-map_x)*room_width)/map_w; _y=((my-map_y)*room_height)/map_h; with(obj_unit_position){check=1; x=_x+irandom_range(-8,8); y=_y+irandom_range(-8,8);} with(obj_player){if select==1{ move_on=1; move_x=_x;move_y=_y;target=noone; alarm[5]=point_distance(x,y,_x,_y)/pspeed; }} }} //--------------- 미니맵을 통해 룸 좌표를 제어 끝 |
저번 강좌에서 이동 설정에 대해 해보았죠?
넵. 그것과 같은 것입니다.
조금 다르다면 목표물(target) 설정이 없다는 것뿐이죠.
미니맵에서 실제크기로 좌표를 환산하여, 유닛 포지션 오브젝트(obj_unit_position)의 위치를
지정해주고, 선택된 유닛들의 위치도 지정하여 이동 시키는 것입니다.
이제 이 이벤트를 [End Step 이벤트]에서 호출 시켜 봅시다.
[End Step 이벤트]에 아래와 같이 추가합니다.
//● obj_ctrl_sys - End Step 이벤트 //------------------------ 미니맵 event_user(0); //------------------------ 미니맵 var mx,my,mbc_L,mbp_L,mbc_R; mx=mouse_x; my=mouse_y; mbc_L=mouse_check_button(mb_left); mbp_L=mouse_check_button_pressed(mb_left); mbc_R=mouse_check_button(mb_right); var aa,bb; if mbp_L=1 && minimap_click==0{ with(obj_player){select=0;} aa=collision_point(mx,my,obj_player,1,1); if !(instance_exists(aa)){ mouse_start_x=mx; mouse_start_y=my; pressed=1; } else{with(aa){select=1;}} } //유닛 선택 var _x1,_y1,_x2,_y2,it; if pressed=1 && mbc_L==0{ _x1=mouse_start_x;_y1=mouse_start_y; _x2=mx;_y2=my; if mouse_start_x>mx{_x1=mx;_x2=mouse_start_x;} if mouse_start_y>my{_y1=my;_y2=mouse_start_y;} var _sel,_max; _sel=0;_max=12; with(obj_player){ if _sel<_max{ if x>_x1 && y>_y1 && x<_x2 && y<_y2{ select=1; it=instance_find(obj_unit_position,_sel); if instance_exists(it){it.target=id;} _sel+=1;}}} pressed=0;} //유닛 이동 if mbc_R=1 && minimap_click==0{ with(obj_player){if select==1{ aa=collision_point(mx,my,obj_player,1,1); bb=collision_point(mx,my,obj_enemy,1,1); if !(instance_exists(bb)){ if !(instance_exists(aa)){ move_on=1; move_x=mx;move_y=my; target=noone; alarm[5]=point_distance(x,y,move_x,move_y)/pspeed; } }else{ move_on=1; move_x=mx;move_y=my; target=bb; alarm[5]=point_distance(x,y,move_x,move_y)/pspeed; } }} } //----------------------- ▼ 삽입 event_user(1); //◀미니맵 클릭 이벤트 호출 //----------------------- ▲ 삽입 //---------------move pointer-------------- with(obj_unit_position){ if instance_exists(target){ if check==1{ with(target){if select==1{move_x=other.x;move_y=other.y;}} } }else{target=noone;}} //END |
캬아~ 길다~
위의 위치에 호출 이벤트를 한줄 삽입하시면 됩니다.
이렇게 하면 [User Defined 1 이벤트]에서 구성했던 것을 실행하여 미니맵을 클릭했을 때
선택된 유닛이 해당 좌표로 이동해요.
와우~! 드디어 미니맵이 완성되었습니다.
테스트! 테스트를 해봅시다!
(▲ 테스트 화면)
후아~ 강좌는 여기까지입니다.
기초적인 부분만 설명했으나, 강좌가 많이 복잡했는데, 재미있으셨는지 모르겠네요.
이제 여러분이 이 강좌를 토대로 응용하셔서 게임을 제작하시면 됩니다.
어째든 재미있는 게임을 만들어 보도록 해요.
- 끝 -
● 예 제 ●
● 실행 버전 ●
'GameMaker강좌[GMS2] > 전략게임강좌' 카테고리의 다른 글
[게임메이커 강좌-전략][GMS2] RTS 게임 만들기-4 적 유닛 (2) | 2023.03.14 |
---|---|
[게임메이커 강좌-전략][GMS2] RTS 게임 만들기-3 유닛 공격 (2) | 2023.03.14 |
[게임메이커 강좌-전략][GMS2] RTS 게임 만들기-2 유닛 이동 (2) | 2023.03.14 |
[게임메이커 강좌-전략][GMS2]RTS 게임 만들기-1 유닛 선택 (0) | 2023.03.13 |
댓글