개발/게임개발
c++ 게임만들기 연습문제 3.2
소심야채
2023. 3. 2. 15:49
* 인프런에 있는 "홍정모의 게임 만들기 연습 문제 패키지" 강의를 바탕으로 작성된 글입니다.
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();
}
};
}