?>

Hard Copy World

HCW

Arduino advanced

Home > Learning >

Arduino advanced

게임 메이커: 아두이노 게임기 만들기 PART4 - 게임 화면 전환

페이지 정보

작성자 하드카피 쪽지보내기 메일보내기 자기소개 아이디로 검색 전체게시물 작성일15-07-06 00:25 조회4,593회 댓글0건

본문

 

강좌 시리즈:

  1. 게임 메이커: 아두이노 게임기 만들기 Part1 - 프로젝트 소개, 하드웨어 구성, 테스트
  2. 게임 메이커: 아두이노 게임기 만들기 Part2 - 게임 프로그래밍 준비
  3. 게임 메이커: 아두이노 게임기 만들기 PART3 - 기획 및 기본 구조
  4. 게임 메이커: 아두이노 게임기 만들기 PART4 - 게임 화면 전환 <<<<<
  5. 게임 메이커: 아두이노 게임기 만들기 PART5 - 캐릭터 움직임 구현
  6. 게임 메이커: 아두이노 게임기 만들기 PART6 - 장애물 움직임과 충돌 구현
  7. 게임 메이커: 아두이노 게임기 만들기 PART7 - 총알과 해골 움직임, 마무리

 

지난 강좌에서는 게임 화면을 만들기 위한 소스코드의 기본 구조를 잡았습니다. 이제 이 소스를 다듬어서 각 화면을 완성시키고 조이스틱+버튼을 이용해서 화면간 전환이 될 수 있도록 해보겠습니다.

이번 강좌에서 사용되는 소스는 GitHub에서 받을 수 있습니다. [Template/Template2] 폴더를 확인하시면 됩니다.

https://github.com/godstale/game-maker

아두이노에 전원이 들어가면 가장 먼저 보여지는 시작 애니메이션과 로고 화면은 지난 강좌의 코드에서 바뀐 게 없습니다. 로고 화면에서 버튼을 눌러 메뉴 화면으로 전환될 때부터 필요한 코드들을 추가해야 합니다.

runningman01runningman02

 

 

추가된 전역 변수와 함수

 

setup() 함수가 시작되기 전, 필요한 전역 변수들과 함수를 위해 아래 코드들이 추가되었습니다.

// Menu
#define MENU_START 1
#define MENU_CREDIT 2
#define MENU_MIN 1
#define MENU_MAX 2
int prevMenu = MENU_MAX;
int currentMenu = 0;

PROGMEM const char* stringTable[] = {
"Start game",
"Credit"
};

// Utilities
int getOffset(int s);
void initUserInput();
void stopUntilUserInput();
void setMenuMode();
void setGameMode();
void setResultMode();
void setCreditMode();

메뉴 화면을 보여주고 조이스틱으로 현재 선택된 항목을 이동시키기 위해서 prevMenu, currentMenu 변수를 만들어 뒀습니다. 그리고 메뉴의 시작과 끝 index 값을 표시하는 MENU_MIN, MENU_MAX를 정의해 뒀습니다. 메뉴화면에서는 딱 2개의 메뉴만 보여줄 겁니다. “Start game”과 “Credit”입니다. 따라서 이 두 문자열을 stringTable[] 배열로 미리 잡아뒀습니다.

그리고 화면 전환, 사용자 입력을 받을 때까지 대기하는 함수들을 추가해뒀습니다.

  • int getOffset(int s);
    문자열을 우측 정렬하기 위해 우측에서 얼마나 띄워서 표시해야 하는지를 계산하는 함수
  • void initUserInput();
    사용자 입력 상태를 담은 변수들을 초기화하는 함수. 사용자 입력 상태에 따라 처리가 끝나면 이 함수를 이용해 입력 상태를 초기화 함.
  • void stopUntilUserInput();
    사용자가 버튼을 누르기 전까지 while() 반복문으로 무한대기시켜주는 함수
  • void setMenuMode();
    메뉴 화면으로 전환
  • void setGameMode();
    게임 화면으로 전환
  • void setResultMode();
    결과 화면으로 전환
  • void setCreditMode();
    게임 제작자 정보 화면으로 전환

 

 

메뉴 화면 만들기

 

시작 애니메이션 - 로고 화면이 출력되면 사용자가 버튼을 입력할 때 까지 대기하도록 수정해야 합니다. 그리고 사용자가 버튼을 누르면 메뉴 화면으로 전환하도록 아래와 같이 수정했습니다. setup() 함수의 가장 마지막 코드입니다.

