티스토리 뷰
* 인프런에 있는 "홍정모의 게임 만들기 연습 문제 패키지" 강의를 바탕으로 작성된 글입니다.
1. 마우스 클릭한 곳에 폭발 효과
#include "Game2D.h"
#include "RandomNumberGenerator.h"
#include "RigidCircle.h"
#include <vector>
#include <memory>
namespace shyplants
{
using namespace std;
static const auto gravity = vec2(0.0f, -9.8f);
class Particle
{
public:
vec2 pos;
vec2 vel;
RGB color;
float rot;
float angular_vel;
float age;
float life;
void update(const float & dt)
{
const auto acc = gravity; //assumes GA only.
vel += acc * dt;
pos += vel * dt;
rot += angular_vel * dt;
// update age.
age += dt;
}
};
class ParticleSystem
{
public:
vector<Particle> particles;
RandomNumberGenerator rn;
vec2 init_pos = { 0.0, 0.5f };
ParticleSystem()
{
// reset(init_pos);
}
auto getRandomUnitVector()
{
const float theta = rn.getFloat(0.0f, 3.141592f * 2.0f); // 0.0 ~ 2pi
return vec2{ cos(theta), -sin(theta) };
}
auto getRandomColor()
{
return RGB{ rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f) };
}
void reset(vec2 init_pos)
{
particles.clear();
// initialize particles
for (int i = 0; i < 1000; ++i)
{
Particle new_particle;
new_particle.pos = init_pos + getRandomUnitVector() * rn.getFloat(0.001f, 0.03f);
new_particle.vel = getRandomUnitVector() * rn.getFloat(0.01f, 2.0f);
new_particle.color = getRandomColor();
new_particle.age = 0.0f;
new_particle.life = rn.getFloat(0.1f, 0.5f);
new_particle.rot = rn.getFloat(0.0f, 360.0f);
new_particle.angular_vel = rn.getFloat(-1.0f, 1.0f) * 360.0f * 4.0f;
particles.push_back(new_particle);
}
}
void update(const float & dt)
{
for (auto & pt : particles)
{
pt.update(dt);
}
}
void draw()
{
beginTransformation();
for (const auto & pt : particles)
{
if (pt.age > pt.life) continue;
const float alpha = 1.0f - pt.age / pt.life;
const RGB blended_color = { pt.color.r * alpha + 1.0f * (1.0f - alpha),
pt.color.g * alpha + 1.0f * (1.0f - alpha),
pt.color.b * alpha + 1.0f * (1.0f - alpha) };
// drawPoint(blended_color, pt.pos, 3.0f);
beginTransformation();
translate(pt.pos);
rotate(pt.rot);
drawFilledStar(blended_color, 0.03f, 0.01f);
endTransformation();
}
endTransformation();
}
};
class Example : public Game2D
{
public:
ParticleSystem ps;
vec2 mouse_pos;
Example()
: Game2D()
{
reset();
}
void reset()
{
// ps.reset();
}
void update() override
{
const float dt = getTimeStep() * 0.4f;
ps.update(dt);
ps.draw();
// reset button
if (isKeyPressedAndReleased(GLFW_KEY_R)) reset();
mouse_pos = getCursorPos(true);
if (isMouseButtonPressedAndReleased(GLFW_MOUSE_BUTTON_1)) {
ps.reset(mouse_pos);
}
}
};
}

2. 스프링클러에서 물이 뿜어져 나오듯이 지속적으로 파티클 생성
#include "Game2D.h"
#include "RandomNumberGenerator.h"
#include "RigidCircle.h"
#include <vector>
#include <memory>
namespace shyplants
{
using namespace std;
static const auto gravity = vec2(0.0f, -9.8f);
class Particle
{
public:
vec2 pos, init_pos;
vec2 vel, init_vel;
RGB color;
float rot, init_rot;
float angular_vel, init_angular_vel;
float age;
float life;
void update(const float & dt)
{
const auto acc = gravity; //assumes GA only.
vel += acc * dt;
pos += vel * dt;
rot += angular_vel * dt;
// update age.
age += dt;
}
void reset()
{
pos = init_pos;
vel = init_vel;
rot = init_rot;
angular_vel = init_angular_vel;
age = 0.0f;
}
};
class ParticleSystem
{
public:
vector<Particle> particles;
RandomNumberGenerator rn;
ParticleSystem()
{
// reset(init_pos);
}
auto getRandomUnitVector()
{
const float theta = rn.getFloat(0.0f, 3.141592f * 2.0f); // 0.0 ~ 2pi
return vec2{ cos(theta), -sin(theta) };
}
auto getRandomColor()
{
return RGB{ rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f) };
}
void reset(vec2 init_pos = { 0.0f, 0.5f })
{
particles.clear();
// initialize particles
for (int i = 0; i < 1000; ++i)
{
Particle new_particle;
new_particle.init_pos = init_pos + getRandomUnitVector() * rn.getFloat(0.001f, 0.03f);
new_particle.init_vel = getRandomUnitVector() * rn.getFloat(0.01f, 2.0f);
new_particle.color = getRandomColor();
new_particle.life = rn.getFloat(0.1f, 0.5f);
new_particle.init_rot = rn.getFloat(0.0f, 360.0f);
new_particle.init_angular_vel = rn.getFloat(-1.0f, 1.0f) * 360.0f * 4.0f;
new_particle.reset();
particles.push_back(new_particle);
}
}
void update(const float & dt)
{
for (auto & pt : particles)
{
pt.update(dt);
}
}
void draw()
{
beginTransformation();
for (auto & pt : particles)
{
if (pt.age > pt.life) {
pt.reset();
continue;
}
const float alpha = 1.0f - pt.age / pt.life;
const RGB blended_color = { pt.color.r * alpha + 1.0f * (1.0f - alpha),
pt.color.g * alpha + 1.0f * (1.0f - alpha),
pt.color.b * alpha + 1.0f * (1.0f - alpha) };
// drawPoint(blended_color, pt.pos, 3.0f);
beginTransformation();
translate(pt.pos);
rotate(pt.rot);
drawFilledStar(blended_color, 0.03f, 0.01f);
endTransformation();
}
endTransformation();
}
};
class Example : public Game2D
{
public:
ParticleSystem ps;
Example()
: Game2D()
{
reset();
}
void reset()
{
ps.reset();
}
void update() override
{
const float dt = getTimeStep() * 0.4f;
ps.update(dt);
ps.draw();
// reset button
if (isKeyPressedAndReleased(GLFW_KEY_R)) reset();
}
};
}

