Add explosion effect in 2d physics engine
This commit is contained in:
parent
7cf2a1d5ca
commit
980d3e856b
3 changed files with 40 additions and 12 deletions
|
|
@ -70,7 +70,7 @@ struct physics_2d_app
|
|||
|
||||
float const inf = std::numeric_limits<float>::infinity();
|
||||
|
||||
material = physics.add_material({1.f, 0.5f, 0.9f});
|
||||
material = physics.add_material({1.f, 0.5f, 0.5f});
|
||||
|
||||
ball_shape = physics.add_shape(phys2d::ball{ball_radius});
|
||||
ball_group = physics.create_group();
|
||||
|
|
@ -78,12 +78,14 @@ struct physics_2d_app
|
|||
box_shape = physics.add_shape(phys2d::box{box_width, box_height});
|
||||
box_group = physics.create_group();
|
||||
|
||||
if(false)
|
||||
for (int x = -4; x <= 4; ++x)
|
||||
int nx = std::ceil(simulation_box[0].length() / box_width);
|
||||
int ny = std::ceil(simulation_box[1].length() / box_height);
|
||||
|
||||
for (int x = 0; x < nx; ++x)
|
||||
{
|
||||
for (int y = 0; y < 3; ++y)
|
||||
for (int y = 0; y < ny / 3; ++y)
|
||||
{
|
||||
geom::point<float, 2> pos{simulation_box[0].center() + x * box_width, simulation_box[1].min + (y + 0.5f) * box_height};
|
||||
geom::point<float, 2> pos{simulation_box.corner((x + 0.5f) / nx, (y + 0.5f) / ny)};
|
||||
physics.add_object(box_group, box_shape, material, {pos, 0.f}, {});
|
||||
}
|
||||
}
|
||||
|
|
@ -103,9 +105,9 @@ struct physics_2d_app
|
|||
auto wall_3_shape = physics.add_shape(phys2d::half_space{{0.f, -1.f}, -simulation_box[1].max});
|
||||
physics.add_object(wall_group, wall_3_shape, wall_material, {}, {});
|
||||
|
||||
auto task = util::recursive([this, dx = 0.1f](auto && self) mutable -> void {
|
||||
// physics.add_object(box_group, box_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {});
|
||||
physics.add_object(ball_group, ball_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {});
|
||||
auto task = util::recursive([this, dx = box_width * 0.4f](auto && self) mutable -> void {
|
||||
physics.add_object(box_group, box_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {});
|
||||
// physics.add_object(ball_group, ball_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {});
|
||||
|
||||
// float r = pcg::uniform_distribution<float>{0.05f, 0.5f}(gen);
|
||||
// auto new_shape = physics.add_shape(phys2d::ball{r});
|
||||
|
|
@ -113,8 +115,8 @@ struct physics_2d_app
|
|||
// radiuses.push_back(r);
|
||||
|
||||
dx *= -1.f;
|
||||
if (physics.group_size(box_group) < 200)
|
||||
loop.dispatch_at(std::chrono::system_clock::now() + std::chrono::milliseconds{250}, self);
|
||||
if (physics.group_size(box_group) < 100)
|
||||
loop.dispatch_at(std::chrono::system_clock::now() + std::chrono::milliseconds{100}, self);
|
||||
});
|
||||
(void)task;
|
||||
// task();
|
||||
|
|
@ -138,7 +140,7 @@ struct physics_2d_app
|
|||
|
||||
if (mouse)
|
||||
{
|
||||
physics.add_object(ball_group, ball_shape, material, {*mouse, 0.f}, {});
|
||||
physics.add_object(ball_group, ball_shape, material, {*mouse, 0.f}, {{0.f, 0.f}, 25.f});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +155,7 @@ struct physics_2d_app
|
|||
|
||||
if (mouse)
|
||||
{
|
||||
physics.add_object(box_group, box_shape, material, {*mouse, 0.f}, {});
|
||||
physics.explode(*mouse, 10.f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ namespace psemek::phys2d
|
|||
|
||||
void set_gravity(geom::vector<float, 2> const & g);
|
||||
|
||||
// Effects
|
||||
|
||||
void explode(geom::point<float, 2> const & center, float strength, float attenuation);
|
||||
|
||||
// Main update
|
||||
|
||||
void update(float dt);
|
||||
|
|
|
|||
|
|
@ -337,6 +337,8 @@ namespace psemek::phys2d
|
|||
|
||||
std::optional<geom::vector<float, 2>> gravity;
|
||||
|
||||
void explode(geom::point<float, 2> const & center, float strength, float attenuation);
|
||||
|
||||
void update(float dt);
|
||||
|
||||
void apply_gravity(float dt);
|
||||
|
|
@ -347,6 +349,21 @@ namespace psemek::phys2d
|
|||
float energy();
|
||||
};
|
||||
|
||||
void engine::impl::explode(geom::point<float, 2> const & center, float strength, float attenuation)
|
||||
{
|
||||
for (auto & g : groups)
|
||||
{
|
||||
for (std::size_t i = 0; i < g.infos.size(); ++i)
|
||||
{
|
||||
auto r = g.static_states[i].position - center;
|
||||
float l = geom::length(r);
|
||||
|
||||
auto J = (r / l) * strength / (1.f + l * l * attenuation);
|
||||
g.dynamic_states[i].velocity += J * g.infos[i].inv_mass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void engine::impl::update(float dt)
|
||||
{
|
||||
apply_gravity(dt);
|
||||
|
|
@ -640,6 +657,11 @@ namespace psemek::phys2d
|
|||
impl().gravity = g;
|
||||
}
|
||||
|
||||
void engine::explode(geom::point<float, 2> const & center, float strength, float attenuation)
|
||||
{
|
||||
impl().explode(center, strength, attenuation);
|
||||
}
|
||||
|
||||
void engine::update(float dt)
|
||||
{
|
||||
impl().update(dt);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue