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

C(&C++) 실습 11. 슈팅 게임 일부 수정

라이피 (Lypi) 2023. 1. 13. 17:08
반응형


출처 

soen.kr


#include "Turboc.h"

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

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

int fx;			//조종기의 x좌표
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;
};

//조종기 총알 구조체
struct Bullet {
	bool exist;
	int x, y;
};

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

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

Enemy eCount[MAXENEMY];			//적 배열
Ball bCount[MAXBALL];			//적 총알 배열
Bullet bBullet[MAXBULLET];		//아군 총알 배열


int main() {
	int i, j;

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

	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좌표를 기준으로 위쪽에 총알을 만든다.
					for (i = 0; i < MAXBULLET && bBullet[i].exist == true; i++) { ; }
					if (i != MAXBULLET) {
						bBullet[i].x = fx;
						bBullet[i].y = 23;
						bBullet[i].exist = true;
					}
					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;
			}
		}

		// 조종기에서 발사한 총알을 이동시킨다.
		for (i = 0; i < MAXBULLET; i++) {
			if (bBullet[i].exist) {
				if (count % 3) break;
				gotoxy(bBullet[i].x, bBullet[i].y); _putch(' ');
				if (bBullet[i].y == 0) {
					bBullet[i].exist = false;
				}
				else {
					bBullet[i].y--;
					gotoxy(bBullet[i].x, bBullet[i].y); _putch('@');
				}
			}
		}

		//적군과 아군 총알이 충돌했는지 판정한다.
		//+ 충돌시 바로 사라지지 않고 잠시 시체가 남게 했다.
		for (i = 0; i < MAXENEMY; i++) {
			if (eCount[i].exist == false || eCount[i].Type == -1) continue;
			for(j=0; j<MAXBULLET; j++) {
				if (bBullet[j].exist == false) continue;
				if (eCount[i].y == bBullet[j].y && abs(eCount[i].x - bBullet[j].x) <= 2) {
					gotoxy(bBullet[j].x, bBullet[j].y); _putch(' ');
					bBullet[j].exist = false;
					eCount[i].Type = -1;
					gotoxy(eCount[i].x - 2, eCount[i].y);
					puts(".,:,.");
					Score += 7 - eCount[i].nFrame;
					eCount[i].nFrame = eCount[i].nStay = 50;
					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 {
					if (random(5)) {
						if (bCount[i].x < fx) {
							bCount[i].x++;
						}
						else {
							bCount[i].x--;
						}
					}

					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);

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

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

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

			if (--eCount[i].nStay == 0) {
				if (eCount[i].Type == -1) {
					gotoxy(eCount[i].x - 2, eCount[i].y);
					puts("     ");
					eCount[i].exist = false;
					continue;
				}

				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++; //루프 카운터 증가
	}
}

■ 사이트에 나온 내용에 따라 조금 바꿔보았다.

■ 클래스로 변경한게 아니고 기능을 조금 바꾼 정도이기 때문에 조금만 바꿔도 전체에 문제가 생길 수 있다.

 

반응형