리메이크 중/C,C++ 실습 중심

C(&C++) 실습 10. 슈팅 게임

라이피 (Lypi) 2023. 1. 12. 17:44
반응형


출처 

soen.kr


#include "Turboc.h"

//특수키 바인딩
#define ESC			27

//MAX값 지정
#define MAXENEMY	10
#define MAXBALL		20


int fx;			//조종기의 x좌표
int bx, by;		//아군 총알의 x,y좌표
int Score;		//점수

//적 구조체
struct Enemy
{
	bool exist;
	int Type;
	int x, y;
	int Delta;
	int nFrame;
	int nStay;
};

//적 총알 구조체
struct Ball
{
	bool exist;
	int x, y;
	int nFrame;
	int nStay;
};

//적기 종류
const char *arEnemy[4] = { "--$--", "ZzTzZ", "oO@Oo", "<-&->"};

//키가 눌러져 있는지 확인하는 함수
bool IsKeyDown(int Key) { return ((GetAsyncKeyState(Key) & 0x8000) != 0); }

Enemy eCount[MAXENEMY];			//적 배열
Ball bCount[MAXBALL];			//적 총알 배열

int main() {
	int i, j;

	randomize();
	clrscr();
	setcursortype(NOCURSOR);
	fx = 40;
	bx = -1;
	Score = 0;

	int count = 0;
	while(true) {	//전체 무한 루프 시작

		//좌우 이동 처리
		//count 처리가 없으면 너무 빨리 움직인다.
		//if 처리는 화면 밖으로 나가지 않게 하기 위한 처리.
		//IsKeyDown함수도 키 입력을 확인하는 함수로 만들어져있는데
		//_kbhit() _getch()와 다른 점은 키를 누르고 있는 것도 연속된 입력으로 인식하고,
		//다른 키와 같이 누른 것도 인식한다는 것이다.
		if (count % 5 == 0) {
			if (IsKeyDown(VK_LEFT)) {
				if (fx > 3) { 
					gotoxy(fx - 3, 23);
					puts("    ");
					fx--; 
				}
			}
			if (IsKeyDown(VK_RIGHT)) {
				if (fx < 75) {
					gotoxy(fx - 3, 23);
					puts("    ");
					fx++; 
				}
			}
		}

		//키 입력 처리
		if (_kbhit()) {
			int ch = _getch();
			// 특수키가 눌린건지 확인
			// 특수키 종류를 확인해 볼 것
			if (ch == 0xE0 || ch == 0) {
				_getch();

			//아니라면 처리
			} else {
				switch (ch) {
				case ' ':
					//발사된 총알이 없다면
					//조종기의 x좌표를 기준으로 위쪽에 총알을 만든다.
					if (bx == -1) {
						bx = fx;
						by = 23;
					}
					break;
				case ESC:
					//ESC키를 누르면 종료 처리 
					//goto문으로 되어 있어서 바꿨다.
					setcursortype(NORMALCURSOR);
					return 0;
				}
			}
		}

		//적군 생성 
		//1%의 확률인데 1초에 100프레임이므로 초당 하나 정도 만들어질 것이다.
		if (random(100) == 0) {
			//eCount안에서 exist가 false인 것을 찾는다
			for (i = 0; i < MAXENEMY && eCount[i].exist == true; i++) { ; }

			//루프가 끝까지 돌아서 끝난게 아닌지 확인한다.
			if (i != MAXENEMY) {
				//이동 방향을 결정하고 화면 끝으로 위치를 설정한다.
				if (random(2) == 1) {
					eCount[i].x = 5;
					eCount[i].Delta = 1;
				}
				else {
					eCount[i].x = 75;
					eCount[i].Delta = -1;
				}

				
				//무한 루프
				while(true) {
					int bFound = false;
					//세로 좌표를 랜덤으로 정한다.
					eCount[i].y = random(10) + 1;
					for (j = 0; j < MAXENEMY; j++) {
						//그 세로 좌표에 이미 적이 존재하는지 확인한다.
						if (eCount[j].exist == true && eCount[j].y == eCount[i].y) {
							bFound = true;
							break;
						}
					}
					//없다면 루프를 나간다.
					if (bFound == false) {
						break;
					}
				}
				//속도와 모양을 결정하고 존재 여부를 true로 한다.
				eCount[i].nFrame = eCount[i].nStay = random(6) + 1;
				eCount[i].Type = random(sizeof(arEnemy) / sizeof(arEnemy[0]));
				eCount[i].exist = true;
			}
		}

		// 조종기에서 발사한 총알을 이동시킨다.
		if (bx != -1) {
			gotoxy(bx, by); _putch(' ');
			if (by == 0) {
				bx = -1;
			}
			else {
				by--;
				gotoxy(bx, by); _putch('i');
			}
		}

		//적군과 아군 총알이 충돌했는지 판정한다.
		for (i = 0; i < MAXENEMY; i++) {
			if (eCount[i].exist == false) continue;
			if (eCount[i].y == by && abs(eCount[i].x - bx) <= 2) {
				gotoxy(bx, by); _putch(' ');
				bx = -1;
				eCount[i].exist = false;
				gotoxy(eCount[i].x - 3, eCount[i].y);
				puts("    ");
				Score += 7 - eCount[i].nFrame;
				break;
			}
		}

		//적군 총알을 이동시킨다.
		for (i = 0; i < MAXBALL; i++) {
			if (bCount[i].exist == false) continue;
			if (--bCount[i].nStay == 0) {
				bCount[i].nStay = bCount[i].nFrame;
				gotoxy(bCount[i].x, bCount[i].y); _putch(' ');
				if (bCount[i].y >= 23) {
					bCount[i].exist = false;
				}
				else {
					bCount[i].y++;
					gotoxy(bCount[i].x, bCount[i].y); _putch('*');
				}
			}
		}

		//적군 총알과 아군 조종기가 충돌했는지 판정한다.
		for (i = 0; i < MAXBALL; i++) {
			if (bCount[i].exist == false) continue;
			if (bCount[i].y == 23 && abs(bCount[i].x - fx) <= 2) {
				gotoxy(fx - 3, 21); puts("   .   ");
				gotoxy(fx - 3, 22); puts(".  .  .");
				gotoxy(fx - 3, 23); puts("..:V:..");
				delay(2000);

				//충돌했다면 게임을 종료한다.
				setcursortype(NORMALCURSOR);
				return 0;
			}
		}

		//적군 이동 
		for (i = 0; i < MAXENEMY; i++) {

			if (eCount[i].exist == false) continue;

			if (--eCount[i].nStay == 0) {
				eCount[i].nStay = eCount[i].nFrame;
				
				//적군이 화면 밖에 있으면
				if (eCount[i].x >= 76 || eCount[i].x <= 4) {
					eCount[i].exist = false;
					gotoxy(eCount[i].x - 2, eCount[i].y);
					puts("    ");
				}
				else {
					//적군의 원래 이미지를 지우고 새로운 이미지를 그린다.
					gotoxy(eCount[i].x - 2, eCount[i].y);
					puts("    ");
					eCount[i].x += eCount[i].Delta;
					gotoxy(eCount[i].x - 2, eCount[i].y);
					puts(arEnemy[eCount[i].Type]);

					//1/40 확률로 총알을 발사한다.
					if (random(40) == 0) {
						for (j = 0; j < MAXBALL && bCount[j].exist == true; j++) { ; }
						if (j != MAXBALL) {
							bCount[j].x = eCount[i].x + 2;
							bCount[j].y = eCount[i].y + 1;
							bCount[j].nFrame = bCount[j].nStay = eCount[i].nFrame * 6;
							bCount[j].exist = true;
						}
					}
				}
			}
		}

		gotoxy(fx - 3, 23);
		puts("<<A>>");
		gotoxy(0, 24);
		printf("점수 = %d", Score);

		delay(10);

		count++; //루프 카운터 증가
	}
}

 

■ 주석으로 쓸말은 다 쓴 것 같음. 

■ C스타일로 만들어진 예제라서 통으로 움직인다. 

■ C++스타일의 클래스로 재설계해보고 싶다.

반응형