[C++] 총알 피하기 게임 제작 2주차

SEUNGJUN JEONG·2022년 12월 13일
0

C/C++

목록 보기
14/15

지난주에 이어서 게임을 제작한다.

획득하면 빨라지는 아이템 만들기

vector<Item> itemList;

Item item1(dis_x(gen), dis_y(gen), 25);
itemList.push_back(item1);

먼저 아이템 객체를 하나 만들고 아이템 객체를 관리하기 위해 벡터를 만들어줬다. 아이템의 출현 좌표는 랜덤으로 한다. (랜덤으로 하는 방법은 전 글 참조)

if ((int)time % 4 == 0 && (int)time != 0) { // create item every 4 seconds, duration is a second
	Item item1(dis_x(gen), dis_y(gen), 25);
	itemList.push_back(item1);
	window.draw(itemList[0].getItem());
} else {
	itemList.clear();
}

4초마다 아이템을 출현시키고 1초가 지나면 제거한다. 짧은 시간마다 출현하나 1초면 사라지고 위치가 랜덤이라는 점에서 획득하는 데에 어려운 점이 있다.

if (collTest.collisionItem(Character1, item1) == true) { // when collide to item
	getItem = true;
	Character1.setVelocity(7);
	currentTime = time;
}

if ((int)time - (int)currentTime > 4) {
	Character1.setVelocity(4);
	currentTime = 0;
}

아이템을 획득할 시 캐릭터의 이동 속도를 4초 동안 증가시킨다.
지속시간은 현재 시간을 임시 변수에 복사시킨 후 현재 시간과의 차이를 계산해 구현해보았다.


획득하면 속도가 빨라지고, 4초가 지나면 다시 속도가 줄어드는 것을 확인할 수 있다.

5초마다 추가되는 총알

if ((int)time % 5 == 0) { // create one bullet at every 5 seconds
	if (isCreated == true)
		continue;

	if ((int)time == 0)
		continue;
    else {
		Bullet obj(dis_x(gen), dis_y(gen), bulletRadius);
		bulletList.push_back(obj);
		isCreated = true;
	}
} else {
	isCreated = false;
}

5초마다 총알의 개수를 하나씩 추가해주는 기능을 만들어보았다.
다만 문제가 있는데, time을 정수로 변환해 체크해 주다보니 time이 5.1, 5.2, ... 되면서 5로 변환되고 여러번 체크가 된다.
따라서 한번 실행되면 지정된 bool 타입의 변수의 상태를 변경해 중복 생성을 막아보았다.

게임 오버!

캐릭터가 총알과 충돌했을 경우 게임 오버! 그 상황을 구현해봤다.
먼저 총알과의 충돌 여부를 확인해야한다.

bool objCollision::collisionTest(Character c1, Bullet c2) {
	double distance;
	distance = sqrt(pow(abs(c1.posX - c2.posX), 2) + pow(abs(c1.posY - c2.posY), 2));

	if (distance <= c1.radius + c2.radius) {
		return true;
	}
	else {
		return false;
	}
}

먼저 피타고라스의 방법을 사용해서 충돌 확인 함수를 만들어줬다. 이 방법에 대한 자세한 내용은 여기 로.

// GAME OVER SITUATION
for (int i = 0; i < bulletList.size(); i++) {
	if (collTest.collisionTest(Character1, bulletList[i]) == true && (int)time != 0) // when collide to bullets
		collide = true;
}

충돌 여부를 계속 체크해준다.

while (collide == true) { // when game is over
	Text endText;
	Text endText2;
	window.clear();

	endText.setFont(font);
	endText.setCharacterSize(50);
	endText.setFillColor(Color::Yellow);
	endText.setPosition(0, 0);
	timeText.setPosition(0, 50);

	endText2.setFont(font);
	endText2.setCharacterSize(50);
	endText2.setFillColor(Color::Yellow);
	endText2.setPosition(0, 100);

	endText.setString("Game Over!");
	endText2.setString("Press R to restart or Q to quit");

	window.draw(endText);
	window.draw(timeText);
	window.draw(endText2);
	window.display();

	if (Keyboard::isKeyPressed(Keyboard::R)) { // when restart
		timeText.setPosition(0, 0);
		Character1.setPosition(c_posX + 580, c_posY - 450);
		timer.restart();

		bulletList.clear(); // delete all bullets
				
		// create new bullets when restart the game
		for (int i = 0; i < 5; i++) { // initial bullets quantity = 5
			Bullet obj(dis_x(gen), dis_y(gen), bulletRadius);
			bulletList.push_back(obj);
		}
		collide = false;
	}
			
	if (Keyboard::isKeyPressed(Keyboard::Q)) { // when quit
		window.close();
	}
}

충돌하면 while loop를 작동시킨다. 게임 오버 화면과 함께 'R'을 누르면 재시작, 'Q'를 누르면 게임이 종료된다.
다시시작하면 캐릭터의 좌표는 원점으로 돌아가고, 타이머가 초기화되고, 총알이 재생성된다.

위와 같이 충돌 시 화면이 뜬다.

타이머 코드 변경

이전에 사용하던 타이머 코드를 사용하는데에 문제가 생겼다. clock_t 타입으로 사용했었는데 문제가 게임을 다시시작하는 과정에서 타이머가 초기화가 안되는 것이다. 따라서 SFML에서 제공하는 Clock 클래스를 활용하여 타이머를 제작했다.

Clock timer;

먼저 이렇게 객체를 선언해준다.

float time = timer.getElapsedTime().asSeconds();
		
timeText.setString(to_string(time) + " sec");

그다음 이건 게임이 돌아가는 while문 안에 적어주도록 한다. float 타입의 time 변수를 선언해주고 위와같이 타이머를 작동시킨다. 위 코드는 timer 객체에서 측정한 시간을 계속 가져오는건데, 실시간으로 계속 가져오는 방식이 아니고 한번 가져오고 마는거라 while로 계속 반복시켜줘야 한다.

또한 초단위로 출력되던 기존 타이머에 비해 소수점 자리수를 여섯자리까지 늘려 더 정확한 측정이 가능해졌다.

profile
Microsoft Learn Student Ambassadors

0개의 댓글