티스토리 뷰

* 인프런에 있는 "홍정모의 게임 만들기 연습 문제 패키지" 강의를 바탕으로 작성된 글입니다.

 

1. 3개 이상의 물체에 대해서 테스트 해보기.

#include "Game2D.h"
#include "RandomNumberGenerator.h"
#include "RigidCircle.h"
#include <vector>
#include <memory>

namespace shyplants
{
	class Example : public Game2D
	{
	public:
		RigidCircle rb[3];

		Example()
			: Game2D()
		{
			reset();
		}

		void reset()
		{
			// Initial position and velocity
			RandomNumberGenerator rnd;

			for (int i = 0; i < 3; ++i) {
				rb[i].pos = vec2(rnd.getFloat(0.0f, 0.4f), rnd.getFloat(-0.8f, 0.8f));
				rb[i].vel = vec2(rnd.getFloat(2.0f, 7.0f) * (rnd.getInt(0,1) ? -1 : 1), 0.0f);
				rb[i].color = RGB(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f));
				rb[i].radius = rnd.getFloat(0.1f, 0.3f);
				rb[i].mass = (i == 0 ? 1.0f : rb[0].mass * std::pow(rb[i].radius / rb[0].radius, 2.0f));
			}
		}

		void drawWall()
		{
			setLineWidth(5.0f);
			drawLine(Colors::blue, { -1.0f, -1.0f }, Colors::blue, { 1.0f, -1.0f });
			drawLine(Colors::blue, { 1.0f, -1.0f }, Colors::blue, { 1.0f, 1.0f });
			drawLine(Colors::blue, { -1.0f, -1.0f }, Colors::blue, { -1.0f, 1.0f });
		}

		void update() override
		{
			const float dt = getTimeStep() * 0.4f;
			const float epsilon = 0.5f;

			// physics update
			for (int i = 0; i < 3; ++i) {
				rb[i].update(dt);
			}

			// check collision between two rigid bodies
			for (int i = 0; i < 3; ++i) for (int j = i + 1; j < 3; ++j) {
				const float distance = (rb[i].pos - rb[j].pos).getMagnitude();

				if (distance <= rb[i].radius + rb[j].radius)
				{
					// compute impulse
					const auto vel_rel = rb[i].vel - rb[j].vel;
					const auto normal = -(rb[j].pos - rb[i].pos) / (rb[j].pos - rb[i].pos).getMagnitude();

					if (vel_rel.getDotProduct(normal) < 0.0f) // approaching
					{
						const auto impulse = normal * -(1.0f + epsilon) * vel_rel.getDotProduct(normal) /
							((1.0f / rb[i].mass) + (1.0f / rb[j].mass));

						// update velocities of two bodies
						rb[i].vel += impulse / rb[i].mass;
						rb[j].vel -= impulse / rb[j].mass;
					}
				}
			}
			
			// draw
			drawWall();
			for (int i = 0; i < 3; ++i) {
				rb[i].draw();
			}

			// reset button
			if (isKeyPressedAndReleased(GLFW_KEY_R)) reset();
		}
	};
}

댓글