Gave planets a particle system

This commit is contained in:
Stephen Seo 2019-10-06 12:53:26 +09:00
parent e7a6dd1293
commit e9fe0b5e87

View file

@ -26,9 +26,9 @@ const DOUBLE_CLICK_TIME: f64 = 350.0;
fn interp_sq_inv(x: f32) -> f32 { fn interp_sq_inv(x: f32) -> f32 {
if x < 0.0 { if x < 0.0 {
return 0.0 return 0.0;
} else if x > 1.0 { } else if x > 1.0 {
return 1.0 return 1.0;
} }
let y = x - 1.0; let y = x - 1.0;
-y * y + 1.0 -y * y + 1.0
@ -36,9 +36,9 @@ fn interp_sq_inv(x: f32) -> f32 {
fn interp_sq(x: f32) -> f32 { fn interp_sq(x: f32) -> f32 {
if x < 0.0 { if x < 0.0 {
return 0.0 return 0.0;
} else if x > 1.0 { } else if x > 1.0 {
return 1.0 return 1.0;
} }
x * x x * x
} }
@ -478,15 +478,13 @@ impl Menu {
fn s_08() -> Menu { fn s_08() -> Menu {
Menu { Menu {
items: vec![ items: vec![Menu::instant_text(
Menu::instant_text( 50.0,
50.0, HEIGHT_F - 90.0,
HEIGHT_F - 90.0, 35.0,
35.0, true,
true, "(Try double-clicking now...)",
"(Try double-clicking now...)", )],
),
],
} }
} }
@ -494,15 +492,22 @@ impl Menu {
Menu { Menu {
items: vec![ items: vec![
Menu::pause(400.0, true), Menu::pause(400.0, true),
Menu::text(50.0, HEIGHT_F - 140.0, 40.0, false, Menu::text(
"A new planet... It has most certainly been a while."), 50.0,
] HEIGHT_F - 140.0,
40.0,
false,
"A new planet... It has most certainly been a while.",
),
],
} }
} }
} }
struct Particle { struct Particle {
rect: Rectangle, rect: Rectangle,
circle: Circle,
is_rect: bool,
velx: f32, velx: f32,
vely: f32, vely: f32,
velr: f32, velr: f32,
@ -517,9 +522,12 @@ struct ParticleSystem {
spawn_time: f64, spawn_time: f64,
lifetime: f64, lifetime: f64,
host_rect: Rectangle, host_rect: Rectangle,
host_circle: Circle,
is_rect: bool,
direction: Vector, direction: Vector,
color: Color, color: Color,
opacity: f32, opacity: f32,
vel_multiplier: f32,
} }
impl ParticleSystem { impl ParticleSystem {
@ -527,9 +535,12 @@ impl ParticleSystem {
spawn_time: f64, spawn_time: f64,
lifetime: f64, lifetime: f64,
host_rect: Rectangle, host_rect: Rectangle,
host_circle: Circle,
is_rect: bool,
direction: Vector, direction: Vector,
color: Color, color: Color,
opacity: f32, opacity: f32,
vel_multiplier: f32,
) -> Self { ) -> Self {
Self { Self {
particles: Vec::new(), particles: Vec::new(),
@ -537,9 +548,12 @@ impl ParticleSystem {
spawn_time, spawn_time,
lifetime, lifetime,
host_rect, host_rect,
host_circle,
is_rect,
direction, direction,
color, color,
opacity, opacity,
vel_multiplier,
} }
} }
@ -549,9 +563,14 @@ impl ParticleSystem {
if self.particles[i].life_timer > self.particles[i].lifetime { if self.particles[i].life_timer > self.particles[i].lifetime {
self.particles.swap_remove(i); self.particles.swap_remove(i);
} else { } else {
self.particles[i].rect.pos.x += self.particles[i].velx * dt as f32; if self.is_rect {
self.particles[i].rect.pos.y += self.particles[i].vely * dt as f32; self.particles[i].rect.pos.x += self.particles[i].velx * dt as f32;
self.particles[i].r += self.particles[i].velr * dt as f32; self.particles[i].rect.pos.y += self.particles[i].vely * dt as f32;
self.particles[i].r += self.particles[i].velr * dt as f32;
} else {
self.particles[i].circle.pos.x += self.particles[i].velx * dt as f32;
self.particles[i].circle.pos.y += self.particles[i].vely * dt as f32;
}
} }
} }
@ -560,16 +579,21 @@ impl ParticleSystem {
self.spawn_timer -= self.spawn_time; self.spawn_timer -= self.spawn_time;
self.particles.push(Particle { self.particles.push(Particle {
rect: self.host_rect, rect: self.host_rect,
velx: rand::thread_rng() circle: self.host_circle,
is_rect: self.is_rect,
velx: (rand::thread_rng()
.gen_range(-PARTICLE_RAND_VEL_RANGE, PARTICLE_RAND_VEL_RANGE) .gen_range(-PARTICLE_RAND_VEL_RANGE, PARTICLE_RAND_VEL_RANGE)
+ self.direction.x, + self.direction.x)
vely: rand::thread_rng() * self.vel_multiplier,
vely: (rand::thread_rng()
.gen_range(-PARTICLE_RAND_VEL_RANGE, PARTICLE_RAND_VEL_RANGE) .gen_range(-PARTICLE_RAND_VEL_RANGE, PARTICLE_RAND_VEL_RANGE)
+ self.direction.y, + self.direction.y)
* self.vel_multiplier,
// velx: self.direction.x, // velx: self.direction.x,
// vely: self.direction.y, // vely: self.direction.y,
velr: rand::thread_rng() velr: rand::thread_rng()
.gen_range(-PARTICLE_RAND_ROT_RANGE, PARTICLE_RAND_ROT_RANGE), .gen_range(-PARTICLE_RAND_ROT_RANGE, PARTICLE_RAND_ROT_RANGE)
* self.vel_multiplier,
r: rand::thread_rng().gen_range(0.0, 90.0), r: rand::thread_rng().gen_range(0.0, 90.0),
lifetime: self.lifetime, lifetime: self.lifetime,
life_timer: 0.0, life_timer: 0.0,
@ -583,15 +607,20 @@ impl ParticleSystem {
} }
for particle in &mut self.particles { for particle in &mut self.particles {
self.color.a = (1.0 - (particle.life_timer / particle.lifetime) as f32) * self.opacity; self.color.a = (1.0 - (particle.life_timer / particle.lifetime) as f32) * self.opacity;
let pre_transform = if particle.is_rect {
Transform::translate((-particle.rect.size.x / 2.0, -particle.rect.size.y / 2.0)) let pre_transform = Transform::translate((
* Transform::rotate(particle.r); -particle.rect.size.x / 2.0,
window.draw_ex( -particle.rect.size.y / 2.0,
&particle.rect, )) * Transform::rotate(particle.r);
Col(self.color), window.draw_ex(
transform * pre_transform, &particle.rect,
1, Col(self.color),
); transform * pre_transform,
1,
);
} else {
window.draw_ex(&particle.circle, Col(self.color), transform, 1);
}
} }
} }
} }
@ -608,16 +637,27 @@ impl RotatingParticleSystem {
spawn_time: f64, spawn_time: f64,
lifetime: f64, lifetime: f64,
host_rect: Rectangle, host_rect: Rectangle,
host_circle: Circle,
is_rect: bool,
direction: Vector, direction: Vector,
color: Color, color: Color,
opacity: f32, opacity: f32,
rotation: f32, rotation: f32,
velr: f32, velr: f32,
offset: f32, offset: f32,
vel_multiplier: f32,
) -> Self { ) -> Self {
RotatingParticleSystem { RotatingParticleSystem {
particle_system: ParticleSystem::new( particle_system: ParticleSystem::new(
spawn_time, lifetime, host_rect, direction, color, opacity, spawn_time,
lifetime,
host_rect,
host_circle,
is_rect,
direction,
color,
opacity,
vel_multiplier,
), ),
r: rotation, r: rotation,
velr, velr,
@ -641,17 +681,26 @@ impl RotatingParticleSystem {
self.particle_system.direction = self.particle_system.direction =
Transform::rotate(self.r) * Vector::new(0.0, -PARTICLE_RAND_VEL_DIST); Transform::rotate(self.r) * Vector::new(0.0, -PARTICLE_RAND_VEL_DIST);
self.particle_system.draw(window, transform); self.particle_system.draw(window, transform);
let mut moved_rect = self.particle_system.host_rect; if self.particle_system.is_rect {
moved_rect.pos += Transform::rotate(self.r) * Vector::new(self.offset, 0.0); let mut moved_rect = self.particle_system.host_rect;
let mut solid_color = self.particle_system.color; moved_rect.pos += Transform::rotate(self.r) * Vector::new(self.offset, 0.0);
solid_color.a = self.particle_system.opacity; let mut solid_color = self.particle_system.color;
window.draw_ex( solid_color.a = self.particle_system.opacity;
&moved_rect, window.draw_ex(
Col(solid_color), &moved_rect,
Transform::translate((-moved_rect.size.x / 2.0, -moved_rect.size.y / 2.0)) Col(solid_color),
* Transform::rotate(self.r * 1.3), transform
1, * Transform::translate((-moved_rect.size.x / 2.0, -moved_rect.size.y / 2.0))
); * Transform::rotate(self.r * 1.3),
1,
);
} else {
let mut moved_cir = self.particle_system.host_circle;
moved_cir.pos += Transform::rotate(self.r) * Vector::new(self.offset, 0.0);
let mut solid_color = self.particle_system.color;
solid_color.a = self.particle_system.opacity;
window.draw_ex(&moved_cir, Col(solid_color), transform, 1);
}
} }
} }
@ -671,12 +720,7 @@ struct ExplConvParticleSystem {
} }
impl ExplConvParticleSystem { impl ExplConvParticleSystem {
fn new( fn new(lifetime: f64, host_circle: Circle, color: Color, opacity: f32) -> Self {
lifetime: f64,
host_circle: Circle,
color: Color,
opacity: f32,
) -> Self {
ExplConvParticleSystem { ExplConvParticleSystem {
particles: Vec::new(), particles: Vec::new(),
lifetime, lifetime,
@ -704,7 +748,7 @@ impl ExplConvParticleSystem {
if self.life_timer >= self.lifetime { if self.life_timer >= self.lifetime {
if !self.particles.is_empty() { if !self.particles.is_empty() {
self.particles.clear(); self.particles.clear();
planets.push(Planet{ circle: self.host_circle, color: self.color, }); planets.push(Planet::new(self.host_circle, self.color));
return true; return true;
} }
return false; return false;
@ -713,15 +757,15 @@ impl ExplConvParticleSystem {
if self.life_timer < self.lifetime / 2.0 { if self.life_timer < self.lifetime / 2.0 {
let amount = interp_sq_inv((self.life_timer / self.lifetime) as f32 * 2.0); let amount = interp_sq_inv((self.life_timer / self.lifetime) as f32 * 2.0);
for particle in &mut self.particles { for particle in &mut self.particles {
let dir = Transform::rotate(particle.r) * Vector::new( let dir =
particle.offset * amount, 0.0); Transform::rotate(particle.r) * Vector::new(particle.offset * amount, 0.0);
particle.circle.pos = dir + self.host_circle.pos; particle.circle.pos = dir + self.host_circle.pos;
} }
} else { } else {
let amount = 1.0 - interp_sq(((self.life_timer / self.lifetime) as f32 - 0.5) * 2.0); let amount = 1.0 - interp_sq(((self.life_timer / self.lifetime) as f32 - 0.5) * 2.0);
for particle in &mut self.particles { for particle in &mut self.particles {
let dir = Transform::rotate(particle.r) * Vector::new( let dir =
particle.offset * amount, 0.0); Transform::rotate(particle.r) * Vector::new(particle.offset * amount, 0.0);
particle.circle.pos = dir + self.host_circle.pos; particle.circle.pos = dir + self.host_circle.pos;
} }
} }
@ -734,12 +778,7 @@ impl ExplConvParticleSystem {
} }
for particle in &mut self.particles { for particle in &mut self.particles {
self.color.a = ((self.life_timer / self.lifetime) as f32 / 2.0 + 0.5) * self.opacity; self.color.a = ((self.life_timer / self.lifetime) as f32 / 2.0 + 0.5) * self.opacity;
window.draw_ex( window.draw_ex(&particle.circle, Col(self.color), transform, 1);
&particle.circle,
Col(self.color),
transform,
1,
);
} }
} }
} }
@ -747,6 +786,36 @@ impl ExplConvParticleSystem {
struct Planet { struct Planet {
circle: Circle, circle: Circle,
color: Color, color: Color,
particle_system: ParticleSystem,
}
impl Planet {
fn new(circle: Circle, color: Color) -> Self {
Planet {
circle,
color,
particle_system: ParticleSystem::new(
3500.0,
900.0,
Rectangle::new((0.0, 0.0), (1.0, 1.0)),
circle,
false,
Vector::new(0.0, 0.0),
color,
1.0,
0.3,
),
}
}
fn update(&mut self, dt: f64) {
self.particle_system.update(dt);
}
fn draw(&mut self, window: &mut Window, transform: Transform) {
self.particle_system.draw(window, transform);
window.draw_ex(&self.circle, Col(self.color), transform, 1);
}
} }
struct GameState { struct GameState {
@ -802,20 +871,26 @@ impl State for GameState {
PP_GEN_RATE, PP_GEN_RATE,
1000.0, 1000.0,
Rectangle::new((400.0, 300.0), (32.0, 32.0)), Rectangle::new((400.0, 300.0), (32.0, 32.0)),
Circle::new((100.0, 100.0), 32.0),
true,
Vector::new(0.0, 0.0), Vector::new(0.0, 0.0),
Color::WHITE, Color::WHITE,
0.0, 0.0,
1.0,
), ),
joining_particles: RotatingParticleSystem::new( joining_particles: RotatingParticleSystem::new(
PP_GEN_RATE, PP_GEN_RATE,
1000.0, 1000.0,
Rectangle::new((400.0, 300.0), (16.0, 16.0)), Rectangle::new((400.0, 300.0), (16.0, 16.0)),
Circle::new((100.0, 100.0), 32.0),
true,
Vector::new(0.0, 0.0), Vector::new(0.0, 0.0),
Color::GREEN, Color::GREEN,
0.0, 0.0,
0.0, 0.0,
0.1, 0.1,
JOINING_FAR_DIST, JOINING_FAR_DIST,
1.0,
), ),
is_create_mode: false, is_create_mode: false,
click_release_time: 0.0, click_release_time: 0.0,
@ -852,8 +927,10 @@ impl State for GameState {
if self.click_release_time < DOUBLE_CLICK_TIME { if self.click_release_time < DOUBLE_CLICK_TIME {
if self.state == 8 { if self.state == 8 {
let mut expl_conv_system = ExplConvParticleSystem::new( let mut expl_conv_system = ExplConvParticleSystem::new(
1500.0, Circle::new(self.mouse_pos, 20.0), 1500.0,
Color::GREEN, 1.0, Circle::new(self.mouse_pos, 20.0),
Color::GREEN,
1.0,
); );
expl_conv_system.activate(30, 200.0); expl_conv_system.activate(30, 200.0);
self.expl_conv_p_systems.push(expl_conv_system); self.expl_conv_p_systems.push(expl_conv_system);
@ -861,8 +938,7 @@ impl State for GameState {
self.state_dirty = true; self.state_dirty = true;
} }
} }
} } else if self.selection_mode {
else if self.selection_mode {
if let Some(idx) = self.current_item { if let Some(idx) = self.current_item {
match self.state { match self.state {
0 => { 0 => {
@ -1182,6 +1258,9 @@ impl State for GameState {
self.expl_conv_p_systems.swap_remove(i); self.expl_conv_p_systems.swap_remove(i);
} }
} }
for planet in &mut self.planets {
planet.update(dt);
}
Ok(()) Ok(())
} }
@ -1263,7 +1342,7 @@ impl State for GameState {
expl_conv_ps.draw(window, Transform::IDENTITY); expl_conv_ps.draw(window, Transform::IDENTITY);
} }
for planet in &mut self.planets { for planet in &mut self.planets {
window.draw(&planet.circle, Col(planet.color)); planet.draw(window, Transform::IDENTITY);
} }
Ok(()) Ok(())
} }