본문 바로가기
GameMaker강좌[GM8]/3D기능강좌

[게임메이커강좌-3D 강좌]간단한 FPS게임 만들기-1-시점 구성

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

 

 

이전 강좌에서 간단한 3D게임을 만들어 보았죠.
게임메이커로 화려한 3D 게임은 힘들지만, 아주 간단한 3D 게임은 만들 수 있답니다.
이번엔 좀 더 어려운 1인칭 시점의 게임인 FPS게임을 한번 만들어보도록 합시다.

 

 

(▲강좌에서 만들게 될 FPS 게임)

 

FPS는 만들기가 매우 어려운 쪽에 속하지만, 만들어보고 이해한다면 다른 어떤 게임을 만들더라도 많은

도움이 된 답니다.

 

 

 

 

 


◈ FPS의 시점(obj_cam)

 


이전 강좌에서도 해보았지만, 시점을 만드려면 아래와 같은 함수를 사용해야합니다.


     d3d_set_projection(xfrom,yfrom,zfrom,xto,yto,zto,xup,yup,zup)

 

 

(▲3D의 시점)


먼저 카메라용 오브젝트(obj_cam)를 하나 만듭니다.

그리고 Sprite 에 마스크 용으로 사용할 스프라이트 이미지를 지정해줍시다.

 

 

(▲3D 카메라 오브젝트를 만듭시다)


그리고 다른 오브젝트보다 이벤트들을 먼저 실행시키기 위해 depth를 높게 설정해줍시다.
여기선 한 99999정도로 해보겠습니다.
3D의 기능을 활성화하기 위해 Create 이벤트를 추가하고, 아래와 같은 코드를 입력합니다.

 

 
      ★ obj_cam - Create이벤트

      d3d_start();



게임을 종료했을 때 3D기능을 종료해야겠지요. Game End 이벤트를 추가합니다.

 

 
     ★ obj_cam - Game End이벤트

     d3d_end();



이제 시점을 설정해봅시다.
먼저 시점에 필요한 변수들을 Create 이벤트에서 선언합니다.

 

 
      ★obj_cam - Create이벤트

      cam_zang=0;//카메라 좌우 각도
      cam_yang=0;//카메라 상하 각도
      cam_dis=128;//목표 시점과의 거리

      z=0;//z좌표
      eye=25;//눈 높이



시점 대해 생각해봅시다.
마우스을 좌우로 움직이면 화면이 좌우로 움직이고, 상하로 움직이면 화면이 상하로 따라 움직이게

해야합니다. 그리고 시점이 될 높이 또한 생각해야 하지요.
또한 바닥에 위치하게 되거나 너무 높이 있으면 제대로 보이지 않기 때문에 안됩니다.
아무튼 여러가지를 상황을 고려해야 해요.

Draw이벤트를 추가하고, 아래와 같이 시점을 설정합시다.

 

 
     ★ obj_cam - Draw이벤트

     _x=x+lengthdir_x(lengthdir_x(cam_dis,cam_yang),cam_zang);
     _y=y+lengthdir_y(lengthdir_x(cam_dis,cam_yang),cam_zang);
     _z=z-lengthdir_y(cam_dis,cam_yang);//카메라를 상하-좌우회전치만큼 좌표를 설정함.

     d3d_set_projection(x,y,z+eye,_x,_y,_z+eye,0,0,1);



시점은 눈높이가 되는 적당한 지점을 기준으로 설정합시다.

강좌에서는 z축으로 25정도의 높이에서 보게 될 것입니다.

이제 시점은 되었지만, 이것을 제어해야합니다.
End Step 이벤트를 추가하고 다음과 같은 코드를 입력합니다.

 

 
     ★ obj_cam - End Step이벤트

     //기본적으로 필요한 변수 선언
     var vw,vh,mx,my,_x,_y;
     vw=window_get_width();//현재 윈도우의 넓이
     vh=window_get_height();//현재 윈도우의 높이
     mx=mouse_x;//마우스의 x좌표
     my=mouse_y;//마우스의 y좌표
     _x=vw/2;//윈도우의 가운데 x좌표
     _y=vh/2;//윈도우의 가운데 y좌표

     //설정
     spd=3;
     d=min(abs(_x-mx),16)/16 //마우스 포인터가 좌우로 흔들리는 값을 적당하게 분배함.

     if _x<mx{cam_zang-=spd*d;}
     if _x>mx{cam_zang+=spd*d;}//d의 값으로 좌우회전 각도를 설정함.

     d=min(abs(_y-my),16)/16 // 마우스 포인터가 상하로 흔들리는 값을 적당하게 분배함.

     if _y>my{if cam_yang<80{cam_yang+=spd*d;}}//정면에서 80각도까지만 올려다 볼 수 있게 함.
     if _y<my{if cam_yang>-80{cam_yang-=spd*d;}}//d의 값으로 상하회전 각도를 설정함.

     window_views_mouse_set(vw/2,vh/2);//마우스 포인터를 화면 중앙에 위치하게 함.



