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

[게임메이커강좌-디펜스]간단한 디펜스게임 만들기-2

by 타락카얀 2013. 4. 30.
728x90

 

 

 

 

 

 

◈게임을 제어할 수 있는 시스템 오브젝트(obj_system)

 

 



이전 강좌에서 게임을 만들 어느 정도의 준비는 된 것 같습니다.
이제 게임을 총괄적으로 제어할 수 있는 시스템 오브젝트를 하나 만듭시다.
이 오브젝트에서 변수값도 화면에 표시하고, 플레이어 제어할 것입니다.

 

 

(▲게임 화면)

 

먼저 설정할 시스템 오브젝트(obj_system)를 하나 만들고 Create 이벤트를 추가한 후 필요한 변수들을

선언합니다.

 



     //obj_system - Create 이벤트

     global.hp=500;//플레이어의 체력
     global.hp_max=500;//최대 체력

     global.gold=500;//플레이어의 자금
     global.set_gold=0;//유닛 가격을 임시 기록함
     global.build_menu=0;//명령 메뉴(버튼)


 

강좌에선 편의상 global 변수를 스테이지 룸에서 선언했지만, 이 global 변수로 수치를 선언하는

변수들(체력, 자금등)은 타이틀 화면이나 게임 시작했을 때 선언하는 것이 좋습니다.

그래야 다음 스테이지로 넘어가도 변수값이 유지 됩니다(global.set_gold, global.build_menu와 같은

명령을 내리는 변수 제외).

 

이 오브젝트는 화면상에 맨 앞에 위치해야하기 때문에 depth를 다른 오브젝트보다 낮게 설정합니다.
강좌에선 대강 -10000로 하도록 하겠습니다..

이제 유닛을 생성 명령을 내릴 버튼 오브젝트(obj_button1)을 하나 만듭니다.
그리고 Create 이벤트를 추가하고, 버튼에 필요한 변수를 선언하도록 해요.

 



     //obj_button1 - Create 이벤트

     gold=100;//생성할 유닛의 가격


 

강좌에서는 버튼을 눌러 유닛을 생성할때 필요한 자금만 선언했습니다.

 

이제 이 버튼을 눌러 유닛을 생성할지 이벤트를 작성해야 겠지요.

마우스로 버튼을 눌렀다 떼었을 때 이벤트를 추가하고 유닛 생성에 관련된 이벤트를 구성하도록 합시다.

 



     //obj_button1 - Left Released 이벤트

     if global.gold>=gold{
     global.set_gold=gold;//차감할 가격을 임시적으로 기록해 둠
     global.build_menu=1;//메뉴 번호. 만약 2번째 버튼이라면 2를 지정하면 됨
     }



이것은 플레이어의 자금이 유닛 가격보다 클때 이벤트가 작동하게 됩니다.
그리고 이 명령(global.build_menu 버튼 메뉴. 강좌에선 1번)을 변수에 기록해두고 시스템 오브젝트에서

버튼에 관련된 유닛을 생성하도록 하는 것이지요.

버튼을 화면에 표시하기 위해 Draw 이벤트로 작성합니다.

 



     //obj_button1 - Draw 이벤트

     if global.gold>=gold{

     draw_sprite_ext(sprite_index,0,x,y,1,1,0,c_white,1);//사용가능 할때
     }
     else{

     draw_sprite_ext(sprite_index,0,x,y,1,1,0,c_red,1);//자금이 모자라 사용 불가능할때
     }

 

이렇게 하면 유닛 생성에 필요한 자금(gold)이 보유한 자금(global.gold)보다 클때는 유닛 생성이

불가능하므로 버튼을 붉게 표시(버튼을 붉은색으로 혼합시킴)하고, 유닛 생성이 가능할 때는 그대로

표시하게 됩니다.

 

그리고 이 버튼은 시스템 오브젝트가 생성될때 같이 생성되도록 합니다.
물론 화면에 따로 배치해도 됩니다. 헤헤~

 

 
     //obj_system - Create 이벤트
     //추가적으로 삽입

     it=instance_create(32,480-32,obj_button1);//유닛1 생성 버튼
     it.depth=depth-10;//깊이는 시스템보다 앞에 보이도록 설정



    

     //만약 추가 버튼이 있을때
     //버튼2
     it=instance_create(64,480-32,obj_button2);//유닛2 생성 버튼
     it.depth=depth-10;



     //버튼3

     it=instance_create(96,480-32,obj_button3);//유닛3 생성 버튼
     it.depth=depth-10;



