지난 포스팅에 이어짐

이제 user defined 함수들을 살펴보자.

 

5) void ofApp::drawPipe( )

//----------- Function for drawing pipe -----------
// consider : type of pipe, rotation, location
// pink pipe = a pipe which is waiting to be placed by user
// grey pipe = pipes already placed on the screen
void ofApp::drawPipe() {
	if (currentP->pipe_type == 1) {
		float x, y;
		switch (currentP->rotation) {
		case 1:
			x = currentP->x;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 120, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x + 105, y - 10, 15, 60);
			break;
		case 2:
			x = currentP->x + 40;
			y = currentP->y;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 120);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x - 10, y + 105, 60, 15);
			break;
		case 3:
			x = currentP->x;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 120, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x, y - 10, 15, 60);
			break;
		case 4:
			x = currentP->x + 40;
			y = currentP->y;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 120);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x - 10, y, 60, 15);
			break;
		}
	}

	else if (currentP->pipe_type == 2) {
		float x, y;
		switch (currentP->rotation) {
		case 1:
			x = currentP->x;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x + 40, y, 40, 40);
			ofDrawRectangle(x + 40, y + 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x + 30, y + 65, 60, 15);
			break;
		case 2:
			x = currentP->x;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x + 40, y, 40, 40);
			ofDrawRectangle(x + 40, y - 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x, y - 10, 15, 60);
			break;
		case 3:
			x = currentP->x + 40;
			y = currentP->y;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x, y + 40, 40, 40);
			ofDrawRectangle(x + 40, y + 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x - 10, y, 60, 15);
			break;
		case 4:
			x = currentP->x + 40;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x + 40, y, 40, 40);
			ofDrawRectangle(x, y + 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x + 65, y - 10, 15, 60);
			break;
		}
	}

	else if (currentP->pipe_type == 3) {
		float x, y;
		switch (currentP->rotation) {
		case 1:
			x = currentP->x;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x + 40, y, 40, 40);
			ofDrawRectangle(x + 40, y + 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x, y - 10, 15, 60);
			break;
		case 2:
			x = currentP->x;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x + 40, y, 40, 40);
			ofDrawRectangle(x + 40, y - 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x + 30, y - 40, 60, 15);
			break;
		case 3:
			x = currentP->x + 40;
			y = currentP->y;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x, y + 40, 40, 40);
			ofDrawRectangle(x + 40, y + 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x + 65, y + 30, 15, 60);
			break;
		case 4:
			x = currentP->x + 40;
			y = currentP->y + 40;
			ofSetColor(colorA, colorB, colorC);
			ofDrawRectangle(x, y, 40, 40);
			ofDrawRectangle(x + 40, y, 40, 40);
			ofDrawRectangle(x, y + 40, 40, 40);
			ofSetColor(colorA, colorD, colorE);
			ofDrawRectangle(x - 10, y + 65, 60, 15);
			break;
		}
	}
}
 

이번 포스팅의 user defined 코드들을 살펴보면 비로소 파이프 게임이 굴러가는 방식을 확인할 수 있다.

일단 drawPipe 함수는 파이프의 모양을 읽어 화면에 그리는 역할의 함수이다.

 

drawPipe 함수는 크게 3가지 파트로 나뉘어져 있으며, 각 파트는 다시 4가지 파트로 나뉜다.

파이프의 회전 각도나 파이프의 종류는 rotation과 pipe_type 변수 값을 통해 구별할 수 있다.

 

파이프의 종류는 총 3가지, 회전 각도는 총 4가지 이므로 drawPipe 함수는 3가지의 파이프의 종류에 대해 각각 4가지 의 roation 경우를 다룬다. 이는 코드를 보면 쉽게 이해할 수 있는데, 결과적으로 rotation 과 pipe_type 변수 값에 따라 다른 모양의 파이프가 화면에 표시되는 것이다.

 

현재 파이프는 핑크색으로, 이미 배치된 파이프는 회색으로 그려진다.

현재 파이프가 표시되는 위치는 파이프를 새롭게 배치할 때 마다 업데이트 되고,

이미 배치된 파이프의 위치 정보는 파이프 연결리스트에 저장되어 있어 draw 함수에서 해당 정보를 읽고 배치된 파이프를 모두 그린다.

 

7) void ofApp::addPath( )

