테트리스 ver 0.1 (8) - 소스코드 구현 (TetrisView)
[TetrisView 클래스의 Class Diagram]
이제는, 테트리스의 UI 를 담당하는 클래스인 TetrisView 에 대해서 말씀드릴 차례입니다. TetrisView.h 와 TetrisView.c 를 분석해 보겠습니다.
[TetrisView.h]
#ifndef _TETRIS_VIEW_H #define _TETRIS_VIEW_H #include "TetrisManager.h" typedef struct _tetrisView{ TetrisManager tetrisManager; }TetrisView; void TetrisView_StartGame(TetrisView* tetrisView); void TetrisView_ProcessGame(TetrisView* tetrisView, int processType, int direction); void TetrisView_EndGame(TetrisView* tetrisView); #endif
1 ~ 2, 14 라인
이 헤더파일을 include 하는 곳들에서 중복 포함 하지 않게 하기 위한 guard 입니다.
6 ~ 8 라인
TetrisView 구조체의 정의부입니다. 멤버로는 tetrisManager 를 가지고 있습니다.
10 ~ 12 라인
TetrisView.c 에서 정의될 함수들의 선언부입니다.
[TetrisView.c]
#include <stdio.h> #include <windows.h> #include <mmsystem.h> #include "TetrisView.h" #include "TetrisManager.h" #include "Constant.h" #pragma comment(lib, "winmm.lib") #define TETRIS_BACKGROUND_MUSIC_FILE_NAME "..\\res\\tetris_background_music.wav" void TetrisView_StartGame(TetrisView* tetrisView){ int speedLevel; PlaySound(TEXT(TETRIS_BACKGROUND_MUSIC_FILE_NAME), NULL, SND_ASYNC | SND_LOOP); printf("***** Tetris *****\nSpeed level (1 ~ 10) : "); scanf_s("%d", &speedLevel); if (speedLevel > MAX_SPEED_LEVEL || speedLevel < MIN_SPEED_LEVEL){ speedLevel = MIN_SPEED_LEVEL; } TetrisManager_Init(&tetrisView->tetrisManager, speedLevel); TetrisManager_Print(&tetrisView->tetrisManager); } void TetrisView_ProcessGame(TetrisView* tetrisView, int processType, int direction){ if (processType == DIRECTION){ TetrisManager_ChangeBoardByDirection(&tetrisView->tetrisManager, direction); } else if (processType == DIRECT_DOWN){ TetrisManager_ProcessDirectDown(&tetrisView->tetrisManager); } else if (processType == AUTO){ TetrisManager_ChangeBoardByAuto(&tetrisView->tetrisManager); } if (TetrisManager_IsReachedToBottom(&tetrisView->tetrisManager)){ //if you are going to move the block which has bottom wall or bottom fixed block, permit the block to move the direction if (processType == DIRECTION && direction == LEFT && (TetrisManager_CheckValidPosition(&tetrisView->tetrisManager, LEFT) == EMPTY) || processType == DIRECTION && direction == RIGHT && (TetrisManager_CheckValidPosition(&tetrisView->tetrisManager, RIGHT) == EMPTY)){ TetrisManager_ChangeBoardByDirection(&tetrisView->tetrisManager, direction); } if (TetrisManager_ProcessReachedCase(&tetrisView->tetrisManager) == END){ TetrisView_EndGame(tetrisView); } } TetrisManager_ProcessDeletingLines(&tetrisView->tetrisManager); TetrisManager_Print(&tetrisView->tetrisManager); if (processType == AUTO){ TetrisManager_Sleep(&tetrisView->tetrisManager); } } void TetrisView_EndGame(TetrisView* tetrisView){ PlaySound(NULL, 0, 0); system("cls"); printf("***** End *****\n%d level / %d lines deleted\n", tetrisView->tetrisManager.speedLevel, tetrisView->tetrisManager.deletedLineCount); system("pause"); exit(-1); }
1 ~ 6 라인
현재 소스 파일에서 필요한 헤더파일들을 include 합니다.
8 라인
소리 및 음악 재생을 위해서 winmm.lib 라이브러리를 로드합니다.
10 라인
테트리스 배경 음악 파일명을 상수화 합니다. (상대 경로 포함)
12 라인
TetrisView_StartGame 함수의 정의부입니다. 매개변수로 tetrisView 를 받아서, 테트리스 게임을 시작하기 위한 설정을 하고, 시작을 하는 역할을 합니다.
14 라인
PlaySound 함수를 호출하여 테트리스 배경음악을 재생합니다.
(소리 및 음악 재생하기 - WinApi 참고)
http://kkikkodev.tistory.com/54
16 ~ 19 라인
사용자로부터 원하는 시작 speedLevel 을 입력받은 뒤, 그 speedLevel 이 유효하지 않으면 (MAX_SPEED_LEVEL (= 10) 보다 크거나, MIIN_SPEED_LEVEL (= 1) 보다 작은 경우) speedLevel 에 임의로 MIN_SPEED_LEVEL 로 설정합니다.
20 라인
TetrisManager_Init 함수를 호출하여, tetrisView->tetrisManager 변수를 초기화합니다.
21 라인
TetrisManager_Print 함수를 호출하여 테트리스 판, 블럭, 게임 상태 등을 화면에 출력합니다.
24 라인
TetrisView_ProcessGame 함수의 정의부입니다. 매개변수로, tetrisView 와 processType (사용자가 방향키를 눌렀는지, 스페이스바를 눌렀는지, 자동으로 내려오는지를 구분하는 변수), direction (방향) 을 전달받아서, 실제 테트리스 게임을 진행합니다.
25 ~ 33 라인
크게, processType 을 확인하여, DIRECTION (방향키를 누른 경우), DIRECT_DOWN (스페이스바를 누른 경우), AUTO (자동으로 내려오는 경우) 의 3 가지 경우로 구분하여 게임을 진행합니다. 먼저, processType 이 DIRECTION 인 경우는, TetrisManager_ChangeBoardByDirection 함수를 호출하여, 블럭의 방향을 업데이트 해 준뒤, 화면을 갱신합니다. 두 번째로, processType 이 DIRECT_DOWN 인 경우에는, TetrisManager_ProcessDirectDown 함수를 호출하여 현재 블럭이 내려갈 수 있을 때까지 내리고, 화면을 갱신합니다. 마지막으로, processType 이 AUTO 인 경우는, TetrisManager_ChangeBoardByAuto 함수를 호출하여 한 칸 밑으로 블럭을 내린 뒤 화면을 갱신합니다.
34 ~ 43 라인
TetrisManager_IsReachedToBottom 함수를 호출하여 현재 블럭이 바닥에 닿았는지를 체크합니다. (바닥은, 아래 벽 말고도, 굳어진 블럭도 포함합니다.) 만약 바닥에 닿았으면, 먼저, 사용자가 좌우키를 눌렀는지 확인하여, 그 방향이 비었는지 확인합니다. (즉. 블럭이 바닥에 닿기는 했찌만, 좌우로 한번더 이동 가능한 경우를 말합니다.) 이것은, 사용자가 LEFT 방향을 원했을 때, 블럭의 왼쪽이 빈 경우와 사용자가 RIGHT 방향을 원했을 때, 블럭의 오른쪽이 빈 경우를 말합니다. 왼쪽이나 오른쪽이 비었는지는 TetrisManager_CheckValidPosition 함수를 호출하여 체크합니다. 만약 이 두 가지 경우중 하나에 해당된다면, TetrisManager_ChanageBoardByDirection 함수를 호출하여 사용자가 원하는 방향으로 블럭을 이동하게 합니다.
그리고 나서, TetrisManager_ProcessReachedCase 함수를 호출하여 현재 블럭이 바닥에 닿은 경우의 처리를 합니다. 추가적으로, 이 함수의 반환값을 확인하여 END 인 경우에 TetrisView_EndGame 을 호출하여 테트리스 게임을 종료합니다.
44 라인
TetrisManageR_ProcessDeletingLines 함수를 호출하여 굳어진 블럭들이 한 줄을 이뤘을 경우를 처리합니다.
45 라인
TetrisManager_Print 함수를 호출하여 게임 화면을 갱신합니다.
46 ~ 48 라인
processType 이 AUTO 인 경우에는, TetrisManager_Sleep 함수를 호출하여 speedLevel 에 기반한 일정 시간동안 게임을 지연시킵니다.
51 라인
TetrisView_EndGame 함수의 정의부입니다. 매개변수로 tetrisView 를 받아서, 테트리스 게임을 종료합니다.
52 라인
PlaySound 함수를 호출하여 테트리스 배경 음악 재생을 정지합니다.
53 라인
system("cls") 함수를 호출하여 화면을 지웁니다.
(콘솔 화면 지우기 참고)
http://kkikkodev.tistory.com/64
54 ~ 56 라인
게임의 현재 속도 레벨과 총 지운 라인의 개수를 출력합니다.
57 라인
system("pause") 함수를 호출하여 콘솔이 바로 닫히지 않도록 프로그램을 일시정지합니다. (사용자가 키 입력을 해야 다음을 실행합니다.)
58 라인
exit(-1) 함수를 호출하여 프로그램을 종료합니다.
(프로그램 강제로 종료시키기 참고)