다음은 유닛을 배치해도 되는지 아니면 안될지를 판단하기 위해 블록 오브젝트를 따로 만듭니다.


     예) obj_block(Parent 오브젝트)-obj_bl32(하위 오브젝트. 룸에 실제 배치되는 오브젝트)

 

캐릭터 오브젝트처럼 부모 오브젝트(Parent 오브젝트)를 두고 분류해두면 관리하기 편합니다.
하위 오브젝트(obj_bl32)는 실제로 배치해야하기 때문에, Sprite에 스프라이트를 지정해야합니다.

그리고 게임상에 보이지 않게 하려면 오브젝트의 visible을 체크해제해야 해요.

 

 

(▲룸에 배치 여부를 결정하기 위해 블럭오브젝트를 배치함)

 

강좌에서는 게임메이커 룸 에디터에서 배치해야하기 때문에 그냥 빨간색 이미지만 지정하여 룸에

배치했습니다.

 

이제 유닛 생성 버튼을 눌렀을 때 유닛을 생성해야겠지요.

시스템 오브젝트(obj_system)에 마우스 왼쪽 버튼을 눌렀을 때 이벤트(Global Left Pressed)를 추가하고,

유닛 생성에 관련된 이벤트를 작성합니다.

 



     //obj_system - Global Left Pressed 이벤트

     var _x,_y;
     _x=(floor(mouse_x/32)*32)+16;//그리드로 포인터를 맞춤
     _y=(floor(mouse_y/32)*32)+16;

     if global.gold>=global.set_gold
     && !(position_meeting(_x,_y,obj_allunit))
     && !(position_meeting(_x,_y,obj_block))
     && _x >0 && _y>20 && _x<view_wview && _y<view_hview-32{
     //자금이 충족하는지 생성하는 곳에 블럭과 유닛이 없는지 또는 포인터가 화면 안에 들어 왔는지를 체크함

     //명령 번호대로 유닛을 생성함
     switch(global.build_menu){
     case 1: instance_create(_x,_y,obj_tw1);break;

     /*2번이 있는 경우



     case 2: instance_create(_x,_y,obj_tw2);break;


     이런 식으로 추가 기입하면 됩니다.

     그리고 case 번호는 버튼의 메뉴 번호와 일치해야 합니다.*/
     }

     global.gold-=global.set_gold;//기록해둔 값으로 전체 자금을 감소
     //변수 리셋
     global.build_menu=0;
     global.set_gold=0;

     }



이것은 그리드의 위치에 유닛을 생성하는 것입니다.
그리드의 크기는 이미지의 크기를 고려해 설정하면 되는데, 예를 들어 이미지가 32X32이고,

중심이 (16,16)으로 맞춰져있다면,

     x=(floor(mouse_x/32)*32)+16
     y=(floor(mouse_y/32)*32)+16


이미지가 64X64이고, 중심이 (32,32)으로 맞춰져있다면,

     x=(floor(mouse_x/64)*64)+32
     y=(floor(mouse_y/64)*64)+32//+32는 이미지의 중심값. (0,0)이면 더하지 않아도 됨.

이런식으로 좌표를 잡아주면 유닛이 생성될때 그리드 중심에 생성되게 됩니다.

다음은 오른쪽 버튼을 눌렀을 때 유닛 생성명령을 취소하도록 합시다.

마우스 오른쪽 버튼을 눌렀을 때 이벤트(Global Right Pressed)를 추가하고, 명령들을 리셋하도록 합니다.

 



     //obj_system - Global Right Pressed 이벤트



     //변수 리셋
     global.build_menu=0;
     global.set_gold=0;


 

일반적으로 버튼 명령에 필요한 변수들만 초기화시켰습니다.

 

