Gave planets a particle system
This commit is contained in:
parent
e7a6dd1293
commit
e9fe0b5e87
1 changed files with 146 additions and 67 deletions
213
src/main.rs
213
src/main.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue