21. Lines, Antialiasing, Timing, Ortho View And Simple Sounds

ㅂ 
[ Nehe 21장 번역중] - [조진현] -
 
21번째 OpenGL 튜토리얼에 온 것을 환영합니다.
먼저 이번 튜토리얼의 화제( topic )들은 무척 어려웠다는 것을 알려드립니다.
저는 기본기를 배우고 있는 여러분들이 무척 힘들고 지쳐있다는 것을 알고 있습니다.
누구나 3차원 오브젝트들이나 멀티 텍스쳐링과 같이 화려하고 멋진 요소들을 배우고 싶어합니다.
이런 분들에게는 죄송한 얘기지만, 저는 여러분들이 너무 조바심을 내지 않기를 바랍니다.
일전에 저는 이 조바심을 견디지 못해서 화려한 기술을 배우려 앞서 나갔던 적이 있었는데,
다시 기초적인 부분을 배우려 뒷쪽으로 돌아오는 것이 쉽지 않았습니다.
그래서 저는 일정한 페이스를 유지하면서, 앞으로 전진해 나갈 것입니다.
 
저는 몇몇의 것들에 대해서 잊고 있었습니다.
저는 이번 튜토리얼을 작성하면서 느낀 점을 약간 얘기해보려 합니다.
지금까지 저의 모든 튜토리얼은 폴리곤, 사각형, 삼각형을 사용했었습니다.
그래서 저는 이번에 선(Line) 에 대한 튜토리얼을 작성하기로 생각했었습니다.
선에 대한 튜토리얼을 작성을 시작한지 얼마지나지 않아서,
저는 이 작업을 중단하기로 했었습니다.
사실, 이번 튜토리얼에서 선을 주제로 선태한 것은 아주 좋은 선택이였습니다.
하지만 그것은 너무 지루했었습니다.
그래서 저는 여러분들이 선들에 대해서 학습할 때, 더 재미있게 만들어 보고 싶었습니다.
저는 이메일이나 게시판 등을 통해서 튜토리얼에 요청 사항이나 개선점에 대해서 듣고 있습니다.
그래서 이들에 대한 요구 사항을 조금이라도 만족시키기 위해서,
이번 튜토리얼은 여러가지 주제를 담아서 진행하기로 결정했습니다.
 
여러분들은 이번 튜토리얼에서 선(Line), 안티 앨리어싱(Anti-Alasing), 직교투영(Orthographic Projection),
시간처리(Timing), 기본 사운드 효과들, 그리고 마지막으로는 간단한 게임 로직에 대해서
배울 수 있을 것입니다.
이번 튜토리얼을 통해서 보다 많은 사람들이 만족해서 행복해졌으면 좋겠습니다.
저는 이번 튜토리얼에 이틀을 코딩 작업을 위해서 보냈고, 2주에 가까운 시간을 HTML 파일 작성에 보냈습니다.
이런 저의 노력을 여러분들이 즐겨주기를 바란다.
 
이 튜토리얼의 마지막에 여러분들은 '땅따먹기(amidar)' 형태의 게임을 제작하게 될 것입니다.
이 게임에서 당신은 악당들을 피해서 자신의 그리드( grid ) 영역을 채우는 것입니다.
이 게임에는 레벨, 스테이지, 생명, 사운드, 그리고 게임 진행 중에 어려울 때 도움을 주는
비밀 아이템의 개념들을 사용합니다.
이 게임은 펜티엄 166 과 부두 2 그래픽 카드에서 잘 실행될 것이지만,
조금 더 부드러운 애니메이션 효과를 느끼고 싶다면, 더 좋은 프로세서들을 추천 드립니다.
 
이번에 작성된 코드는 Lesson 1 를 기반으로 작성되었습니다.
우리는 파일 연산을 위해서 stdio.h 헤더 파일을 추가하고,
현재 점수나 현재 스테이지에 대한 변수들을 스크린에 표시하기 위해 stdarg.h를 추가합니다.
 
// This Code Was Created By Jeff Molofee 2000
// If You've Found This Code Useful, Please Let Me Know.

#include	<windows.h>	// 윈도우즈용 헤더파일
#include	<stdio.h>	// 표준 입축력용 헤더파일
#include	<stdarg.h>	// 가변 변수용 헤더파일
#include	<gl\gl.h>       // OpenGL32 라이브러리 헤더파일
#include	<gl\glu.h>	// GLu32 라이브러리 헤더파일
#include	<gl\glaux.h>	// Glaux 라이브러리 헤더파일

HDC		hDC=NULL;	// GDI 컨텍스트
HGLRC		hRC=NULL;	// 렌더링 컨텍스트
HWND		hWnd=NULL;	// 윈도우 핸들을 저장
HINSTANCE	hInstance;	// 애플리케이션 인스턴스를 저장
 
이제 우리는 부울(boolean) 변수를 세팅합니다.
vline 이란 변수는 우리의 게임에 사용하는 121개의 수직선들을 저장하기 변수입니다.
11개의 선들은 ???????????????
hline 변수는 게임의 121개의  수평선들을 저장하기 위한 변수입니다.
우리는 ap 라는 변수를 통해서 'A' 키가 눌러졌는지 여부를 계속 추적할 것입니다.
 
filled 변수는 그리드(grid)가 채워지지 않았다면 FALSE 이고, 워졌다면 TRUE 입니다.
gameover 변수는 변수 이름에서도 알 수 있듯이 아주 명확합니다.
이 변수는 TRUE이면 게임이 종료되어 버립니다.
그 이외의 상태이면 플레이 중인 상태를 의미합니다.
anti 변수가 TRUE 이면, 오브젝트 안티-앨리어싱(anti-aliasing)이 활성화된 것을 의미하고,
그렇지 않으면 비활성화된 상태를 의미합니다.
active 변수는 여러분이 만든 윈도우의 활성화 여부를 추적하고,
fullscreen 변수는 윈도우 애플리케이션이 현재 전체화면( fullscreen ) 형태로 실행되고 있는지,
혹은 윈도우 창 모드 형태로 실행되고 있는지를 체크합니다.
 
 
bool		keys[256];	// Array Used For The Keyboard Routine
bool		vline[11][10];	// Keeps Track Of Verticle Lines
bool		hline[10][11];	// Keeps Track Of Horizontal Lines
bool		ap;		// 'A' Key Pressed?
bool		filled;		// Done Filling In The Grid?
bool		gameover;	// Is The Game Over?
bool		anti=TRUE;	// Antialiasing?
bool		active=TRUE;	// Window Active Flag Set To TRUE By Default
bool		fullscreen=TRUE;// Fullscreen Flag Set To Fullscreen Mode By Default
 
 
 이제 우리는 정수형 변수들에 대한 설정을 할 차례입니다.
만약에 하나의 적이 우리와 충돌했다면, 이들의 충돌 지점을 체크하기 위해서 loop1 과 loop2 변수는 격자들의 체크 지점들을 위해서 사용할 것입니다. loop1과 loop2 변수가 변하게 된다면 프로그램 상에서 변화를 보게 될 것입니다.
delay 변수는 적들의 공격에 의해서 시간을 낮추기 위한 것입니다.
만약 delay 변수가 주어진 값보다 크다면, 적들이 이동되어지고 다시 0으로 설정됩니다.
 
adjust 변수는 매우 특별한 역할을 하는 변수입니다.
비록 이 프로그램이 타이머를 가지고 있지만, 이 타이머는 오직 당신의 컴퓨터가 너무 빠르게 동작하지 않도록 제어를 할 뿐입니다. 만약에 그렇다면, delay 변수는 컴퓨터를 느리게 하기 위한 목적으로 탄생되어 진 것입니다.( ??? )
 
나의 지포스 그래픽카드에서 이 프로그램은 무척이나 자연스럽게 동작했으며, 매우 쾌적한 성능을 보여줬습니다.
반면에 Vodoo 3500TV 기반의 펜티엄3/450 에서 테스트했을 때는 무척이나 느렸었습니다.
문제되었던 부분은 저의 시간을 제어하는 코드가 실제 플레이 자체를 느리게 만들었기 때문이였습니다.
그 문제를 해결하는 것은 플레이 스피드를 향상시키는 것이였습니다.
그래서 저는 새로운 변수가 필요하게 되었고, 그것을 adjust 라고 추가한 것입니다.
adjust 는 0~5 사이의 어떤 수치가 될 수 있습니다.
게임 상의 오브젝트들은 바로 이 adjust 의 수치에 의존해서 서로 다른 스피드로 움직입니다.
낮은 수치를 가진 오브젝트들은 시스템 상에서 천천히 자연스러운 움직임을 보여 줍니다.
그리고 3보다 크다면 오브젝트들은 더욱 빠른 움직임을 보여줍니다.
이것은 단지 낮은 시스템에서 자연스러운 움직임을 제어하는 쉬운 방법입니다.
한가지 유의할 사항은 아무리 빠른 오브젝트라고 해도 내가 의도한 움직임보다는 절대로 빨라질 수 없다는 것입니다.
그래서 adjust 값을 3으로 설정하는 것이 빠른 시스템과 느린 시스템에서 가장 안전합니다.
 