3. 시간에 따라 별이 점점 더 커지게 만들어 보기.
#include "Game2D.h"
#include "RandomNumberGenerator.h"
#include "RigidCircle.h"
#include <vector>
#include <memory>
namespace shyplants
{
using namespace std;
static const auto gravity = vec2(0.0f, -9.8f);
class Particle
{
public:
vec2 pos, init_pos;
vec2 vel, init_vel;
RGB color;
float rot, init_rot;
float angular_vel, init_angular_vel;
float scale;
float age;
float life;
void update(const float & dt)
{
const auto acc = gravity; //assumes GA only.
vel += acc * dt;
pos += vel * dt;
rot += angular_vel * dt;
scale += dt * 5.0f;
// update age.
age += dt;
}
void reset()
{
pos = init_pos;
vel = init_vel;
rot = init_rot;
angular_vel = init_angular_vel;
age = 0.0f;
scale = 1.0f;
}
};
class ParticleSystem
{
public:
vector<Particle> particles;
RandomNumberGenerator rn;
ParticleSystem()
{
// reset(init_pos);
}
auto getRandomUnitVector()
{
const float theta = rn.getFloat(0.0f, 3.141592f * 2.0f); // 0.0 ~ 2pi
return vec2{ cos(theta), -sin(theta) };
}
auto getRandomColor()
{
return RGB{ rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f) };
}
void reset(vec2 init_pos = { 0.0f, 0.5f })
{
particles.clear();
// initialize particles
for (int i = 0; i < 1000; ++i)
{
Particle new_particle;
new_particle.init_pos = init_pos + getRandomUnitVector() * rn.getFloat(0.001f, 0.03f);
new_particle.init_vel = getRandomUnitVector() * rn.getFloat(0.01f, 2.0f);
new_particle.color = getRandomColor();
new_particle.life = rn.getFloat(0.1f, 0.5f);
new_particle.init_rot = rn.getFloat(0.0f, 360.0f);
new_particle.init_angular_vel = rn.getFloat(-1.0f, 1.0f) * 360.0f * 4.0f;
new_particle.reset();
particles.push_back(new_particle);
}
}
void update(const float & dt)
{
for (auto & pt : particles)
{
pt.update(dt);
}
}
void draw()
{
beginTransformation();
for (auto & pt : particles)
{
if (pt.age > pt.life) {
pt.reset();
continue;
}
const float alpha = 1.0f - pt.age / pt.life;
const RGB blended_color = { pt.color.r * alpha + 1.0f * (1.0f - alpha),
pt.color.g * alpha + 1.0f * (1.0f - alpha),
pt.color.b * alpha + 1.0f * (1.0f - alpha) };
// drawPoint(blended_color, pt.pos, 3.0f);
beginTransformation();
translate(pt.pos);
rotate(pt.rot);
scale(pt.scale, pt.scale);
drawFilledStar(blended_color, 0.03f, 0.01f);
endTransformation();
}
endTransformation();
}
};
class Example : public Game2D
{
public:
ParticleSystem ps;
Example()
: Game2D()
{
reset();
}
void reset()
{
ps.reset();
}
void update() override
{
const float dt = getTimeStep() * 0.4f;
ps.update(dt);
ps.draw();
// reset button
if (isKeyPressedAndReleased(GLFW_KEY_R)) reset();
}
};
}

