GAME MAKER 강좌
KAYAN
☆ 이번에는 플레이어 유닛의 공격에 대해 설정해 보도록 하겠습니다.
(▲플레이어 유닛의 공격 장면)
◈공격 오브젝트(obj_att)
강좌에선 간단하게 동그란 포탄을 직선으로 발사하여 공격시키는 형태로 만들어 보겠습니다.
먼저 공격용 이미지를 스프라이트(spr_att1)로 구성합니다.
(▲공격 이미지)
중심점을 가운데로 맞추세요.
마스크 설정이 필요하다면 Modify Mask버튼을 누르고 마스크 설정을 하도록 합니다.
그리고 공격으로 사용할 오브젝트(obj_att)를 하나 만들고, 스프라이트를 지정합니다.
(▲공격 오브젝트)
Create 이벤트를 추가하고, 필요한 변수를 선언합니다.
★ obj_att - Create 이벤트 flag=0;//0=플레이어 1=적 att=0;//공격력 |
이 오브젝트는 플레이어와 적 모두 사용할 수 있어요. flag 변수 값으로 두 진영을 구분하게 됩니다.
플레이어에서만 사용할 것이라면 빼도 됩니다.
이제 이 오브젝트가 적에게 데미지를 입혀야 겠지요.
Step 이벤트를 추가하고, 아래와 같이 이벤트를 작성합니다.
★ obj_att - Step 이벤트 if flag=0{//적(obj_enemy)과의 충돌. 플레이어의 공격 it=instance_place(x,y,obj_enemy); if instance_exists(it){ if it.hp>att{it.hp-=att;}else{it.hp=0;} instance_destroy();} } if flag=1{//플레이어(obj_player)와 충돌. 적의 공격 it=instance_place(x,y,obj_player); if instance_exists(it){ if it.hp>att{it.hp-=att;}else{it.hp=0;} instance_destroy();} } |
이것은 공격 오브젝트의 flag변수가 0일 때, 즉, 플레이어가 공격했을 때, 적 오브젝트와 충돌을 했다면,
적의 체력을 감소시키고, 자신은 파기합니다.
flag가 1일때는 반대로 적이 공격하는 것이므로, 플레이어와 충돌하면 그 상대 오브젝트의 체력을 감소시키고,
자신은 파기합니다.
※참고 : instance_place(x,y,오브젝트)는 x,y위치에서 충돌하는 상대 인스턴스 id를 반환하는 함수입니다.
사용예)
it=instance_place(x,y,obj_player);
if instance_exists(it){with(it){instance_destroy();}}
이것은 obj_player와 충돌하면 충돌 상대를 파기시킵니다.
Draw 이벤트를 추가하고 이 공격 오브젝트의 이미지를 표시하도록 합니다.
★ obj_att - Draw 이벤트 draw_sprite_ext(sprite_index,0,x,y,1,1,direction,c_white,1); |
목표 오브젝트를 빗맞추었거나, 없을 때는 계속 지나가겠지요.
따라서 플레이어의 이동시 시간제한을 둔것처럼 이 오브젝트에도 이동 시간 제한을 설정하도록 해요.
여기에선 Alarm 0 이벤트를 사용하도록 하겠습니다.
Alarm 0 이벤트를 추가하고, 아래와 같이 이벤트를 작성합니다.
★ obj_att - Alarm 0 이벤트 instance_destroy(); |
이 공격 오브젝트가 파기될때 아래와 같이 간단한 이펙트를 발생시켜 볼까요.
(▲ 흰색 이펙트)
먼저 이펙트로 사용할 이미지를 스프라이트(spr_effect1)로 구성합니다.
(▲ 흰색 이펙트 이미지)
중심점을 가운데로 맞춰주세요.
이 이펙트를 표시할 오브젝트(spr_ef1)를 하나 만듭니다.
(▲ 이펙트 오브젝트)
Create 이벤트를 추가하고, 필요한 변수들을 선언합니다.
여기에선 여러 용도로 사용하니, 여러 수치들을 세부적으로 선언하도록 하겠습니다. 헤헤~
★ obj_ef1 - Create 이벤트 spr=sprite_index;//표시할 스프라이트 이미지 img=0;//서브 이미지. -1일경우 애니메이션 재생 fade_spd=0.05;//페이드 아웃 값 sca=1;//확대/축소치 sca_spd=0;//확대/축소 속도 rot=0;//회전 rot_spd=0;//회전 속도 col=c_white;//혼합색 alp=1;//투명도 |
후우~ 이 정도면 여러 용도로 충분하겠군요. 헤헤~
스프라이트 지정도 있고, 페이드 아웃치도 따로 준비, 확대나 축소 할수있는 기능도, 그리고, 회전도 가능하게 했네요.
이제 Step이벤트를 추가하고, 아래와 같이 작성합니다.
★ obj_ef1 - Step 이벤트 if alp>0{alp-=fade_spd;}else{alp=0;instance_destroy();} rot+=rot_spd; sca+=sca_spd; |
투명도가 0이 될때까지 점점 투명해지다 0이하가 되면 이펙트는 파기하도록 합니다.
Draw 이벤트를 추가하고 이펙트를 표시하도록 합니다.
★ obj_ef1 - Draw 이벤트 draw_sprite_ext(spr,img,x,y,sca,sca,rot,col,alp); |
이 이펙트도 일정 시간이 지나면 파기하는 이벤트를 추가해볼까요?
여기에선 Alarm 0 이벤트를 사용하도록 하겠습니다.
Alarm 0 이벤트를 추가하고, 아래와 같이 작성합니다.
★ obj_ef1 - Alarm 0 이벤트 instance_destroy(); |
이제 이 이펙트를 공격 오브젝트(obj_att)의 Destroy 이벤트에서 생성하면 됩니다.
공격 오브젝트(obj_att)로 이동해서, Destroy 이벤트를 추가한 다음 아래와 같이 이펙트를 생성합니다.
★ obj_att - Destroy 이벤트 it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0; |
이펙트를 생성 후 spr변수에 이전에 만든 이펙트 이미지를 할당하면 됩니다.
음. 이 이펙트가 그냥 날라가면 좀 밋밋해보이겠죠.
여기에 잔상효과를 넣어봅시다.
(▲잔상 효과)
이것은 단순히 공격 오브젝트가 이동할 때마다 이펙트를 하나씩 떨궈뜨리면 됩니다.
간단하죠. 헤헤~
Step이벤트에 아래와 같이 추가합니다.
★ obj_att - Step 이벤트 it=instance_create(x,y,obj_ef1); it.spr=spr_att1;//공격 이미지와 같은 스프라이트를 지정 it.alp=0.5; |
이렇게 하면 이동할 때마다 이펙트를 하나씩 떨어뜨리며 이동하고, 이펙트는 점점 투명해진 후 소멸하게 됩니다.
와우! 공격 오브젝트가 하나 완성되었네요! 굳~!
이제 플레이어 유닛의 공격 설정에 대해 알아봅시다.
◈플레이어 유닛의 공격(obj_pl_unit1)
Create 이벤트에 아래와 같이 추가해주세요.
★ obj_pl_unit1 - Create 이벤트 flag=0; select=0; hp=10; hp_max=hp; pspeed=2; move_on=0; move_x=0; move_y=0; target=noone;//공격 목표물 //---------------------▼추가 range_min=96;//공격시 근접 거리 range_max=320;//공격시 이동 체크 범위 range_att=128;//공격 범위 att=1;//공격력 att_sw=0;//공격 스위치 att_delay=30;//공격 딜레이 //---------------------▲추가 |
일단 목표물을 따로 지정해주지 않았을 때, 유닛이 알아서 가까운 목표물을 인지하여,
목표물로 정하게 만들어 봅시다.
Step이벤트에 아래와 같이, 이전 강좌에서 작성 했던 이동 코드 위에 이벤트를 추가하여 작성합니다.
★ obj_pl_unit1 - Step 이벤트 //---------------------▼추가 var aa; if !(instance_exists(target)){target=noone;//목표물이 없는 경우 목표물을 초기화함 if instance_exists(obj_enemy){aa=instance_nearest(x,y,obj_enemy); if instance_exists(aa) && move_on=0{//가까운 적을 검색해 이동 범위 안에 있을 때 목표물로 설정 if distance_to_object(aa)<=range_max{target=aa;} }} } //---------------------▲추가 //----------------------이동 코드 위에 추가함 if move_on=1{if point_distance(x,y,move_x,move_y)>pspeed{ mp_potential_step(move_x,move_y,pspeed,0); }else{move_on=0;}} if hp<=0{hp=0;instance_destroy();} |
이것은 일단 목표물(target)이 없는 경우 목표물을 초기화 하고, 룸 상에 존재하는 가장 가까운 적을 검색해서
이동할 수 있는 범위 안에 드는지 체크해요.
그리고 어떠한 행동을 하지 않은 상태에서, 적이 이동 범위 안에 든다면 그 적 인스턴스를 목표물로 설정하는 거에요.
이제 목표물이 설정되었다면 유닛이 공격을 하든, 이동을 하든 어떠한 행동을 해야겠지요.
역시 마찬가지로 Step 이벤트에 아래와 같이 추가합니다.
이것은 목표물이 생겼을 때 상황으로 else라는 기능을 사용할 거에요.
★ obj_pl_unit1 - Step 이벤트 var aa; if !(instance_exists(target)){target=noone; if instance_exists(obj_enemy){aa=instance_nearest(x,y,obj_enemy); if instance_exists(aa) && move_on=0{ if distance_to_object(aa)<=range_max{target=aa;} }} } //---------------------▼추가 else{ if !(distance_to_object(target)<range_min){ mp_potential_step(target.x,target.y,pspeed,0); if move_on=1{move_on=2;}//게임 유저가 직접 이동시켰을 때는 일단 그 이동은 중지. 공격 이동 우선함 }else{move_on=0;} _dir=point_direction(x,y,target.x,target.y); //------------------------공격 if distance_to_object(target)<=range_att{ if att_sw=0{direction=_dir; it=instance_create(x,y,obj_att);//공격 오브젝트 발사! it.direction=point_direction(x,y,target.x,target.y); it.speed=5;it.att=att;it.flag=flag; it.alarm[0]=point_distance(x,y,target.x,target.y)/it.speed;//이동 시간 제한 alarm[0]=att_delay;att_sw=1;} } //------------------------공격 종료 if !(distance_to_object(target)<=range_max){target=noone;}//목표물이 이동거리보다 멀때는 target을 초기화 } if !(instance_exists(target)){if move_on=2{move_on=1;}}//이동 중이었을 때는 목표지점까지 마저 이동함. //---------------------▲추가 //----------------------이동 코드 if move_on=1{if point_distance(x,y,move_x,move_y)>pspeed{ mp_potential_step(move_x,move_y,pspeed,0); }else{move_on=0;}} if hp<=0{hp=0;instance_destroy();} |
이것은 공격 목표물이 정해졌을 때, 근접할 수 있는 거리(range_min)보다 멀면 mp_potential_step으로 이동하게 됩니다.
또한 이동중일때는 멈추도록 move_on을 다른 값으로 설정하지요.
만약 근접거리에 당도했다면 완전히 멈추게 됩니다.
그리고 공격할 수 있는 범위(range_att)에 든다면, 목표물 방향으로 이전에 만든 공격 오브젝트를 발사하게 됩니다.
다시 발사할때는 약간의 지연시간을 두고 발사하게 되지요.
만약 목표물이 이동할 수 있는 거리보다 멀면 목표물(target)은 다시 초기화 하게 됩니다.
move_on이 1이면 게임 유저가 직접 유닛을 이동시켰을 때입니다.
따라서 유닛이 이동 중인데 목표물이 없어졌다면, 이동 지점까지 마저 이동을 하는 것이죠.
다음은 재장전에 대해 설정해야합니다.
Alarm 0 이벤트를 추가하고, 다시 공격을 발사하도록 이벤트를 작성하도록 해요.
★ obj_pl_unit1 - Alarm 0 이벤트 att_sw=0; |
실제 게임을 플레이하는 사람이 직접 목표물을 정하도록 만들어 봅시다.
시스템 오브젝트(obj_ctrl_sys)로 이동해서 End Step 이벤트에 아래와 같이 추가합니다.
★ obj_ctrl_sys - End Step 이벤트 var mx,my; 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)){mp_x=mx;mp_y=my;pressed=1;} else{with(aa){select=1;}} } //select var _x1,_y1,_x2,_y2; if pressed=1 && mbc_L=0{ _x1=mp_x;_y1=mp_y; _x2=mx;_y2=my; if mp_x>mx{_x1=mx;_x2=mp_x;} if mp_y>my{_y1=my;_y2=mp_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{ 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{target=bb; //---------------------▼추가 move_on=1; move_x=mx;move_y=my; 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;}} |
캬아~ 추가 코드가 몇줄 안되네요. 핫~ 핫~
이건 간단합니다. 이전 강좌에서 유닛 이동에 대해 해보셨죠.
그것과 같은 것입니다. 조금 다른 점이라면 공격시 행동을 정해주는 것이지요.
먼저 목표물을 게임 유저가 직접 정했다면, 유닛의 목표물을 지정해주지요.
그리고 이동을 체크(move_on=1)도 해주고, 이동 좌표를 지정해줍니다.
이것은 목표물이 없어졌을 때 마저 이동시키게 하기 위함입니다.
테스트 하기 전에 적에 대해 간단하게 설정해봅시다.
적에 대한 설정을 아무것도 안했기 때문에 이대로 테스트하면 오류가 생길 수 있습니다.
◈적 설정(obj_en_unit1)
Create 이벤트에 아래와 같이 작성해요.
★obj_en_unit1 - Create 이벤트 flag=1;//적 유닛이므로 1 select=0; hp=10; hp_max=hp; pspeed=2; move_on=0; move_x=0; move_y=0; target=noone; range_min=96; range_max=320; range_att=128; att=1; att_sw=0; att_delay=30; |
플레이어 유닛과 별다른 차이점이 없죠.
flag은 적 유닛이므로 1값을 넣고, 다른 수치는 입맛대로 변경하시면 됩니다.
강좌에선 플레이어 유닛의 수치들과 동일하게 적용하도록 하겠습니다.
유닛을 표시해야겠지요.
Draw 이벤트를 추가하고, 이미지를 표시하도록 합니다.
★obj_en_unit1 - Draw 이벤트 draw_sprite_ext(sprite_index,0,x,y,1,1,direction,c_white,1); |
그리고 체력이 0일때의 이벤트도 만들어야 하겠죠.
Step 이벤트를 추가하고, 체력이 0일때의 이벤트를 작성하도록 해요.
★obj_en_unit1 - Step 이벤트 if hp<=0{hp=0;instance_destroy();} |
음. 적 유닛이 파기될때 그냥 없어지면 좀 허전할 거에요.
간단한 이펙트라도 발생시킵시다.
Destroy 이벤트를 추가하고, 간단한 이펙트를 생성하도록 합니다.
★obj_en_unit1 - Destroy 이벤트 repeat(8){ it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0; it.sca=random_range(0.05,0.6); it.direction=irandom(360); it.speed=random_range(2,5); it.friction=0.1; }//흰색 이펙트를 랜덤 방향으로 날림 it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0;it.col=c_red; it.sca_spd=0.05;//붉은색 이펙트를 가운데 생성하고 점점 확대시킴. it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0;//흰색 이펙트를 가운데 생성함 |
이것은 이전에 만든 이펙트 오브젝트를 사용해서, 이펙트 여러개를 먼저 랜덤방향으로 흩날리고,
또 다른 이펙트로 가운데 위치에 붉은색 이펙트를 생성한 다음 점점 확대시킴니다.
그리고 가운데에 흰색 이펙트를 생성하는 것입니다.
이왕 만든김에 플레이어 유닛(obj_pl_unit1)의 파기했을 때도 같이 만들어 보도록 합시다.
플레이어 유닛 오브젝트(obj_pl_unit1)로 이동해서 Destroy 이벤트에서 이펙트를 생성하도록 합시다.
★ obj_pl_unit1 - Destroy 이벤트 repeat(8){ it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0; it.sca=random_range(0.05,0.6); it.direction=irandom(360); it.speed=random_range(2,5); it.friction=0.1; }//흰색 이펙트를 랜덤 방향으로 날림 it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0;it.col=c_red; it.sca_spd=0.05;//붉은색 이펙트를 가운데 생성하고 점점 확대시킴. it=instance_create(x,y,obj_ef1); it.spr=spr_effect1; it.img=0;//흰색 이펙트를 가운데 생성함 |
강좌에선 적 유닛의 파기 이벤트와 동일하게 적용하겠습니다.
와우! 드디어 플레이어의 공격설정이 끝났어요. 굳~!
어찌보면 쉽다고 생각한다면 쉬울 수도 있고, 어렵다고 생객할 수도 있었던 강좌였죠? 헤헤~
여러분 생각, 취향대로 공격 설정이라던지, 이펙트들을 만드시면 됩니다.
어째든 제대로 작동되는지 테스트 해봅시다.
(▲테스트 화면)
오우~ 맙소사! 적이 아무런 행동이 없군요.ㅠㅠ
이것은 마치 학살 수준이네요.
다음 강좌에선 적이 공격할 수 있는 이벤트에 대해 알아보도록 하겠습니다.
- 다음 편에서 계속 -
----------- 예 제 -----------
'GameMaker강좌[GM8] > 전략게임강좌' 카테고리의 다른 글
[게임메이커강좌-전략]RTS 게임 만들기 - 5 미니맵 구성 (43) | 2013.07.02 |
---|---|
[게임메이커강좌-전략]RTS 게임 만들기 - 4 적 유닛 (17) | 2013.07.02 |
[게임메이커강좌-전략]RTS 게임 만들기 - 2 유닛 이동 (14) | 2013.06.30 |
[게임메이커강좌-전략]RTS 게임 만들기 - 1 유닛 선택 (35) | 2013.06.29 |
[게임메이커강좌-디펜스]간단한 디펜스게임 만들기-2 (15) | 2013.04.30 |
댓글