lives 변수는 당신의 게임 생명을 초반에 5로 설정하기 위해서 5로 초기화 합니다.
level 은 내부 변수입니다. 게임은 난이도의 설정을 위해서 이 변수를 사용합니다.
이것은 화면에 보여질 레벨이 아님을 주의하시기 바랍니다.
level2 변수는 level 과 같은 변수로 시작합니다만,
당신의 실력에 의해서 지속적으로 증가할 수도 있습니다.
만약 당신이 과거 level 3 에 의해서 게임을 다루었다면, level 변수는 3에서 증가를 멈출 것입니다.
level 변수가 게임의 난이도를 저장하고 있는 반면에, stage 변수는 현재 게임의 스테이지를 저장하고 있습니다.
 
 
 
 
 이제 우리는 게임에서 사용할 오브젝트 정보를 위한 구조체를 만들 것입니다.
우리는 X와 Y 위치를 위해서 fx, fy 변수를 멤버 변수로 선언합니다.
이 변수들은 플레이어와 적들을 주어진 격자(grid)에서 약간 분산되어서 움직이도록 할 것입니다.
 
부드럽게 이동하는 오브젝트를 만들기 위해서는 아래와 같이 합니다.
변수 x와 y 를 또 가지고 있습니다.
이 변수들은 플레이어의 격자 위치를 유지하는 변수입니다.
전체적으로 왼쪽에서 오른쪽으로 11개와 위에서 아래로 11개의 위치들이 있습니다.
그래서 x와 y의 범위는 0~10 사이입니다.
그렇기 때문에 fx와 fy 변수가 필요합니다.
만약에 격자(grid) 의 어느 부분에 이동을 한다고 가정할 때,
이 움직임은 스크린 상에서 매우 빠르게 표현되어 질 것입니다.
즉, 전혀 부드럽지 않을 것입니다.
 
오브젝트 구조체의 마지막 변수는 spin 입니다.
이것은 z축을 기준으로 회전을 위해서 사용되어질 것입니다.
 
 
 
이제 우리는 우리들의 플레이어, 적들을 표현할 수 있는 오브젝트 구조체를 만들었다.
이는 특별한 아이템과 같은 특수한 목적에도 충분히 사용할 수 있을만큼 기본적인 구조입니다.
 
 
아래의 첫번째 오브젝트 변수는 플레이어를 나타내는 player 입니다.
이 변수는 기본적으로 fx, fy, x, y, spin 변수를 가지고 있습니다.
이 변수를 선언함으로써 우리는 player.x를 통해서 플레이어의 x 위치에 접근할 수 있습니다.
또한 우리는 player.spin 에 특정 값을 설정함으로써 이를 변화시킬 수 있습니다.
 
두번째 오브젝트 변수는 꽤 다릅니다.
왜냐하면 게임 상에서는 최대 9개의 적들이 나타날 수 있기 때문입니다.
그래서 우리는 각각의 적들을 생성하기 위해서 오브젝트 형 변수들이 필요합니다.
이를 간단히 표현하기 위해서 9개의 적들을 나타내는 배열 형태로 관리 합니다.
첫번째 적의 x 위치에 접근하고 싶다면 enemy[0].x 형태로 사용하고,
두번째 적의 x 위치에 접근하고 싶다면 enemy[1].x 형태로 사요합니다.
 
마직만 오브젝트 변수는 우리의 특별 아이템을 위한 것입니다.
특별 아이템은 수시로 화면에 나타나게 될 모래시계입니다.
우리는 모래시계를 위해서 격자의 위치를 나타내는 x, y 변수가 필요합니다.
그러나 그 변수들은 모래시계들을 움직이게 하지 않습니다.
모래시계는 격자 주변으로 움직일 이유가 없습니다..
그렇기 때문에 fx와 fy는 사용하지 않겠지만, 이후의 특별한 목적을 위해 이 변수를 사용할 것입니다.
 
 
 
 
 
 
 
 
 
Comments