4. 공 위에 파티클을 뿌릴 경우 물체와의 충돌
#include "Game2D.h"
#include "RandomNumberGenerator.h"
#include "RigidCircle.h"
#include <vector>
#include <memory>
namespace shyplants
{
using namespace std;
static const auto gravity = vec2(0.0f, -9.8f);
class Particle
{
public:
vec2 pos, init_pos;
vec2 vel, init_vel;
RGB color;
float rot, init_rot;
float angular_vel, init_angular_vel;
float scale;
float age;
float life;
void update(const float & dt)
{
const auto acc = gravity; //assumes GA only.
const float coef_res = 0.8f; // coefficient of restitution
const float coef_friction = 0.99f; // friction (not physical)
vel += acc * dt;
pos += vel * dt;
rot += angular_vel * dt;
scale += dt * 5.0f;
// update age.
age += dt;
}
void reset()
{
pos = init_pos;
vel = init_vel;
rot = init_rot;
angular_vel = init_angular_vel;
age = 0.0f;
scale = 1.0f;
}
};
class ParticleSystem
{
public:
vector<Particle> particles;
RandomNumberGenerator rn;
vec2 circle_pos = { 0.0f, -0.2f };
float circle_radius = 0.3f;
ParticleSystem()
{
// reset(init_pos);
}
auto getRandomUnitVector()
{
const float theta = rn.getFloat(0.0f, 3.141592f * 2.0f); // 0.0 ~ 2pi
return vec2{ cos(theta), -sin(theta) };
}
auto getRandomColor()
{
return RGB{ rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f), rn.getFloat(0.0f, 1.0f) };
}
void reset(vec2 init_pos = { 0.0f, 0.5f })
{
particles.clear();
// initialize particles
for (int i = 0; i < 1000; ++i)
{
Particle new_particle;
new_particle.init_pos = init_pos + getRandomUnitVector() * rn.getFloat(0.001f, 0.03f);
new_particle.init_vel = getRandomUnitVector() * rn.getFloat(0.01f, 2.0f);
new_particle.color = getRandomColor();
new_particle.life = rn.getFloat(0.1f, 0.5f);
new_particle.init_rot = rn.getFloat(0.0f, 360.0f);
new_particle.init_angular_vel = rn.getFloat(-1.0f, 1.0f) * 360.0f * 4.0f;
new_particle.reset();
particles.push_back(new_particle);
}
}
void update(const float & dt)
{
const float epsilon = 0.5f;
for (auto& pt : particles)
{
pt.update(dt);
}
// check collision between particles and a circle
for (auto& pt : particles)
{
const float distance = (pt.pos - circle_pos).getMagnitude();
if (distance <= 0.03f * pt.scale + circle_radius)
{
// compute impulse
const auto normal = (pt.pos - circle_pos) / distance;
if (pt.vel.getDotProduct(normal) < 0.0f) // approaching
{
const auto impulse = normal * -(1.0f + epsilon) * pt.vel.getDotProduct(normal) /
((1.0f / 5.0f) + (1.0f / pt.scale));
pt.vel += impulse / pt.scale;
}
}
}
}
void draw()
{
beginTransformation();
beginTransformation();
translate(circle_pos);
drawFilledCircle(Colors::red, 0.3f);
endTransformation();
for (auto & pt : particles)
{
if (pt.age > pt.life) {
pt.reset();
continue;
}
const float alpha = 1.0f - pt.age / pt.life;
const RGB blended_color = { pt.color.r * alpha + 1.0f * (1.0f - alpha),
pt.color.g * alpha + 1.0f * (1.0f - alpha),
pt.color.b * alpha + 1.0f * (1.0f - alpha) };
// drawPoint(blended_color, pt.pos, 3.0f);
beginTransformation();
translate(pt.pos);
rotate(pt.rot);
scale(pt.scale, pt.scale);
drawFilledStar(pt.color, 0.03f, 0.01f);
endTransformation();
}
endTransformation();
}
};
class Example : public Game2D
{
public:
ParticleSystem ps;
Example()
: Game2D()
{
reset();
}
void reset()
{
ps.reset();
}
void update() override
{
const float dt = getTimeStep() * 0.4f;
ps.update(dt);
ps.draw();
// reset button
if (isKeyPressedAndReleased(GLFW_KEY_R)) reset();
}
};
}

'개발 > 게임개발' 카테고리의 다른 글
브레젠험 알고리즘 (0) | 2023.07.24 |
---|---|
[C/C++ 콘솔게임] 타이틀(알파벳) 생성기 (0) | 2023.05.07 |
c++ 게임만들기 연습문제 3.3 (1) | 2023.03.04 |
c++ 게임만들기 연습문제 3.2 (0) | 2023.03.02 |
c++ 게임만들기 연습문제 3.1 (0) | 2023.03.02 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 정보올림피아드
- unreal enigne
- 초등부
- 언리얼 프로젝트 재생성 자동화
- 백준
- C++게임개발
- 브레젠험 알고리즘
- 백준 27469
- 언리얼 프로젝트 재생성
- DP
- opengl
- C++게임
- 백준 2365
- ndisplay
- 테트리스
- ICPC 후기
- pygame
- 코드포스
- Codeforces
- BOJ 2365
- 언리얼 자동화
- 퀸 움직이기
- 숫자판 만들기
- OpenVDB
- UE5.3
- 홍정모의 게임 만들기 연습 문제 패키지
- BOJ 27469
- Python
- Unreal Engine
- tetris
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함