// display main image
display.clearDisplay();
display.drawBitmap(0,0,nightrun,128,64,1);
display.display();

stopUntilUserInput(); // Wait until user touch the button

setMenuMode(); // Menu mode

setMenuMode() 함수를 호출하면 gameState 변수가 STATUS_MENU 로 바뀝니다. loop() 함수가 반복될 때 gameState 변수의 값에 따라 디스플레이로 표시될 화면이 결정됩니다.

 

loop() 함수의 코드 중 if(millis() > lTime + gameFPS) {} 블록 안에 있는 부분들이 실제 화면을 그려주는 부분들입니다. 이 코드 중 메뉴 화면을 구성하기 위해 아래와 같이 수정했습니다.

		if (gameState == STATUS_MENU) {  // Main menu
			if(up) currentMenu--;
			else if(down) currentMenu++;
			if(currentMenu > MENU_MAX) currentMenu = MENU_MAX;
			if(currentMenu < MENU_MIN) currentMenu = MENU_MIN;
			if(aBut || bBut) {
  				if(currentMenu == MENU_CREDIT) {
					setCreditMode();
				}
				else if(currentMenu == MENU_START) {
					setGameMode();
				}
			} else {
				if(prevMenu != currentMenu) {
					prevMenu = currentMenu;		// Remember current menu index
					
					// Draw menu
					display.clearDisplay();
					for(int i=0; i ");
					display.display();
				}
			}
		}

일단 사용자가 조이스틱을 어떻게 움직였는지를 체크해서 커서(>)의 위치를 나타내는 currentMenu 값을 변경합니다. 그리고 메뉴와 커서를 화면에 그려줍니다. 이 코드만으로 메뉴 화면은 조이스틱의 움직임에 반응합니다.

runningman03

그리고 A(aBut), B(bBut) 버튼을 누르면 현재 커서의 위치에 해당하는 화면으로 전환하도록 코딩되어 있습니다. currentMenu 값에 따라 setCreditMode(), setGameMode() 함수가 호출되어 화면이 전환됩니다.

 

 

게임 제작자 정보(Credit) 화면

 

사용자가 Credit 메뉴를 선택하면 setCreditMode() 함수가 실행되면서 gameState 변수의 값이 STATUS_CREDIT 으로 바뀝니다. 그러면 loop() 함수가 다시 실행될 때 Credit 화면을 그리기 시작합니다.

		else if (gameState == STATUS_CREDIT) {  // Draw credit screen
			// Draw credit screen
			display.clearDisplay();
			display.drawBitmap(0,0,nightrun,128,64,1);

			display.setCursor(18,5);
			display.print(F("Presented by"));
			display.setCursor(18,20);
			display.print(F("HardCopyWorld.com"));

			display.display();  // Make sure final frame is drawn
			stopUntilUserInput();    // Wait until user touch the button
			setMenuMode();
		}

Credit 화면은 로고 이미지를 출력하고 그 위에 제작자 정보 문자열을 출력해줍니다. 그리고 stopUntilUserInput(); 함수를 호출해서 사용자가 버튼을 누를 때까지 대기합니다. 사용자가 버튼을 누르면 setMenuMode(); 함수가 실행되면서 다시 메뉴 화면으로 돌아갑니다.

runningman06

소스코드 중간에 버튼을 누를 때 까지 멈추는 효과를 주고 싶을 때 stopUntilUserInput(); 함수를 사용하면 됩니다. 이 함수는 소스코드 하단에 정의되어 있습니다.

void stopUntilUserInput() {
	while (true) {  // While we wait for input
		if (digitalRead(BUTTON_A) == LOW || digitalRead(BUTTON_B) == LOW) {  // Wait for a button press
			break;
		}
		delay(200);  // Slight delay the loop
	}
}

 

 

게임 화면

 

메뉴 화면에서 Start game 메뉴를 선택하면 setGameMode(); 함수를 실행하면서 게임 화면으로 전환됩니다. 가장 중요하고 복잡한 게임 엔진이 실행되어야 하므로 미리 변수들을 setGameMode() 함수 안에서 초기화 해줘야 합니다.

지금은 각 화면 간 전환하는 코드만을 작성할 예정이므로 게임 화면에서는 아무 것도 하질 않습니다. 게임 화면 상태가 되면 바로 결과 화면으로 전환해 버리도록 작성해 뒀습니다. setResultMode(); 함수를 호출하면 결과 화면으로 전환됩니다.

		else if (gameState == STATUS_PLAYING) { // If the game is playing
			// Run game engine
			// Draw game screen
			
			setResultMode();
		}

 

 

결과 화면

 

결과 화면은 현재 게임 스코어, 최고 스코어를 표시해주는 화면입니다. 그리고 최고 스코어를 갱신한 경우 EEPROM 에 기록해서 전원이 꺼지더라도 데이터가 유실되지 않도록 해줍니다. (EEPROM 부분은 나중에 구현)

		else if (gameState == STATUS_RESULT) {  // Draw a Game Over screen w/ score
			if (gameScore > gameHighScore) { gameHighScore = gameScore; }  // Update game score
			display.display();  // Make sure final frame is drawn

			// delay(100); // Pause for the sound
			
			// Draw game over screen
			display.drawRect(16,8,96,48, WHITE);  // Box border
			display.fillRect(17,9,94,46, BLACK);  // Black out the inside
			
//			display.setCursor(39,12);
//			display.print("Game Over!");
			display.drawBitmap(30,12,gameover,72,14,1);
			
			display.setCursor(56 - getOffset(gameScore),30);
			display.print(gameScore);
			display.setCursor(69,30);
			display.print("Score");
		
			display.setCursor(56 - getOffset(gameHighScore),42);
			display.print(gameHighScore);
			display.setCursor(69,42);
			display.print("High");

			display.display();

			stopUntilUserInput();    // Wait until user touch the button
			gameState = STATUS_MENU;  // Then start the game paused
			gameScore = 0;  // Reset score to 0
			setMenuMode();
		}

코드가 복잡해 보이지만 실은 별게 없습니다. 현재의 게임 화면을 지우지 않고 그 위에 사각형 박스를 그립니다. 그리고 게임 종료 이미지(gameover[])와 스코어 문자를 적당한 위치에 출력한 겁니다.

runningman05

stopUntilUserInput(); 함수를 호출해서 버튼을 누를 때까지 작업을 멈추고 버튼이 눌러지면 메뉴 화면으로 다시 돌아갑니다.

 

 

기타

 

loop() 함수 아래쪽에 setup(), loop() 안에서 사용되는 다양한 함수들을 정의해 뒀습니다. 추후 필요한 함수들도 여기에 계속 추가해 나갈 것입니다.

 

 

테스트

 

여기까지 게임에 필요한 화면들과 화면 간 전환 코드를 구현했습니다. 이 코드를 컴파일해서 아두이노에 올리면 조이스틱과 버튼을 이용해 각 화면들을 확인해 볼 수 있습니다. 게임 화면은 아직 구현이 되어 있질 않지만 다음 강좌부터 본격적으로 게임 화면을 구현해 나갈 것입니다.

runningman02

 

강좌 시리즈:

  1. 게임 메이커: 아두이노 게임기 만들기 Part1 - 프로젝트 소개, 하드웨어 구성, 테스트
  2. 게임 메이커: 아두이노 게임기 만들기 Part2 - 게임 프로그래밍 준비
  3. 게임 메이커: 아두이노 게임기 만들기 PART3 - 기획 및 기본 구조
  4. 게임 메이커: 아두이노 게임기 만들기 PART4 - 게임 화면 전환 <<<<<
  5. 게임 메이커: 아두이노 게임기 만들기 PART5 - 캐릭터 움직임 구현
  6. 게임 메이커: 아두이노 게임기 만들기 PART6 - 장애물 움직임과 충돌 구현
  7. 게임 메이커: 아두이노 게임기 만들기 PART7 - 총알과 해골 움직임, 마무리

 


하드카피 쪽지보내기 메일보내기 자기소개 아이디로 검색 전체게시물

모든 전통이 한 때는 오해를 면치 못했다. 마찬가지로 모든 아이디어는 한 때는 비웃음을 면치 못했다. -홀브룩 잭슨 ::::: 느닷없이 떠오르는 생각이 가장 귀중한 것이며, 보관해야할 가치가 있는 것이다. -베이컨 ::::: 미리 숙고하면 힘든 일도 그저 실행에 옮기는 순간 쉬워진다. - 로버트 M. 피어식

추천 0
  • 페이스북으로 보내기
  • 트위터로 보내기
  • 구글플러스로 보내기

댓글목록

등록된 댓글이 없습니다.