//----------- Function for addning water nodes in water linked list -----------
// save every location water will go by : according to the pipes placed on the screen
// on every location the small blue circle will be drawn (water path)
void ofApp::addPath() {
	if (currentP->pipe_type == 1) {
		struct water *w;
		w = (struct water*)malloc(sizeof(struct water));
		switch (currentP->rotation) {
		case 1:
			w->x = currentP->x + 1; w->y = currentP->y + 60;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 120; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x + 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x + 120;
			pyNew = currentP->y;
			break;
		case 2:
			w->x = currentP->x + 60; w->y = currentP->y + 1;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 120; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y + 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x;
			pyNew = currentP->y + 120;
			break;
		case 3:
			w->x = currentP->x + 119; w->y = currentP->y + 60;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 120; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x - 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x - 120;
			pyNew = currentP->y;
			break;
		case 4:
			w->x = currentP->x + 60; w->y = currentP->y + 119;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 120; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y - 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x;
			pyNew = currentP->y - 120;
			break;
		}
	}

	else if (currentP->pipe_type == 2) {
		struct water *w;
		w = (struct water*)malloc(sizeof(struct water));
		switch (currentP->rotation) {
		case 1:
			w->x = currentP->x + 1; w->y = currentP->y + 60;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x + 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y + 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x;
			pyNew = currentP->y + 120;
			break;
		case 2:
			w->x = currentP->x + 60; w->y = currentP->y + 1;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y + 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x - 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x - 120;
			pyNew = currentP->y;
			break;
		case 3:
			w->x = currentP->x + 119; w->y = currentP->y + 60;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x - 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y - 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x;
			pyNew = currentP->y - 120;
			break;
		case 4:
			w->x = currentP->x + 60; w->y = currentP->y + 119;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y - 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x + 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x + 120;
			pyNew = currentP->y;
			break;
		}
	}
// 이어서
 
// 이어서
    else if (currentP->pipe_type == 3) {
		struct water *w;
		w = (struct water*)malloc(sizeof(struct water));
		switch (currentP->rotation) {
		case 1:
			w->x = currentP->x + 60; w->y = currentP->y + 119;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y - 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x - 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x - 120;
			pyNew = currentP->y;
			break;
		case 2:
			w->x = currentP->x + 1; w->y = currentP->y + 60;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x + 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y - 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x;
			pyNew = currentP->y - 120;
			break;
		case 3:
			w->x = currentP->x + 60; w->y = currentP->y + 1;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y + 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x + 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x + 120;
			pyNew = currentP->y;
			break;
		case 4:
			w->x = currentP->x + 119; w->y = currentP->y + 60;
			w->next = NULL;
			endW->next = w; endW = w;
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x - 1; w->y = endW->y;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			for (int i = 1; i < 60; i++) {
				struct water *w;
				w = (struct water*)malloc(sizeof(struct water));
				w->x = endW->x; w->y = endW->y + 1;
				w->next = NULL;
				endW->next = w; endW = w;
			}
			pxNew = currentP->x;
			pyNew = currentP->y + 120;
			break;
		}
	}
}
 

addPath 함수는 물줄기가 흘러가야 할 경로를 저장하는 역할을 수행한다. 새롭게 파이프를 배치할 때 마다 물줄기 연결리스트에 계속 경로가 추가되는데, 이때 '경로'라는 것은 파이프의 가운데 위치 경로를 의미한다.

물이 흐르는 경로가 저장되는 과정
위 그림과 같이 파이프 하나를 배치하면, 파이프의 가운데 위치 좌표가 하나씩 물줄기 연결리스트에 추가되는 것이다.

연결리스트에 저장된 경로를 어디까지 읽어 화면에 표시할 것 인지를 시간이 지날수록 점점 늘려 나가면,

마치 물줄기가 파이프를 따라 흘러가는 듯한 모양새로 표현된다.

 

위 코드가 긴 이유는 현재 배치하는 파이프의 모양과 각도에 따라 모양 3가지, 각도 4가지 : 총 12가지의 경우의 수에 대한 경로를 저장하도록 코드를 작성했기 때문이다...

 

코드 자체는 단순한 switch/case문의 반복이므로, 코드에 대한 세세한 설명은 생략하도록 하겠다.

 


이렇게 게임의 모든 구현이 끝났다!

아쉬운 점은 함수를 적극적으로 이용했다면 코드의 길이를 지금보다 훨씬 단축시킬 수 있었을 것 같다는 점...

 

그럼 다음 포스팅에서 이 간단한 게임이 어떻게 실행되는지를 확인해보자.