Add fish as possible creatable
This commit is contained in:
parent
3a1b734fa2
commit
bb37e67f2e
2 changed files with 167 additions and 2 deletions
169
src/main.rs
169
src/main.rs
|
@ -994,10 +994,121 @@ impl Star {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
struct Fish {
|
||||||
|
pos: Vector,
|
||||||
|
r: f32,
|
||||||
|
swim_time: f64,
|
||||||
|
swim_timer: f64,
|
||||||
|
swim_v: f32,
|
||||||
|
anim_timer: f64,
|
||||||
|
anim_time: f64,
|
||||||
|
color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FishState {
|
||||||
|
Idle,
|
||||||
|
Swim,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fish {
|
||||||
|
fn new(pos: Vector, r: f32, color: Color) -> Self {
|
||||||
|
let anim_timer = rand::thread_rng().gen_range(800.0, 1000.0);
|
||||||
|
Self {
|
||||||
|
pos,
|
||||||
|
r,
|
||||||
|
swim_time: 800.0,
|
||||||
|
swim_timer: 800.0,
|
||||||
|
swim_v: 0.2,
|
||||||
|
anim_timer,
|
||||||
|
anim_time: anim_timer,
|
||||||
|
color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_next(&mut self, state: FishState) {
|
||||||
|
match state {
|
||||||
|
FishState::Idle => {
|
||||||
|
self.swim_time = rand::thread_rng().gen_range(1100.0, 2400.0);
|
||||||
|
self.swim_timer = self.swim_time;
|
||||||
|
self.anim_timer = 1600.0;
|
||||||
|
self.anim_time = 1600.0;
|
||||||
|
self.swim_v = 0.0;
|
||||||
|
}
|
||||||
|
FishState::Swim => {
|
||||||
|
self.swim_time = rand::thread_rng().gen_range(1400.0, 2300.0);
|
||||||
|
self.swim_timer = self.swim_time;
|
||||||
|
self.r = rand::thread_rng().gen_range(0.0, 360.0);
|
||||||
|
self.anim_timer = rand::thread_rng().gen_range(600.0, 1000.0);
|
||||||
|
self.anim_time = self.anim_timer;
|
||||||
|
self.swim_v = (self.anim_timer / 8000.0) as f32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, dt: f64) {
|
||||||
|
self.swim_time -= dt;
|
||||||
|
if self.swim_time < 220.0 {
|
||||||
|
self.swim_v /= 1.1;
|
||||||
|
}
|
||||||
|
if self.swim_time <= 0.0 {
|
||||||
|
if rand::thread_rng().gen_bool(0.4) {
|
||||||
|
self.set_next(FishState::Idle);
|
||||||
|
} else {
|
||||||
|
self.set_next(FishState::Swim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_timer -= dt;
|
||||||
|
if self.anim_timer <= 0.0 {
|
||||||
|
self.anim_timer = self.anim_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pos += Transform::rotate(self.r) * Vector::new(self.swim_v, 0.0) * dt as f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&mut self,
|
||||||
|
fish_body: &Image,
|
||||||
|
fish_tail: &Image,
|
||||||
|
window: &mut Window,
|
||||||
|
transform: Transform,
|
||||||
|
) {
|
||||||
|
let anim_angle = ((self.anim_timer / self.anim_time) * std::f64::consts::PI * 2.0).sin();
|
||||||
|
let mut body_rect = fish_body.area();
|
||||||
|
body_rect.pos = self.pos - body_rect.size / 2.0;
|
||||||
|
let body_tr =
|
||||||
|
Transform::rotate(anim_angle as f32 * 30.0) * Transform::rotate(self.r + 180.0);
|
||||||
|
window.draw_ex(
|
||||||
|
&body_rect,
|
||||||
|
Blended(fish_body, self.color),
|
||||||
|
transform * body_tr,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
let mut tail_rect = fish_tail.area();
|
||||||
|
tail_rect.pos = self.pos - tail_rect.size / 2.0;
|
||||||
|
let anim_angle = ((self.anim_timer / self.anim_time) * std::f64::consts::PI * 2.0
|
||||||
|
- std::f64::consts::PI / 3.0)
|
||||||
|
.sin();
|
||||||
|
let tail_tr = body_tr
|
||||||
|
* Transform::translate((body_rect.size.x / 1.5, 0.0))
|
||||||
|
* Transform::translate((-tail_rect.size.x / 2.0, 0.0))
|
||||||
|
* Transform::rotate(-anim_angle as f32 * 45.0)
|
||||||
|
* Transform::translate((tail_rect.size.x / 2.0, 0.0));
|
||||||
|
window.draw_ex(
|
||||||
|
&tail_rect,
|
||||||
|
Blended(fish_tail, self.color),
|
||||||
|
transform * tail_tr,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
struct SaveData {
|
struct SaveData {
|
||||||
planets: Vec<Planet>,
|
planets: Vec<Planet>,
|
||||||
stars: Vec<Star>,
|
stars: Vec<Star>,
|
||||||
|
fishes: Vec<Fish>,
|
||||||
player: Rectangle,
|
player: Rectangle,
|
||||||
joining_particles: RotatingParticleSystem,
|
joining_particles: RotatingParticleSystem,
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1129,9 @@ struct GameState {
|
||||||
music2: Asset<Sound>,
|
music2: Asset<Sound>,
|
||||||
i_star: Option<Asset<Image>>,
|
i_star: Option<Asset<Image>>,
|
||||||
i_star_actual: Option<Image>,
|
i_star_actual: Option<Image>,
|
||||||
|
i_fish: Asset<Image>,
|
||||||
|
i_fish_body: Option<Image>,
|
||||||
|
i_fish_tail: Option<Image>,
|
||||||
music_on: bool,
|
music_on: bool,
|
||||||
music_timer: f64,
|
music_timer: f64,
|
||||||
menu: Menu,
|
menu: Menu,
|
||||||
|
@ -1039,6 +1153,7 @@ struct GameState {
|
||||||
expl_conv_p_systems: Vec<ExplConvParticleSystem>,
|
expl_conv_p_systems: Vec<ExplConvParticleSystem>,
|
||||||
planets: Vec<Planet>,
|
planets: Vec<Planet>,
|
||||||
stars: Vec<Star>,
|
stars: Vec<Star>,
|
||||||
|
fishes: Vec<Fish>,
|
||||||
camera: Rectangle,
|
camera: Rectangle,
|
||||||
move_to: Vector,
|
move_to: Vector,
|
||||||
save_load_notification: Option<SaveLoadNotification>,
|
save_load_notification: Option<SaveLoadNotification>,
|
||||||
|
@ -1057,6 +1172,9 @@ impl State for GameState {
|
||||||
music2: Asset::new(Sound::load("music2.mp3")),
|
music2: Asset::new(Sound::load("music2.mp3")),
|
||||||
i_star: Some(Asset::new(Image::load("star.png"))),
|
i_star: Some(Asset::new(Image::load("star.png"))),
|
||||||
i_star_actual: None,
|
i_star_actual: None,
|
||||||
|
i_fish: Asset::new(Image::load("fish.png")),
|
||||||
|
i_fish_body: None,
|
||||||
|
i_fish_tail: None,
|
||||||
music_on: false,
|
music_on: false,
|
||||||
music_timer: 0.0,
|
music_timer: 0.0,
|
||||||
menu: Menu::start(),
|
menu: Menu::start(),
|
||||||
|
@ -1101,6 +1219,7 @@ impl State for GameState {
|
||||||
expl_conv_p_systems: Vec::new(),
|
expl_conv_p_systems: Vec::new(),
|
||||||
planets: Vec::new(),
|
planets: Vec::new(),
|
||||||
stars: Vec::new(),
|
stars: Vec::new(),
|
||||||
|
fishes: Vec::new(),
|
||||||
camera: Rectangle::new((0.0, 0.0), (WIDTH_F, HEIGHT_F)),
|
camera: Rectangle::new((0.0, 0.0), (WIDTH_F, HEIGHT_F)),
|
||||||
move_to: Vector::new(400.0, 300.0),
|
move_to: Vector::new(400.0, 300.0),
|
||||||
save_load_notification: None,
|
save_load_notification: None,
|
||||||
|
@ -1155,7 +1274,7 @@ impl State for GameState {
|
||||||
} else if self.state == 10 {
|
} else if self.state == 10 {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let rand_out = rng.gen_range(0.0, 1.0);
|
let rand_out = rng.gen_range(0.0, 1.0);
|
||||||
if rand_out < 0.75 {
|
if rand_out < 0.6 {
|
||||||
// spawn planet
|
// spawn planet
|
||||||
let mut expl_conv_system = ExplConvParticleSystem::new(
|
let mut expl_conv_system = ExplConvParticleSystem::new(
|
||||||
rng.gen_range(1200.0, 1600.0),
|
rng.gen_range(1200.0, 1600.0),
|
||||||
|
@ -1173,7 +1292,7 @@ impl State for GameState {
|
||||||
rng.gen_range(150.0, 300.0),
|
rng.gen_range(150.0, 300.0),
|
||||||
);
|
);
|
||||||
self.expl_conv_p_systems.push(expl_conv_system);
|
self.expl_conv_p_systems.push(expl_conv_system);
|
||||||
} else {
|
} else if rand_out < 0.85 {
|
||||||
// spawn star
|
// spawn star
|
||||||
let rot_clockwise = rng.gen_bool(0.5);
|
let rot_clockwise = rng.gen_bool(0.5);
|
||||||
self.stars.push(Star::new(
|
self.stars.push(Star::new(
|
||||||
|
@ -1191,6 +1310,20 @@ impl State for GameState {
|
||||||
},
|
},
|
||||||
rng.gen_range(0.0, 90.0),
|
rng.gen_range(0.0, 90.0),
|
||||||
));
|
));
|
||||||
|
} else {
|
||||||
|
// spawn fish
|
||||||
|
for i in 0..rng.gen_range(1, 3) {
|
||||||
|
self.fishes.push(Fish::new(
|
||||||
|
self.mouse_pos,
|
||||||
|
rng.gen_range(0.0, 360.0),
|
||||||
|
Color::from_rgba(
|
||||||
|
rng.gen_range(0x44, 0xFF),
|
||||||
|
rng.gen_range(0x44, 0xFF),
|
||||||
|
rng.gen_range(0x44, 0xFF),
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.s_boom.execute(|s| {
|
self.s_boom.execute(|s| {
|
||||||
s.set_volume(0.8);
|
s.set_volume(0.8);
|
||||||
|
@ -1318,6 +1451,7 @@ impl State for GameState {
|
||||||
let save_data = SaveData {
|
let save_data = SaveData {
|
||||||
planets: self.planets.clone(),
|
planets: self.planets.clone(),
|
||||||
stars: self.stars.clone(),
|
stars: self.stars.clone(),
|
||||||
|
fishes: self.fishes.clone(),
|
||||||
player: self.player.clone(),
|
player: self.player.clone(),
|
||||||
joining_particles: self.joining_particles.clone(),
|
joining_particles: self.joining_particles.clone(),
|
||||||
};
|
};
|
||||||
|
@ -1333,6 +1467,7 @@ impl State for GameState {
|
||||||
if let Ok(save_data) = load_result {
|
if let Ok(save_data) = load_result {
|
||||||
self.planets = save_data.planets;
|
self.planets = save_data.planets;
|
||||||
self.stars = save_data.stars;
|
self.stars = save_data.stars;
|
||||||
|
self.fishes = save_data.fishes;
|
||||||
self.player = save_data.player;
|
self.player = save_data.player;
|
||||||
self.joining_particles = save_data.joining_particles;
|
self.joining_particles = save_data.joining_particles;
|
||||||
self.expl_conv_p_systems.clear();
|
self.expl_conv_p_systems.clear();
|
||||||
|
@ -1473,6 +1608,7 @@ impl State for GameState {
|
||||||
self.expl_conv_p_systems.clear();
|
self.expl_conv_p_systems.clear();
|
||||||
self.planets.clear();
|
self.planets.clear();
|
||||||
self.stars.clear();
|
self.stars.clear();
|
||||||
|
self.fishes.clear();
|
||||||
self.player.pos = Vector::new(WIDTH_F / 2.0, HEIGHT_F / 2.0);
|
self.player.pos = Vector::new(WIDTH_F / 2.0, HEIGHT_F / 2.0);
|
||||||
self.move_to = Vector::new(WIDTH_F / 2.0, HEIGHT_F / 2.0);
|
self.move_to = Vector::new(WIDTH_F / 2.0, HEIGHT_F / 2.0);
|
||||||
self.camera.pos = Vector::new(0.0, 0.0);
|
self.camera.pos = Vector::new(0.0, 0.0);
|
||||||
|
@ -1674,6 +1810,27 @@ impl State for GameState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.i_fish_body.is_none() {
|
||||||
|
let mut body: Option<Image> = None;
|
||||||
|
self.i_fish.execute(|i| {
|
||||||
|
body = Some(i.subimage(Rectangle::new((0.0, 0.0), (32.0, 16.0))));
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
self.i_fish_body = body;
|
||||||
|
}
|
||||||
|
if self.i_fish_tail.is_none() {
|
||||||
|
let mut tail: Option<Image> = None;
|
||||||
|
self.i_fish.execute(|i| {
|
||||||
|
tail = Some(i.subimage(Rectangle::new((32.0, 0.0), (16.0, 16.0))));
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
self.i_fish_tail = tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for fish in &mut self.fishes {
|
||||||
|
fish.update(dt);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1763,6 +1920,14 @@ impl State for GameState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(body) = &self.i_fish_body {
|
||||||
|
if let Some(tail) = &self.i_fish_tail {
|
||||||
|
for fish in &mut self.fishes {
|
||||||
|
fish.draw(body, tail, window, Transform::IDENTITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(sl) = &mut self.save_load_notification {
|
if let Some(sl) = &mut self.save_load_notification {
|
||||||
match sl {
|
match sl {
|
||||||
SaveLoadNotification::Save { text, timer }
|
SaveLoadNotification::Save { text, timer }
|
||||||
|
|
BIN
static/fish.png
Normal file
BIN
static/fish.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 343 B |
Loading…
Reference in a new issue