GAME MAKER 강좌
KAYAN
이번 강좌에서는 필드의 아이템을 체크하는 방법과 계단을 이동하는 방법에 대해 알아보도록 합시다.
(▲ 계단)
(▲ 아이템 체크)
강좌 2까지 따라해보셨다면 이번 강좌는 응용편이 되겠군요.
먼저 필드에 있는 아이템을 체크하는 방법에 대해 알아봅시다.
◈ 필드의 아이템 체크(obj_item)
일단 아이템을 체크하려면 아이템 오브젝트(obj_item)가 있어야 겠지요.
아이템 오브젝트를 하나 만들고, 룸에 배치할 수 있게 Sprite에 적당한 스프라이트 이미지를
지정하도록 해요.
물론 이 스프라이트 이미지는 마스크 역할도 같이 할 것입니다.
(▲ 아이템 오브젝트)
그리고 Create 이벤트를 추가하고, 간단하게 Z축과 높이에 대한 변수들을 선언하도록 합니다.
(블럭들과 마찬가지로 3D상에서 체크할 수 있어야 하기 때문)
★ obj_item - Create 이벤트 z=0;//z축 ztop=5;//높이 color=c_white;//체크 확인 |
color 변수는 테스트시 체크가 되었는지 확인하기 위해 변수를 작성했습니다.
체크가 되면 빨간색으로 변하게 되고, 그렇지 않으면 일반적인 모습이 되는 것이지요.
이제 아이템 모델을 표시하도록 합시다.
(▲ 임시 아이템)
강좌에선 간단하게 체크가 되는지 확인만 할것이라 위와 같은 형태로 표시하겠지만,
여러분은 어느정도 모습을 갖춘 모델로 표시하도록 하세용.
먼저 텍스쳐로 사용할 이미지를 배경이미지(back_item)로 준비하도록 해요.
(▲ 아이템 텍스쳐)
그리고 Draw 이벤트를 추가하고, 모델을 표시하도록 합시다.
★ obj_item - Draw 이벤트 draw_set_color(color);//카메라(플레이어)에서 체크했을때 색을 혼합시킴 draw_set_alpha(1); texid=background_get_texture(back_item);//텍스쳐 d3d_transform_add_translation(x,y,z+1); d3d_draw_floor(-8,-8,0,8,8,0,texid,1,1);//아이템 표시 d3d_transform_set_identity(); draw_set_color(c_white);//혼합시켰던 색을 다시 기본 값으로 되돌림. color=c_white;//체크 혼합색 초기화 |
이것은 카메라(플레이어)로부터 체크가 되었을 때, color 변수 값에 따라 모델을 체크되었는지 식별이
가능하도록 어떠한 색을 혼합시켜 표시할 것이고, 그렇지 않을 경우는 원래 모습으로 표현할 것입니다.
(▲ color값에 따른 아이템 체크 표현)
이제 카메라 오브젝트, 그러니까 플레이어에서 이 아이템을 체크하게 하면 되는 것입니다.
먼저 체크할 스크립트를 하나 만듭시다.
★ 스크립트 - place_3d_inst_ext //place_3d_inst_ext(obj,x,y,zmin,zmax); var _obj,it,i,n,_x,_y,_z1,_z2,_zc,_on,_d1,_d2,_inst; _obj=argument0; _x=argument1; _y=argument2; _z1=argument3; _z2=argument4; n=instance_number(_obj); _on=0; _inst=noone; if !(collision_point(_x,_y,_obj,1,1)=noone){ for(i=0;i<n;i+=1;){it=instance_find(_obj,i); if !(collision_point(_x,_y,it,1,1)=noone){ //--------------------------- _zmin=it.z; _zmax=it.z+it.ztop; _d1=abs(_z2-_z1); _d2=abs((_zmax)-_zmin); if _d1<=_d2{ _zc=_z1+(_d1/2); if (_zmin<_z1 && _zmax>_z1) || (_zmin<_z2 && _zmax>_z2) || (_zmin<_zc && _zmax>_zc){ _on=1;_inst=it;break;} } else{ _zc=_z1+(_d2/2); if (_z1<_zmin && _z2>_zmin) || (_z1<_zmax && _z2>_zmax) || (_zmin<_zc && _zmax>_zc){ _on=1;_inst=it;break;} } //--------------------------- }} } return _inst; |
이 스크립트는 이전에도 만들어 보셨죠.
좌표만 따로 입력할 수 있게 만든 place_3d_inst 의 확장 스크립트입니다.
place_3d_inst_ext(obj,x,y,zmin,zmax)
obj : 충돌 대상
x, y : 현재 좌표
zmin : 현 오브젝트 z좌표의 최소값
zmax : 현 오브젝트 z좌표의 최대값
(▲ 스크립트의 체크 방식)
이전 스크립트와 마찬가지로 충돌하는 블럭 중 높이별로 3등분하여 어느 한쪽이라도 걸린다면
그 블럭의 ID를 반환하는 스크립트입니다.
강좌에서 아이템 체크는 아래와 같은 방식으로 체크 할 것입니다.
(▲ 아이템 체크 방식)
이것은 카메라(obj_cam)으로 부터 아이템 체크 가능한 거리를 여러개로 나누어 분기별로 조금씩
이동하면서 체크하는 방식입니다.
카메라 오브젝트(obj_cam)으로 이동해서, Draw 이벤트 끝에 아이템 체크 이벤트를 추가 작성하도록
합시다.
★ obj_cam - Draw 이벤트 //체크 가능한 거리는 64, 카메라로부터 2씩 보는 방향으로 이동하며 체크 for(i=0;i<64;i+=2;){ _x=x+lengthdir_x(lengthdir_x(i,cam_yang),cam_zang); _y=y+lengthdir_y(lengthdir_x(i,cam_yang),cam_zang); _z=z+eye-lengthdir_y(i,cam_yang); aa=place_3d_inst_ext(obj_item,_x,_y,_z-1,_z+1);//아이템 체크 if !(aa=noone){//아이템이 있는가? with(aa){color=c_red;}//해당 아이템의 color변수를 빨간색으로 설정하고 반복문을 빠져나감 break;} } |
이것은 체크 가능한 거리가 64이고, 카메라로부터 2씩 보는 방향으로 이동하면서 아이템이 있는지
체크하는 것입니다.
그리고 만약 아이템을 체크 가능한 거리안에 있다면, 그 아이템의 color변수를 c_red(빨간색)으로
설정하게 되지요.
그렇게 되면 체크되는 동안 해당 아이템은 빨간색으로 혼합되어 표시될 것입니다.
(▲ 아이템 체크)
와우! 아이템 체크가 끝났습니다.
제대로 되는지 아이템을 룸에 배치하고, 테스트 해보도록 해요.
◈ 계단 이동(obj_stair8)
다음은 계단 이동에 대해 알아보도록 합시다.
(▲ 계단 이동 가능한 블럭)
계단 이동은 위와 같이 높이가 높을 때는 점프하지 않는 이상 이동하지 못하고, 계단과 같이 올라갈 수 있는
정도의 낮은 높이라면 이동시킬 겁니다.
강좌에서 올라갈 수 있는 높이는 10정도로 낮은 높이일 때 올라갈 수 있도록 하겠습니다.
일단 일반 블럭과 구분하기 쉽게 높이가 낮은 블럭 오브젝트(obj_stair8)를 따로 만들도록 합시다.
그리고 Parent에 obj_block 을 지정합니다.
(▲ 계단 오브젝트)
그리고 Create 이벤트를 추가하고, 높이에 대한 변수를 선언하도록 해요.
★ obj_stair8 - Create 이벤트 z=0; ztop=8;//올라갈 수 있는 높이인 10보다 작게 높이를 설정 |
Draw 이벤트를 추가하고, 계단 모양의 모델을 표시하도록 합시다.
강좌에서는 블럭과 같은 모양이지만, 높이만 낮게 설정할 것입니다.
★ obj_stair8 - Draw 이벤트 draw_set_color(c_white); draw_set_alpha(1); texid=background_get_texture(back_floor); d3d_transform_add_translation(x,y,z); d3d_draw_block(0,0,0,32,32,8,texid,1,1); d3d_transform_set_identity(); |
다음은 카메라 오브젝트(obj_cam)로 이동해서 Step 이벤트에 계단을 인식하도록 이벤트를 추가해야
합니다.
★ obj_cam - Step 이벤트 spd=2; dir=cam_zang; key_pressed=0; if keyboard_check(ord("A")){dir=cam_zang+90; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} if keyboard_check(ord("D")){dir=cam_zang-90; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} if keyboard_check(ord("W")){dir=cam_zang; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} if keyboard_check(ord("S")){dir=cam_zang+180; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} zspeed-=0.3; if zspeed<-8{zspeed=-8;} if keyboard_check_pressed(vk_space){if jump=0{zspeed=6;jump=1;}} //--------------------------- zmin=0; n=instance_number(obj_block); for(k=0;k<n;k+=1;){it=instance_find(obj_block,k); aa=instance_place(x,y,it); if instance_exists(aa){ //---------------▼ 이벤트를 삭제해야 하는 부분 //if z>=aa.z+aa.ztop{if zmin<=aa.z+aa.ztop{zmin=aa.z+aa.ztop;}} //---------------▲ 이벤트를 삭제해야 하는 부분 //---------------▼ 이벤트 추가 //계단 if abs((aa.z+aa.ztop)-zmin)<10 && aa.z+aa.ztop>z{ //올라갈 수 있는 블럭의 높이가 10정도 인가? if z<aa.z+aa.ztop{zspeed=2;}else{z=aa.z+aa.ztop;} //2정도의 속도로 짧게 점프해 올라감 } //---------------▲ 이벤트 추가 //일반 블럭 if z>=aa.z+aa.ztop{if zmin<=aa.z+aa.ztop{zmin=aa.z+aa.ztop;}} i=1;repeat(ztop){if aa.z+aa.ztop>z+i && aa.z<z+i{ x=xprevious;y=yprevious; if key_pressed=1{ x+=lengthdir_x(spd,dir)*!(place_meeting(x+lengthdir_x(spd,dir),y,aa)); y+=lengthdir_y(spd,dir)*!(place_meeting(x,y+lengthdir_y(spd,dir),aa)); } break;}i+=1;} i=0;repeat(ceil(abs(zspeed))+1){ if zspeed>0{if (aa.z>z+ztop+i-1 && aa.z<=z+ztop+i){z=aa.z-ztop;zspeed=-0.3;break;}} if z+i-1>=aa.z+aa.ztop && z+i>=aa.z+aa.ztop-2{if zmin<=aa.z+aa.ztop{ zmin=aa.z+aa.ztop;break;}} if zspeed<0{i-=1;}else{i+=1;}} } } //--------------------------- z+=zspeed; if z<=zmin{z=zmin;zspeed=0;jump=0;} |
이것과 같이 이전 강좌의 내용중 수정하거나 추가해야할 부분이 있습니다.
if z>=aa.z+aa.ztop{if zmin<=aa.z+aa.ztop{zmin=aa.z+aa.ztop;}}
중간에 위와 같은 부분이 있는데 이 부분을 삭제하고,
//▼ 계단식 이동으로 수정 ▼ if abs((aa.z+aa.ztop)-zmin)<10 && aa.z+aa.ztop>z{ //올라갈 수 있는 블럭의 높이가 10정도 인가? if z<aa.z+aa.ztop{zspeed=2;}else{z=aa.z+aa.ztop;} //2정도의 속도로 짧게 점프해 올라감 } |
이렇게 변경해야합니다.
이것은 이동할 때 블럭에 올라갈 수 있는 10 높이인지 체크하여, 올라갈 수 있는 높이라면 짧게
점프를 하여 조금씩 올라가게 하는 것입니다.
의외로 간단하죠. 굳!
만약 올라갈수 있는 높이를 10보다 크게 하고 싶다면, 강좌에서 설정한 10 대신 여러분이 원하시는
높이로 설정하고, zspeed값을 좀 더 크게 잡으시면 될 거에요.
이제 블럭위에 있을때 여러 블럭을 체크하는 것이 필요해요.
왜냐하면 이동할 수 있는 블럭인지, 아니면 이동할 수 없는 블럭인지 구별해야 블럭에 끼이지 않기
때문이죠.
일단 블럭체크에 대한 스크립트를 하나 추가해야 합니다.
★ 스크립트 - place_3d_obj //place_3d_obj(obj,zmin,zmax); var _obj,i,_z1,_z2,_zc,_d1,_d2,_inst; _obj=argument0; _z1=argument1; _z2=argument2; _inst=0; if instance_exists(_obj){ if place_meeting(x,y,_obj){ //--------------------------- _zmin=_obj.z; _zmax=_obj.z+_obj.ztop; _d1=abs(_z2-_z1); _d2=abs((_zmax)-_zmin); if _d1<=_d2{ _zc=_z1+(_d1/2); if (_zmin<_z1 && _zmax>_z1) || (_zmin<_z2 && _zmax>_z2) || (_zmin<_zc && _zmax>_zc) {_inst=1;} } else{ _zc=_z1+(_d2/2); if (_z1<_zmin && _z2>_zmin) || (_z1<_zmax && _z2>_zmax) || (_zmin<_zc && _zmax>_zc) {_inst=1;} } //--------------------------- }} return _inst; |
엇! 이전에 만든 place_3d_inst 스크립트와 비슷하지요.
place_3d_inst 에서는 collision_point를 사용하여 점으로 체크하게 했지만, 이것은 place_meeting으로
현재 카메라 지정된 마스크를 사용해 블럭과 체크하는 것입니다.
이 스크립트는 해당 오브젝트와 충돌하게 되면 1을 반환하게 되고, 그렇지 않으면 0을 반환합니다.
place_3d_obj(obj,zmin,zmax)
obj : 충돌 대상
zmin : 현 오브젝트 z좌표의 최소값
zmax : 현 오브젝트 z좌표의 최대값
이제 이 스크립트를 이용해 Step 이벤트에 아래와 같이 블럭 체크하는 부분을 추가합시다.
★ obj_cam - Step 이벤트 spd=2; dir=cam_zang; key_pressed=0; if keyboard_check(ord("A")){dir=cam_zang+90; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} if keyboard_check(ord("D")){dir=cam_zang-90; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} if keyboard_check(ord("W")){dir=cam_zang; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} if keyboard_check(ord("S")){dir=cam_zang+180; x+=lengthdir_x(spd,dir)*place_free(x+lengthdir_x(spd,dir),y); y+=lengthdir_y(spd,dir)*place_free(x,y+lengthdir_y(spd,dir));key_pressed=1;} zspeed-=0.3; if zspeed<-8{zspeed=-8;} if keyboard_check_pressed(vk_space){if jump=0{zspeed=6;jump=1;}} //--------------------------- zmin=0; n=instance_number(obj_block); for(k=0;k<n;k+=1;){it=instance_find(obj_block,k); aa=instance_place(x,y,it); if instance_exists(aa){ //계단 //if z>=aa.z+aa.ztop{if zmin<=aa.z+aa.ztop{zmin=aa.z+aa.ztop;}} if abs((aa.z+aa.ztop)-zmin)<10 && aa.z+aa.ztop>z{ if z<aa.z+aa.ztop{zspeed=2;}else{z=aa.z+aa.ztop;} } //일반 블럭 if z>=aa.z+aa.ztop{if zmin<=aa.z+aa.ztop{zmin=aa.z+aa.ztop;}} i=1;repeat(ztop){if aa.z+aa.ztop>z+i && aa.z<z+i{ x=xprevious;y=yprevious; if key_pressed=1{ x+=lengthdir_x(spd,dir)*!(place_meeting(x+lengthdir_x(spd,dir),y,aa)); y+=lengthdir_y(spd,dir)*!(place_meeting(x,y+lengthdir_y(spd,dir),aa)); } break;}i+=1;} //---------------▼ 이벤트 추가 if (place_3d_obj(aa,z,z+ztop)=1){x=xprevious;y=yprevious;} //블럭에 충돌하면 멈춤(이동했다면 이전 좌표로 되돌아감) //---------------▲ 이벤트 추가 i=0;repeat(ceil(abs(zspeed))+1){ if zspeed>0{if (aa.z>z+ztop+i-1 && aa.z<=z+ztop+i){z=aa.z-ztop;zspeed=-0.3;break;}} if z+i-1>=aa.z+aa.ztop && z+i>=aa.z+aa.ztop-2{ if zmin<=aa.z+aa.ztop{zmin=aa.z+aa.ztop;break;} } if zspeed<0{i-=1;}else{i+=1;}} } } //--------------------------- z+=zspeed; if z<=zmin{z=zmin;zspeed=0;jump=0;} |
설명은 길었지만, 블럭 충돌 관련 이벤트 한줄만 추가하면 됩니다. 굳!
이것은 이동할 수 없는 블럭에 충돌했을 때 멈추고, 이동했을 경우는 이동하기 이전 좌표로 되돌리는
것 이에요.
그러면 실제로 이동하다 블럭에 충돌했을 때 이동하지 못하는 곳일 경우 멈추게 되는 것처럼
보이는거죠.
와우! 드디어 계단 이동이 완성되었습니다.
제대로 작동이 되는지 계단을 룸에 배치하고 테스트 해보도록 해요.
[참고]
일반적으로 룸에 높이별로 블럭을 직접 배치해도 되지만, 강좌에서는 룸 설정탭의 Creation Code통해
코드로 배치했습니다. Creation Code는 룸이 시작할때 실행되는 이벤트입니다.
★ 룸 Creation Code i=0; repeat(10){ it=instance_create(128+(i*32),320,obj_stair8); it.z=i*8; i+=1;} |
이것은 10개의 블럭을 (128, 320) 좌표에서 오른쪽으로, z값을 8씩 추가하며, 배치하는 겁니다.
물론 블럭을 z값을 따로 설정하고 만들어, 룸에 직접 배치해도 됩니다.
(▲ 테스트 화면)
이번 강좌는 간단했죠.
강좌에서는 간단하게 표현했지만, 여러분은 좀 더 멋진 게임을 만드실 수 있을 것이라 생각합니다.
--------- 예 제 ---------
'GameMaker강좌[GM8] > 3D기능강좌' 카테고리의 다른 글
[게임메이커강좌-3D 강좌]간단한 FPS게임 만들기-4-대쉬 기능 (32) | 2014.01.23 |
---|---|
[게임메이커강좌-3D 강좌]3D 플랫폼 게임 만들기-2-적 유닛 추가 (39) | 2013.08.12 |
[게임메이커강좌-3D 강좌]3D 플랫폼 게임 만들기-1-시점 설정 (31) | 2013.08.12 |
[게임메이커강좌-3D 강좌]간단한 FPS게임 만들기-2-게임 구성 (118) | 2013.05.31 |
[게임메이커강좌-3D 강좌]간단한 FPS게임 만들기-1-시점 구성 (51) | 2013.05.30 |
댓글