본문 바로가기
GameMaker강좌[GMS2]/전략게임강좌

[게임메이커 강좌-전략][GMS2]RTS 게임 만들기-1 유닛 선택

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

 

 

GAME MAKER 강좌

 

KAYAN

 

 

 

 

 

 

◈RTS 게임을 만들기 이전에

 

 

이번에는 실시간 전략 시뮬레이션(RTS) 게임을 한번 만들어 봅시다.

RTS게임은 만들기가 복잡하고, 이것저것 이벤트 설정해야하는 것이 많아 제작하기가 까다로운 측에 속하며,

최적화를 위해 오브젝트나 이벤트 관리가 매우 중요합니다.

 

(▲강좌에서 제작할 RTS 게임)

 

이번 강좌에서는 유닛 선택까지 해볼 것 입니다. 한번 따라서 해보아요.^^

 

 

 

 

 

◈유닛 준비(obj_pl_unit1,obj_en_unit1)

 

 

유닛을 만들기 위해 유닛 이미지를 준비하여 스프라이트를 만듭시다.

 

(▲강좌에서 사용할 플레이어1 유닛)

 

스프라이트를 만들었다면 중심점과 마스크(Modify Mask)를 적당하게 설정합니다.

 

(▲강좌에서 사용할 적1 유닛)

 

강좌에선 2가지 이미지를 준비했습니다.

그리고 유닛의 parent를 이용할 오브젝트를 플레이어(obj_player)와 적(obj_enemy) 2가지 오브젝트를 만들고,

실제로 배치 시킬 유닛 오브젝트(obj_pl_unit1,obj_en_unit1)를 각각 만듭니다.

 

예)


   ● obj_player (플레이어 부모 오브젝트) - obj_pl_unit1 (자식 오브젝트, 실제 배치)

   obj_enemy (적 부모 오브젝트) - obj_en_unit1 (자식 오브젝트, 실제 배치)


 

(▲ 유닛의 부모 오브젝트로 사용할 오브젝트)

 

플레이어 오브젝트(obj_pl_unit1)와 적 오브젝트(obj_en_unit1)의 준비된 스프라이트를 각각 지정하고,

부모 오브젝트를 parent에 연결해줍니다.

 

(▲ 플레이어 오브젝트)

 

(▲ 적 오브젝트)

 

 

 

 

 

◈플레이어 유닛(obj_pl_unit1)

 

 

먼저 플레이어 유닛(obj_pl_unit1)에 [Create 이벤트]를 추가하고 필요한 변수들을 선언합니다.

 


   //● obj_pl_unit1 - Create 이벤트
   
  

   flag=0;//0=플레이어 1=적
   select=0;//선택 체크
   
   HP=10;//체력
   HP_MAX=HP;//최대 체력


 

그리고 [Draw 이벤트]를 추가하고 이미지를 표시하도록 합니다.

 


   //● obj_pl_unit1 - Draw 이벤트
   
  

   draw_sprite_ext(sprite_index,-1,x,y,1,1,direction,c_white,1);


 

이것은 오브젝트에 설정된 스프라이트 이미지를 표시하는 것으로 방향에 따라 이미지가 회전하게 됩니다.

 

※[참고]

※draw_sprite_ext(sprite,subimg,x,y,xscale,yscale,angle,color,alpha)

※만약 스프라이트가 애니메이션이라면 subimg에 -1을 넣으시면 됩니다.

 

 

 

 

 

◈유닛 선택(obj_ctrl_sys)

 

유닛 선택을 총괄하여 제어하는데 사용할 오브젝트(obj_ctrl_sys)를 하나 만듭니다.

 

(▲시스템 오브젝트)

 

[Create 이벤트]를 추가하고 필요한 변수를 선언합니다.

 


   //● obj_ctrl_sys - Create 이벤트
  
   

   mouse_start_x=0;//마우스 드래그시 기준점 x좌표
   mouse_start_y=0;//마우스 드래그시 기준점 y좌표
   
   pressed=0;//마우스 버튼 체크


 

다음은 마우스를 드래그하여 유닛을 선택하는 이벤트를 작성해봅시다.