다음은 화면에 각종 정보를 표시하도록 Draw이벤트에 작성해요.
글자도 표시해야하기 때문에 글자를 표시하기 위한 폰트도 하나 만듭시다(자금, 그외 표시).

 



     //obj_system - Draw 이벤트

     var mx,my;
     mx=mouse_x;
     my=mouse_y;//마우스 좌표

     //플레이어에 포인터가 가있는 경우 공격 범위를 표시함
     it=collision_point(mx,my,obj_player,1,1);
     if instance_exists(it){
     with(it){draw_circle_color(x,y,range,c_red,c_red,1);}
     }

     //텍스트를 표시할 폰트를 지정
     draw_set_font(font10);
     draw_set_halign(fa_left);
     draw_set_valign(fa_top);//텍스트를 좌측 상단으로 정렬

     //상단의 메뉴 범위
     draw_rectangle_color(-1,-1,view_wview+1,20,c_dkgray,c_dkgray,c_dkgray,c_dkgray,0);
     draw_text_color(32,2,"GOLD :: "+string(global.gold),c_white,c_white,c_white,c_white,1);//자금 표시

     //하단의 메뉴 범위
     draw_rectangle_color(-1,view_hview-32,view_wview,view_hview+1,c_dkgray,c_dkgray,c_dkgray,c_dkgray,0);

     var _x,_y;
     _x=(floor(mouse_x/32)*32)+16;
     _y=(floor(mouse_y/32)*32)+16;//그리드 포인터 좌표


 

이것은 포인터가 유닛에 위치해 있다면 공격 범위를 표시해주고, 화면 상단에 자금을 표시해주는 것입니다.

 

다음은 유닛을 생성했을 때 어떤 유닛을 생성 할 것인지 미리 표시해주는 이벤트를 작성해보도록 해요.

Draw 이벤트에 유닛 표시 이벤트를 추가합니다.

 



     //obj_system - Draw 이벤트


     //----------------------------- ▼ 이벤트 추가



     //유닛 생성 버튼을 눌렀을 때 유닛 생성 정보를 마우스 포인터에 표시
     c=c_white;
     if !(!(position_meeting(_x,_y,obj_allunit))
     && !(position_meeting(_x,_y,obj_block))
     && _x >0 && _y>20 && _x<view_wview && _y<view_hview-32){c=c_red;}

     switch(global.build_menu){//몇 번째의 버튼을 눌렀는지 체크하여 유닛 정보를 표시.
     case 1:
     draw_circle_color(_x,_y,128,c_red,c_red,1);//예상 공격 범위
     draw_sprite_ext(spr_tw1,0,_x,_y,1,1,0,c,0.5);
     draw_sprite_ext(spr_tw1,1,_x,_y,1,1,0,c,0.5);//생성 유닛
     break;

     /*2번이 있는 경우
     case 2:
     draw_circle_color(_x,_y,128,c_red,c_red,1);//예상 공격 범위
     draw_sprite_ext(spr_tw2,0,_x,_y,1,1,0,c,0.5);
     draw_sprite_ext(spr_tw2,1,_x,_y,1,1,0,c,0.5);//생성 유닛
     break;
     */

     }

 

유닛이 생성될때는 생성할 위치에 무엇이 있는 지 확인해야 합니다.

그리고 생성 가능하면 생성가능하다는 표시를 해주는 것이지요.

 

후하~ 좀 길었군요. 하하핫^^
어째든 다음으로 넘어갑시다.

 

 

 

 

 

 

적 유닛들의 이동 경로(path0)

 
 
룸에 배경들을 배치하고, 적들이 이동경로를 패스로 작성합니다.

패스는 오브젝트들의 이동경로를 미리 작성하여 쉽게 적용할 수 있는 기능이며 마우스 클릭만으로

쉽게 만들 수 있습니다.

일단 패스 폴더에 적 유닛의 이동 경로로 사용할 패스(path0)를 추가합시다.

 

아래 그림에서 보이는 맨 우측 상단 툴바의 윈도우 모양의 아이콘이 보이시죠.

이 버튼을 누르면 편집 화면에서 미리 표시할 룸을 선택하여 표시할 수 있어,  패스를 쉽게 만들 수 있습니다.