위와 같은 설정을 하게 되면, 마우스 포인터를 화면 가운데 위치한 상태에서 흔들었을때,

마우스 포인터가 이리저리 흔들리게 되는 것을 보실수 있을 겁니다.
이 마우스 포인터가 움직이는 거리만큼 값을 조절하여, 마우스를 약간 움직이면 카메라도 약간만

회전하고, 많이 움직이면 카메라도 많이 회전하도록 회전치를 설정하는 것입니다.

 

 

 

 

[참고]게임메이커 스튜디오 사용자에 대한 설정

 

게임메이커 스튜디오 사용자는 아마 위쪽 설정이 안될 것입니다.

게임메이커 스튜디오에서 window_views_mouse_set 함수는 폐기되어 더 이상 사용할 수 없기

때문이죠. 하지만 window_mouse_set를 대체 사용할 수 있으니 걱정하지 마세요.

게임메이커 스튜디오에서의 설정은 아래와 같습니다.

 

 

 

 

 

 
     ★ obj_cam - End Step이벤 [게임메이커 스튜디오]

     //기본적으로 필요한 변수 선언
     var vw,vh,mx,my,_x,_y;


     //-----------------▼ 수정



     vw=view_wview;//현재 뷰의 넓이
     vh=view_hview;//현재 뷰의 높이



     //-----------------▲ 수정


     mx=mouse_x;//마우스의 x좌표
     my=mouse_y;//마우스의 y좌표
     _x=vw/2;//윈도우의 가운데 x좌표
     _y=vh/2;//윈도우의 가운데 y좌표

     //설정
     spd=3;
     d=min(abs(_x-mx),16)/16 //마우스 포인터가 좌우로 흔들리는 값을 적당하게 분배함.

     if _x<mx{cam_zang-=spd*d;}
     if _x>mx{cam_zang+=spd*d;}//d의 값으로 좌우회전 각도를 설정함.

     d=min(abs(_y-my),16)/16 // 마우스 포인터가 상하로 흔들리는 값을 적당하게 분배함.

     if _y>my{if cam_yang<80{cam_yang+=spd*d;}}//정면에서 80각도까지만 올려다 볼 수 있게 함.
     if _y<my{if cam_yang>-80{cam_yang-=spd*d;}}//d의 값으로 상하회전 각도를 설정함.





     //-----------------▼ 수정

     window_mouse_set(window_get_width() / 2, window_get_height() / 2)

     //마우스 포인터를 화면 중앙에 위치하게 함.


     //-----------------▲ 수정


몇 가지만 수정하면 정상적으로 표시될 것 입니다.

 

 

 

 

 

 


와우~! 드디어 FPS의 시점이 완성되었습니다.
테스트를 위해 벽같은 배경들을 간단하게 구성하고 제대로 실행되는지 확인해봅시다.

 

 



◈간단한 배경 구성

   (obj_map, obj_wall_h, obj_wall_v)

 


배경으로 사용할 모델의 텍스쳐 이미지를 구성합시다.

 

 

(▲배경이미지에 텍스쳐를 준비)

 

먼저 바닥을 설정하기 위해 오브젝트(obj_map)를 하나 만듭니다.
Draw 이벤트를 추가하고, 바닥으로 사용할 모델을 입력합니다.

 

 
     ★ obj_map - Draw 이벤트

     draw_set_alpha(1);
     draw_set_color(c_white);

     texid=background_get_texture(back_floor);

     d3d_draw_floor(0,0,0,room_width,room_height,0,texid,20,15);



강좌에선 간단하게 룸 넓이만큼 그려보도록 합시다.

다음은 벽을 구성해볼까요?
벽은 여러가지 벽이 있을 수 있으니 간단하게 통합적으로 처리하기 위해 parent오브젝트 먼저 만듭시다.
그리고 하위 오브젝트를 만듭니다.

     obj_block(parent) - obj_wall_h,obj_wall_h(하위 오브젝트)