[End Step 이벤트]를 추가하고 드래그 이벤트를 작성합니다.

 


   //● obj_ctrl_sys - End Step 이벤트
   
  

   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);//마우스 오른족 버튼을 누르고 있을때
   
   
   if mbp_L==1{
   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;}}//현 마우스 좌표에 플레이어가 있는 경우 선택함
   }
   


 

이것은 마우스 왼쪽 버튼을 눌렀을 때 드래그 기준점을 정하는 것입니다.

처음에는 모든 플레이어 유닛의 select 변수를 초기화 시키고, 마우스 좌표에 플레이어 유닛이 없다면,

드래그 기준점 좌표를 설정하고, 드래그 선택했는지 변수를 설정하게 됩니다.

만약 마우스 좌표에 플레이어 유닛이 하나 있을 경우(else) 그 유닛은 일단 선택하도록 합니다.

즉 유닛을 한개씩 선택할 경우에 사용하는 이벤트라 할 수 있습니다.

 

※[참고] var는 스크립트, 또는 해당 이벤트에서만 변수를 사용할 때 사용합니다. 사용법은 var 뒤에 해당 이벤트에서 사용할 변수명을 적고, 그 뒤에 변수를 선언하면 됩니다.


   예)
   var aa,bb;
   aa=0;
   bb=1;


 

다음은 드래그 이후의 설정을 해봅시다.

여기에서 유닛을 드래그해 선택할 수 있는 것입니다.

[End Step 이벤트]에 아래와 같이 작성합니다.

 


   //● obj_ctrl_sys - End Step 이벤트
   
  
   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);//마우스 오른족 버튼을 누르고 있을때
   
   
   if mbp_L==1{
   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;
   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;//최대 선택은 12로 제한
   
   with(obj_player){
   if _sel<_max{//기준점과 현재 좌표를 기준으로 사각형 범위 안에 들면 유닛을 선택함.
   if x>_x1 && y>_y1 && x<_x2 && y<_y2{
   select=1;
   _sel+=1;}
   }
   }
   
   pressed=0;
   }//마우스 체크한 것을 다시 리셋

   


 

이것은 아래의 그림과 같이 마우스 드래그 이후, 마우스 왼쪽 버튼을 눌렀을 때 설정한 기준점과 현재 좌표를

이용한 사각형 범위 안에 유닛을 선택하게 하는 것입니다.

 

(▲ 마우스 드래그하여 유닛 선택)

 

또한 유닛 선택 최대 인원을 12로 제한하여 선택합니다.

많이 선택하고 싶다면 12보다 높은 값을 넣으면 되겠죠. 헤헤~

 

※[참고] with는 지정한 오브젝트에서 이벤트를 발생시키고자 할때 사용합니다. 이벤트 처리는 반복문(repeat, for문등)과 비슷하며, with(오브젝트) 괄호 안에 있는 오브젝트 또는 인스턴스를 생성된 id순서대로 이벤트를 처리하게 됩니다.

 

사용 예)


   with(obj_player){ instance_destroy( ); }//모든 obj_player를 파기시킴.

 

다음은 아래와 같은 빨간 드래그 표시를 화면에 만들어 봅시다.

 

(▲ 마우스 드래그중임을 표시)

 

[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);
   }
   


 

이것은 draw_rectangle_color를 사용하여 [End Step 이벤트]에서 설정한 기준점과 현재 마우스 좌표를

기준으로 사각형을 그리는 것입니다.

[Draw GUI 이벤트]는 카메라 뷰의 영향을 받지 않기 때문에 마우스 좌표에서 카메라의 위치를 빼줘야 합니다.

 

 

 

 

 

 

◈유닛 선택 표시(obj_draw_floor)

 

 

이번엔 선택되었는지 유닛에 표시를 해봅시다.

 

(▲ 유닛 선택)

 

유닛을 표시하기 위해 사용할 오브젝트(obj_draw_floor)를 하나 생성합니다.

 

(▲ 화면에서 유닛 오브젝트들보다 후위에 보이는 오브젝트)

 

이 오브젝트는 다른 오브젝트들 보다 맨 아래에 위치할 거에요.

 

오브젝트에 [Draw 이벤트]를 추가하고, 유닛이 선택되었는지 표시에 대한 이벤트를 작성해요.

강좌에선 원형태의 표시를 해보겠습니다.

 


   //● obj_draw_floor - Draw 이벤트
   
   
   //선택된 유닛 표식
   var r,c;
   with(obj_player){
   if select=1{
   r=sprite_width*0.7;//선택 원표시의 반지름 크기는 스프라이트 넓이의 0.7배로 설정함
   draw_set_alpha(0.5);
   c=c_green;draw_circle_color(x,y,r,c,c,0);//녹색원형
   c=c_yellow;draw_circle_color(x,y,r,c,c,1);//노란색 외곽선
   draw_set_alpha(1);
   }
   }


 

이것은 선택되었을 시, 스프라이트 넓이의 0.7배 반지름 크기 녹색 원형태로 표시되게 합니다.

일정한 크기라면 적당한 크기를 입력하면 되겠죠.

 

(▲ 유닛 선택)

 

이 오브젝트를 배치할 때는 룸에서 가장 하위에 보이는 인스턴스 레이어에 직접 배치하는 방법과

룸에 먼저 배치한 오브젝트에서 생성하는 방법이 있습니다.

강좌에서는 단순하게 어차피 배치해야하는 시스템 오브젝트(obj_ctrl_sys)로 통해서 이 오브젝트를 생성해봅시다.

시스템 오브젝트(obj_ctrl_sys)의 [Create 이벤트]에 아래와 같이 추가합니다.

 


   //● obj_ctrl_sys - Create 이벤트
   
   
   instance_create_depth(0,0,50,obj_draw_floor);




 

깊이는 50 정로로 배치합니다.

강좌에서는 기본 유닛을 룸의 깊이 0짜리 인스턴스 레이어 배치할 것이기 때문에 1~99 사이의 값을

지정했지만, 기본적으로 룸의 레이어의 깊이 값을 다른 레이어의 깊이값을 고려(다른 레이어에

가려지지 않고 유닛 후위에 보이도록)하여 생성하시면 됩니다.

 

이제 플레이어의 체력도 선택시 표시되게 해볼까요.

 

(▲ 플레이어 위에 체력 표시)

 

플레이어 유닛 오브젝트(obj_pl_unit1)로 이동해서 [Draw 이벤트]에 아래와 같이 추가합니다.

 


     //● obj_pl_unit1 - Draw 이벤트
   
   
   draw_sprite_ext(sprite_index,-1,x,y,1,1,direction,c_white,1);
   
   //-----------------▼ 이어서 추가
   
   var _max,_p,_x,_y,c;
   if select==1{
   _max=20;
   _p=(_max*HP)/HP_MAX;//체력을 픽셀크기로 환산
   
   _x=x-(_max/2);
   _y=y-16;
   c=c_red;draw_rectangle_color(_x,_y,_x+_max,_y+3,c,c,c,c,0);//빨간 배경. 체력이 없는 경우
   c=c_green;draw_rectangle_color(_x,_y,_x+_p,_y+3,c,c,c,c,0);//녹색 체력
   c=c_black;draw_rectangle_color(_x,_y,_x+_max,_y+3,c,c,c,c,1);//검은색 외곽선
   }
   


 

이렇게 하면 선택된 유닛의 체력을 표시합니다.

여기까지 해봤으니 잘 작동하는지 테스트해봐야겠죠?

 

 

 

 

 

◈ 룸 설정 및 카메라 뷰 이동(obj_mouse_pointer)

 

 

테스트 하기 전에 룸이 화면보다 클 때 카메라 뷰를 이동하는 이벤트를 작성해봅시다.

카메라 뷰를 이동 시킬 오브젝트(obj_mouse_pointer)를 하나 만듭니다.

 

(▲ 뷰를 이동시킬 오브젝트)

 

그리고 16X16정도의 크기의 스프라이트를 지정하고, 보이지 않게 Visible을 체크해제합니다.