이 기능을 이용하여 룸 내용을 미리 표시하고, 적의 이동경로를 마우스로 점을 찍어 만들도록 해요.

 

 

(▲적유닛이 이동할 수 있는 경로를 패스로 작성)

 

sp는 이동 속도를 기본 속도의 몇 퍼센트(%) 속도로 이동할 지 지정하는 것입니다.

예를 들어 100으로 지정하면 오브젝트에서 지정한 속도로 이동하게 하며, 200으로 지정하면 2배 빠른 속도로

이동하게 됩니다.

 

Straight kind는 패스의 모양을 선택하는 것으로 패스를 직선 또는 곡선모양으로 구성할 수 있습니다.

그리고 Closed를 체크하면 패스의 시작시점과 패스의 종료지점 이어주어 패스를 무한 루프 가능한 이동 패스를

만들  수 있습니다.

그리고 체크 해제하면 1회성 이동 패스를 만들 수 있게 되는 것이지요.

 

이제 시간별로 유닛을 생성하도록 타임라인을 작성해요.

타임라인 폴더에 타임라인 하나를 생성한후 Moments에 이벤트를 추가하고, 적 유닛이 생성되는 이벤트를

작성하도록 해요.

Moments의 1스텝은 1/룸 속도(초)와 같습니다.
예를 들어 룸속도가 60일때, 타임라인 60스텝은 약 1초입니다.

 

 

(▲유닛 생성용 타임라인)

 

아래처럼 유닛이 생성될때 이미 준비한 패스(path0)를 따라 이동하도록 설정합니다.

 

 
    //타임라인 - timeline0



     it=instance_create(-80,-80,obj_en1);//적 유닛 생성
     with(it){path_start(path0,1,0,1);}//경로를 따라서 이동하도록 패스를 지정함.



강좌에선 시스템 오브젝트(obj_system)에서 타임라인을 실행하도록 했지만, 유닛 생성용 타임라인 실행하는

오브젝트들을 따로 만들어, 스테이지별로 실행하도록 하는 것이 좋습니다.

강좌에선 시스템 오브젝트(obj_system)에서 게임 시작 후, 약간의 시간차를 주어 타임라인을 실행시킬

것입니다.

 

 
     //obj_system - Create 이벤트


     alarm[0]=60*10;//룸속도60일때 약 10초

 

 



     //obj_system - Alarm[0] 이벤트

     timeline_index = timeline0;
     timeline_running=1;



게임 시작후 약 10초후 타임라인을 실행합니다.

그리고 시스템 오브젝트의 Draw 이벤트 끝에 타임라인이 언제쯤 시작하는지의 정보를 표시하도록 해요.

 



     //obj_system - Draw 이벤트

     //게임 준비 정보를 상단 가운데에 표시
     if alarm[0]>0{
     draw_text_color(320,2,"Ready :: "+string(round(alarm[0]/60)),c_white,c_white,c_white,c_white,1);
     }
     //게임이 시작되면 체력을 표시함
     else{
     _x=240;_y=5;
     _h=320;
     c=c_red;draw_rectangle_color(_x,_y,_x+_h,_y+10,c,c,c,c,0);
     _h=(global.hp*320)/global.hp_max;
     c=c_green;draw_rectangle_color(_x,_y,_x+_h,_y+10,c,c,c,c,0);
     _h=320;
     c=c_black;draw_rectangle_color(_x,_y,_x+_h,_y+10,c,c,c,c,1);
     }



이렇게 하면 타임라인 시작전에 알람이벤트(Alarm 0 이벤트)의 시간에 따라 타이머를 화면의 상단 가운데에

'Ready :: 남은시간'을 표시하게 되고, 타임라인이 시작하면 체력바를 표시하게 됩니다.

 

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

 

 

(▲작동이 잘되는지 테스트)

 

룸에 배경들은 모두 배치했는지 확인하시고, 지금까지 설정한 시스템 오브젝트를 룸에 배치해요.
그리고 제대로 작동되는지 확인해봅시다.

 

 

 

 

------------- 예 제 -------------

 

 

defence1-예제.gmk
다운로드

 

defence1-예제.exe
다운로드

 

 

 

 

300x250

댓글