먼저 가로벽을 만들어 보아요.
오브젝트(obj_wall_h)를 하나 만들고 Draw 이벤트를 추가한 다음 아래와 같이 설정합니다.

 

 
     ★ obj_wall_h - Draw 이벤트

     draw_set_alpha(1);
     draw_set_color(c_white);

     texid=background_get_texture(back_wall);

     d3d_transform_add_translation(x,y,0);
     d3d_draw_wall(0,0,32*10,32,0,0,texid,1,10);
     d3d_transform_set_identity();



눈높이가 25정도이니 위와 같이 설정하면 꽤나 높겠죠? 헤헤

이 오브젝트를 플레이어가 통과하지 못하도록 오브젝트의 Solid를 체크하도록 합시다.

다음은 세로벽입니다.
마찬가지로 오브젝트(obj_wall_v)를 하나 만들어 Solid를 체크하고, Draw 이벤트를 추가한 다음

아래와 같이 설정합니다.

 

 
     ★ obj_wall_v - Draw 이벤트

     draw_set_alpha(1);
     draw_set_color(c_white);

     texid=background_get_texture(back_wall);

     d3d_transform_add_translation(x,y,0);
     d3d_draw_wall(0,0,32*10,0,32,0,texid,1,10);
     d3d_transform_set_identity();


 

가로 벽과 비슷한 높이의 세로벽 생겼네요.

일단 테스트 용으로 배경을 간단히 만들었으니, 다음은 크로스 헤어와 같은 2D를 화면에 표시하는

방법에 해 알아보도록 해요.




 

 


◈ 화면에 2D 정보 표시(obj_screen)

 


3D화면에 2D를 표시할 때는 아래와 같은 함수를 사용합니다.

     d3d_set_projection_ortho(x,y,w,h,angle)

이 함수를 이용하여 아래와 같은 크로스 헤어를 표시해볼까요.

 

 

(▲화면 가운데 크로스 헤어를 표시)


표시하고 싶은 크로스 헤어를 스프라이트 이미지(spr_cross)로 만들도록 해요.

그리고 이 크로스 헤어와 같이 2D 이미지 또는 텍스트를 표시할 오브젝트(obj_screen)를 하나 만듭시다.
이 오브젝트는 depth를 다른 오브젝트들보다 매우 낮게 설정해야 3D와 2D가 제대로 표시됩니다.
Draw 이벤트를 추가하고 아래와 같이 준비한 크로스 헤어 이미지를 표시합니다.

 

 
     ★ obj_screen - Draw 이벤트

     var vw,vh;
     vw=view_wview;//뷰의 넓이
     vh=view_hview;//뷰의 높이
     d3d_set_projection_ortho(0,0,vw,vh,0);

     draw_sprite_ext(spr_cross,0,vw/2,vh/2,1,1,0,c_white,0.8);//이미지를 화면 가운데 표시함.



그리고 화면에 마우스 포인터가 남아 있기 때문에, 이것을 보이지 않게 해야합니다.
마우스 포인터는 Global Game Settings - Graphics탭에서 Display the cursor를 체크해제하면
마우스 포인터를 감출 수 있습니다.

하지만 게임 상에 포인터를 표시할 경우가 생길 수 있기 때문에 아래와 같은 함수를 알고 있으면 좋습니다.

     window_set_cursor(cr_none);//커서 없음
     window_set_cursor(cr_default);//커서 표시

어디에서 설정해도 되지만, 강좌에선 카메라에서 설정해보도록 하겠습니다.
카메라의 Create 이벤트에 아래와 같이 추가합니다.

 

 
     ★ obj_cam - Create 이벤트

     window_set_cursor(cr_none);//커서 없음.


 

이렇게 하면 마우스 포인터가 게임 화면에서 보이지 않게 됩니다.

 

 

 

 

 

 

 


◈ 룸에 오브젝트 배치 및 테스트

 

 

와우! 어느정도 준비가 되었으니 다음은 작동이 잘 되는지 테스트해보아요.

 

 

 

(▲룸에 배치)

 

지금 까지 구성한 오브젝트들을 룸에 배치하고, 제대로 실행되는지 확인해봅시다.

 

 

 

 

 

 

 

------- 응용예제 ------

 

 

fpsX1-1.gmk
다운로드

 

fpsX1-1.exe
다운로드

 

 

 

 

 

 

300x250

댓글