[Step 이벤트]를 추가한 다음 아래와 같이 이벤트를 작성합니다.

 


   //● obj_mouse_pointer - Step 이벤트
   
   
   x=mouse_x;
   y=mouse_y;


 

이것은 오브젝트의 좌표를 마우스 위치로 설정하여 마우스 포인터를 따라 다니게 하는 것입니다.

 

다음은 시스템 오브젝트(obj_ctrl_sys)로 이동해서 이 오브젝트를 생성하도록 합니다.

시스템 오브젝트(obj_ctrl_sys)의 [Create 이벤트]에 아래와 같이 추가 작성합니다.

 


   //● obj_ctrl_sys - Create 이벤트
   
   
   instance_create_depth(0,0,0,obj_mouse_pointer);


 

그러면 이 오브젝트가 자동으로 생성되겠지요.

 

 

이제 테스트할 시간입니다.

먼저 유닛들을 배치할 게임 룸을 하나 만들고, 룸 편집기를 열어 룸의 크기를 설정합니다.

강좌에서 기본적을 생성되어 있는 룸을 사용하고 룸의 크기는 2000X1500크기로 설정했습니다.

 

(▲ 룸의 크기 설정)

 

이제 룸의 카메라 뷰 설정으로 이동합니다.

일단 뷰 활성화(Enable Viewport)를 체크합니다.

다음 사용할 뷰를 선택하고 Visible을 체크하고, 카메라 뷰의 속성을 설정합니다.

 

(▲ 룸의 카메라 뷰 설정)

 

카메라 속성(Camera Properties)는 룸의 내용을 담는 것을 말하고,

뷰포트 속성(Viewport Properties)는 카메라의 내용을 화면에 최종적으로 출력하는 것을 말합니다.

강좌에서는 Viewport1을 활성화하여 800X600 크기로 설정하겠습니다.

 

이제 Object Following(오브젝트 추적) 에 마우스 포인터 오브젝트(obj_mouse_pointer)를

지정하주면 그 오브젝트를 카메라 뷰가 따라다니게 됩니다(스크롤 타입).

이 따라 다니는 속도를 조절할 수 있는데, 그 값은 아래에 있는 Horizontal Speed(가로속도)와

Vertical Speed(세로 속도)값을 지정하면 됩니다.

예를 들어, 값을 5로 설정하면 오브젝트 이동과 마찬가지로 1프레임당 5만큼 이동하게 됩니다.

 

(▲ 마우스 포인터 오브젝트 지정)

 

강좌에서는 적당하게 5정도로 설정하겠습니다.

카메라 뷰를  더 빠르게 이동시키려면 값을 크게 지정하거나, 기본값인  -1을 지정하시면 됩니다.

 

(▲ 화면 가장자리에 위치하면 마우스 포인터를 따라 뷰가 이동 )

 

와우! 이제 테스트 할 시간!

이왕 테스트 하기 전에 룸에 플레이어, 적 유닛(obj_pl_unit1)과 시스템 오브젝트(obj_ctrl_sys)를 배치하고

배경도 꾸며본 다음, 설정이 제대로 되었는지 확인하도록 해요.

 

(▲ 룸에 배치)

 

리소스를 배치할 때, 오브젝트는 [인스턴스 레이어]에서 배치하고, 타일은 [타일 레이어]에서 배치하면 됩니다.

그리고 그냥 단순 배경 이미지라면 [배경 레이어]에 이미지를 지정하세요.

여기까지 강좌대로 잘 되는지 테스트 해봅시다.

 

(▲ 테스트 화면)

 

※[참고]:오브젝트를 너무 많이 배치하면 오브젝트 이벤트 연산 처리 때문에 게임이 느려질 수 있습니다. 그렇기 때문에 적당히 배치하도록 해요.^^

 

다음 강좌에선 플레이어 유닛을 이동시키는 것에 대해 알아보도록 합시다.

 

 

 

- 다음 편에서 계속 -

 

 

strategy_rts_example01a_1.yyz
0.04MB

 

 

 

 

 

300x250

댓글