[C++] 두 물체 충돌 구현

SEUNGJUN JEONG·2022년 11월 15일
0

C/C++

목록 보기
12/15


위 알고리즘을 사용해 두 물체의 충돌 여부를 구현합니다.
물체 출력은 SFML 프레임워크를 사용합니다.

해결 과정

먼저 위의 공식에 대한 함수는 다음과 같이 작성 할 수 있습니다.

bool MyCircle::collisionTest(MyCircle c1, MyCircle c2) {
	double distance;
	distance = sqrt(pow(abs(c1.posX - c2.posX), 2) + pow(abs(c1.posY - c2.posY), 2));
	// cmath 라이브러리 사용
	if (distance <= c1.radius + c2.radius) {
		return true;
	}
	else {
		return false;
	}
}

거리가 두 원의 반지름보다 큰지 작은지에 따라 충돌 여부를 따집니다.

전체 코드를 보면

#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>

using namespace std;
using namespace sf;

class MyCircle {
public:
	CircleShape circle;

	double radius;
	double diameter;
	double posX;
	double posY;
	double velocity;
	MyCircle() {
		posX = 0;
		posY = 0;
		radius = 10;
		diameter = radius * 2;
		velocity = 2;
		circle.setPosition(posX, posY);
		circle.setRadius(radius);
		circle.setFillColor(Color(0, 255, 0));
		circle.setPointCount(30);
	}

	MyCircle(double x, double y, double rad) {
		posX = x;
		posY = y;
		radius = rad;
		diameter = radius * 2;
		velocity = 2;
		circle.setPosition(posX, posY);
		circle.setRadius(radius);
		circle.setFillColor(Color(0, 255, 0));
		circle.setPointCount(30);
	}

	void setVelocity(double vel) {
		velocity = vel;
	}

	double getVelocity() {
		return velocity;
	}

	void setRadius(double rad) {
		radius - rad;
		diameter = radius * 2;
		circle.setRadius(radius);
	}

	void setPosition(double x, double y) {
		posX = x;
		posY = y;
		circle.setPosition(x, y);
	}

	void move(double dx, double dy) {
		circle.move(dx, dy);
	}

	bool collisionTest(MyCircle c1, MyCircle c2);
	

	CircleShape getCircle() {
		return circle;
	}
};

bool MyCircle::collisionTest(MyCircle c1, MyCircle 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;
	}
}


int main()
{
	int nX = 600;
	int nY = 600;
	RenderWindow window(VideoMode(nX, nY), "Moving Ball");
	window.setFramerateLimit(150);
	
	double radius = 20;
	double diameter = radius * 2;
	double posX = 0;
	double posY = nY - diameter;
	double velocity = 4;

	CircleShape circle(radius); //반지름
	circle.setPosition(posX, posY);
	circle.setFillColor(Color(0, 255, 0));
	circle.setPointCount(50);

	MyCircle circleM1(posX + 50, posY - 300, radius);
	MyCircle circleM2(posX + 450, posY - 300, radius);
	MyCircle obj;

	// 여기서부터 게임 루프
	while (window.isOpen())
	{	
		// 이벤트 검사 및 처리
		Event e;
		while (window.pollEvent(e)) {
			if (e.type == Event::Closed)
				window.close();
		}

		if (Keyboard::isKeyPressed(Keyboard::Up)) {
			circleM1.move(0, -circleM1.getVelocity());
			circleM1.posY += -circleM1.getVelocity();
		}
		else if (Keyboard::isKeyPressed(Keyboard::Down)) {
			circleM1.move(0, circleM1.getVelocity());
			circleM1.posY += circleM1.getVelocity();
		}
		if (Keyboard::isKeyPressed(Keyboard::Left)) {
			circleM1.move(-circleM1.getVelocity(), 0);
			circleM1.posX += -circleM1.getVelocity();
		}
		else if (Keyboard::isKeyPressed(Keyboard::Right)) {
			circleM1.move(circleM1.getVelocity(), 0);
			circleM1.posX += circleM1.getVelocity();
		}

		// 화면을 지운다. 
		window.clear();

		// 화면에 원을 그린다. 
		window.draw(circleM1.getCircle());
		window.draw(circleM2.getCircle());

		// 화면을 표시한다. 
		window.display();
		
		cout << obj.collisionTest(circleM1, circleM2) << endl;
	}
	return 0;
}

과 같이 작성 가능합니다.
프로그램을 실행하는 동안 충돌 여부를 프린트하고 충돌할 시 true를 반환합니다.

결과


충돌하면 1, 아니면 0을 출력하는걸 확인할 수 있습니다.

profile
Microsoft Learn Student Ambassadors

0개의 댓글