susuwatari-game/src/mobs/star.rs

135 lines
3.9 KiB
Rust
Raw Normal View History

use ai_behavior::Action;
use find_folder;
use gfx_device_gl::Resources;
use piston_window::*;
2017-07-13 22:53:30 +00:00
use ncollide::shape::Cuboid2;
use nalgebra::Vector2;
use sprite::*;
use uuid::Uuid;
2017-07-13 20:16:14 +00:00
use rand;
use std::rc::Rc;
2017-07-13 20:16:14 +00:00
use super::wrap;
2017-07-13 20:16:14 +00:00
pub struct Star {
2017-07-12 00:25:54 +00:00
pub sprite_id: Uuid,
pub x: f64,
pub y: f64,
2017-07-13 20:16:14 +00:00
w: f64,
h: f64,
2017-07-13 21:03:56 +00:00
dir: u32,
2017-07-13 22:53:30 +00:00
pub collider: Cuboid2<f64>,
pub destroyed: bool,
2017-08-08 18:02:57 +00:00
accel: f64,
}
const DESIGNED_FOR_WIDTH: f64 = 640.0;
const SCALE_FACTOR: f64 = 0.5;
const MOVE_DUR: f64 = 0.75;
const DESTROY_DUR: f64 = 0.75;
2017-07-13 20:16:14 +00:00
impl Star {
2017-08-08 18:02:57 +00:00
pub fn new(color: &str, w: &mut PistonWindow, scene: &mut Scene<Texture<Resources>>) -> Star {
let assets = find_folder::Search::ParentsThenKids(3, 3)
.for_folder("assets")
.unwrap();
let tex = Rc::new(Texture::from_path(&mut w.factory,
2017-08-08 18:02:57 +00:00
assets.join(format!("{}_star.png", color)),
Flip::None,
&TextureSettings::new())
.unwrap());
let Size { width, height } = w.size();
let x = rand_pos(width as f64);
let y = rand_pos(height as f64);
let scale = width as f64 / DESIGNED_FOR_WIDTH * SCALE_FACTOR;
2017-08-08 18:02:57 +00:00
let accel = match color {
"yellow" => 3.0,
"blue" => 1.0,
"green" => 2.0,
_ => 2.0,
};
let mut sprite = Sprite::from_texture(tex);
sprite.set_scale(scale, scale);
sprite.set_position(x, y);
2017-07-13 20:16:14 +00:00
let bounds = sprite.bounding_box();
let sprite_id = scene.add_child(sprite);
2017-07-13 20:16:14 +00:00
Star {
x: x,
y: y,
2017-07-13 20:16:14 +00:00
w: bounds[2],
h: bounds[3],
sprite_id: sprite_id,
2017-07-13 21:03:56 +00:00
dir: rand_dir(),
2017-07-13 22:53:30 +00:00
collider: Cuboid2::new(Vector2::new(bounds[2], bounds[3])),
destroyed: false,
2017-08-08 18:02:57 +00:00
accel: accel,
}
}
2017-07-13 20:16:14 +00:00
pub fn mov(&mut self, w: &PistonWindow, scene: &mut Scene<Texture<Resources>>, dt: f64) {
2017-07-13 22:53:30 +00:00
if self.destroyed {
return;
}
2017-07-12 00:25:54 +00:00
if let Some(sprite) = scene.child(self.sprite_id) {
let (sprite_x, sprite_y) = sprite.get_position();
self.x = sprite_x;
self.y = sprite_y;
}
let (wrapped, new_x, new_y) = wrap((w.size().width.into(), w.size().height.into()),
(self.w, self.h),
(self.x, self.y));
2017-07-12 00:25:54 +00:00
if wrapped {
if let Some(ref mut sprite) = scene.child_mut(self.sprite_id) {
2017-07-13 20:16:14 +00:00
self.x = new_x;
self.y = new_y;
2017-07-12 00:25:54 +00:00
sprite.set_position(self.x, self.y);
}
}
2017-07-13 21:03:56 +00:00
self.dir = rand_turn(self.dir);
let dir = lookup_dir(self.dir);
2017-08-08 18:02:57 +00:00
let mov_x = self.accel * dir.0;
let mov_y = self.accel * dir.1;
scene.run(self.sprite_id,
&Action(Ease(EaseFunction::CubicOut,
Box::new(MoveBy(dt * MOVE_DUR, mov_x, mov_y)))));
}
2017-07-13 22:53:30 +00:00
pub fn destroy(&mut self, scene: &mut Scene<Texture<Resources>>, dt: f64) {
scene.run(self.sprite_id,
&Action(Ease(EaseFunction::CubicOut, Box::new(FadeOut(dt * DESTROY_DUR)))));
2017-07-13 22:53:30 +00:00
self.destroyed = true;
}
}
2017-07-13 21:03:56 +00:00
fn rand_dir() -> u32 {
rand::random::<u32>() % 8
}
fn rand_pos(dim: f64) -> f64 {
(rand::random::<f64>() % dim).abs()
}
2017-07-13 21:03:56 +00:00
fn rand_turn(dir: u32) -> u32 {
let coin = rand::random::<i32>() % 10;
match coin {
-9 => if dir == 0 { 7 } else { dir - 1 },
9 => if dir == 7 { 0 } else { dir + 1 },
2017-07-13 21:03:56 +00:00
_ => dir,
}
}
fn lookup_dir(dir: u32) -> (f64, f64) {
match dir {
0 => (0.0, -1.0),
1 => (1.0, -1.0),
2 => (1.0, 0.0),
3 => (1.0, 1.0),
4 => (0.0, 1.0),
5 => (-1.0, 1.0),
6 => (-1.0, 0.0),
7 => (-1.0, -1.0),
_ => (0.0, 0.0),
}
}