주녘공부일지

[C언어] 콘솔 비행기 게임 본문

GameDevelopment/[C++] Project

[C언어] 콘솔 비행기 게임

주녘 2024. 9. 11. 11:03

0. 게임 플레이 영상

 

 

 

 

 

 

 

1. 콘솔 비행 슈팅 게임

- 스테이지를 클리어하며, 최고 점수를 기록하는 게임

- 스테이지가 지날수록 적 기체의 수, 체력이 늘어나며 난이도가 올라감

https://github.com/godgjwnsgur7/C_FlightShootingGame/tree/main

 

GitHub - godgjwnsgur7/C_FlightShootingGame

Contribute to godgjwnsgur7/C_FlightShootingGame development by creating an account on GitHub.

github.com

2. 게임 핵심 시스템

1) 핵심 기능

- 오브젝트 메모리 풀 ( Struct Array )

- 더블 버퍼링 ( Ingame ) // window.h

- View와 Game Info의 갱신되는 주기를 분리
- 객체지향 프로그래밍 ( Struct )

#pragma region Enemy
void InitEnemy();
void UpdateEnemy();

void MoveEnemy(struct _ENEMY* enemy);
void SpawnEnemy(struct _ENEMY* enemy);

void DrawEnemy();
void EraseEnemy(struct _ENEMY* enemy);

void OnEnemyHit(struct _ENEMY* enemy);
#pragma endregion

2) 백그라운드 배열 ( Background Arrays )

- 더블 버퍼링의 두 스크린을 프론트 스크린, 백 스크린이라고 칭함

- 스크린을 교체하기 전에 백그라운드 배열을 백 스크린에 출력하고 프론트 스크린과 교체

- 즉, 콘솔에 출력할 예정인 인 게임 공간에 대한 정보를 백그라운드 배열이 가지고 있음

 > 이를 이용하여 Event를 감지하고 처리할 수 있도록 함

void UpdateScreen()
{
	ClearScreen();

	for (int y = 0; y <= g_ingameAreaSizeY; y++)
	{
		for (int x = 0; x < g_ingameAreaSizeX; x++)
		{
			char tempStr[2] = "";
			tempStr[0] = g_ingameScreen[y][x];
			tempStr[1] = '\0';

			if (tempStr[0] == ' ')
				continue;

			enum EObjectType type = GetCustomObjectType(tempStr[0]);
			switch (type)
			{
			case Player: CharPrintScreen(y, x, tempStr, WHITE); break;
			case Enemy: CharPrintScreen(y, x, tempStr, RED); break;
			case PlayerBullet: CharPrintScreen(y, x, tempStr, WHITE); break;
			case EnemyBullet: CharPrintScreen(y, x, tempStr, YELLOW); break;
			case Item: CharPrintScreen(y, x, tempStr, DarkYellow); break;
			}
		}
	}

	if (isWaitNextStage)
	{
		char tempCh[horizon];
		sprintf(tempCh, "                                     Stage %d", gameInfoData.currStageId);
		LinePrintScreen(g_ingameAreaSizeY / 2, tempCh, RED);
	}
	
	DividingLinePrintScreen(g_ingameAreaSizeY + 2, GREEN);
	LinePrintScreen(g_ingameAreaSizeY + 3, ingameUIStr, SkyBlue);
	DividingLinePrintScreen(g_ingameAreaSizeY + 4, GREEN);
	
	FlippingScreen();
}

3) 프레임 ( Frame ) & 틱 ( Tick )

- Frame : 20으로 설정 (1초에 20번) // 콘솔 환경

- 1프레임당 5번 호출되는 Game Info Update

- 1프레임당 1번 호출되는 View Update

- 일정한 호출 주기를 가지기 위한 제어 단위 : Tick

 > Speed, Key Press Time, Delay, Event Timing, etc.

void StartInGame()
{
	DWORD gameInfoUpdateStandardTime = GetTickCount64(); // 0.01초
	DWORD viewUpdateStandardTime = GetTickCount64(); // 0.05초

	while (true)
	{
		DWORD gameInfoUpdateElapsedTime = GetTickCount64() - gameInfoUpdateStandardTime;
		if (gameInfoUpdateElapsedTime > g_gameInfoUpdateTick)
		{
			gameInfoUpdateStandardTime = GetTickCount64() - (gameInfoUpdateElapsedTime - g_gameInfoUpdateTick);

			// 실제 화면에 그리기 전에 필요한 연산 ( 0.01초 )
			UpdateInput();
			UpdateBullet();
			UpdateEnemy();
			UpdateItem();
			UpdatePlayer();
			UpdateStage();
		}

		DWORD viewUpdateElapsedTime = GetTickCount64() - viewUpdateStandardTime;
		if (viewUpdateElapsedTime > g_viewUpdateTick)
		{
			viewUpdateStandardTime = GetTickCount64() - (viewUpdateElapsedTime - g_viewUpdateTick);

			// 실제 화면에 그릴 때 필요한 연산 ( 0.05초 )
			if (!player.isDie && player.isInvincible)
				PlayerEffect();

			UpdateUI();
			UpdateScreen();
		}
	}
}

'GameDevelopment > [C++] Project' 카테고리의 다른 글

[C++] 종스크롤 슈팅 게임 ( WinAPI )  (1) 2024.10.30
[C++] 벽돌깨기 게임 ( WinAPI )  (1) 2024.09.15