commit
9cc9512771
@ -0,0 +1,2 @@ |
||||
/target |
||||
**/*.rs.bk |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@ |
||||
[package] |
||||
name = "rustic_swarm" |
||||
version = "0.1.1" |
||||
authors = ["Cpt.Captain <nilskoch94@gmail.com>"] |
||||
edition = "2018" |
||||
|
||||
[dependencies] |
||||
rand = "0.6" |
||||
piston = "0.40.0" |
||||
piston2d-graphics = "0.29.0" |
||||
pistoncore-glutin_window = "0.52.0" |
||||
piston2d-opengl_graphics = "0.58.0" |
@ -0,0 +1,288 @@ |
||||
extern crate glutin_window; |
||||
extern crate graphics; |
||||
extern crate opengl_graphics; |
||||
extern crate piston; |
||||
extern crate rand; |
||||
|
||||
use glutin_window::GlutinWindow as Window; |
||||
use opengl_graphics::{GlGraphics, OpenGL}; |
||||
use piston::event_loop::*; |
||||
use piston::input::*; |
||||
use piston::window::WindowSettings; |
||||
use rand::seq::SliceRandom; |
||||
use std::f64::consts::PI; |
||||
|
||||
pub struct App { |
||||
gl: GlGraphics, |
||||
} |
||||
|
||||
#[derive(Clone)] |
||||
pub struct Object { |
||||
color: [f32; 4], |
||||
rotation: f64, |
||||
pos: Vec<f64>, |
||||
vel: Vec<f64>, |
||||
border_dist: Vec<f64>, |
||||
window_size: Vec<f64>, |
||||
} |
||||
|
||||
impl App { |
||||
fn render(&mut self, objs: &[Object], args: &RenderArgs) { |
||||
use graphics::*; |
||||
const BLACK: [f32; 4] = [0.1, 0.1, 0.1, 0.0]; |
||||
|
||||
// let square = rectangle::square(0.0, 0.0, 50.0);
|
||||
let square = rectangle::centered([0.0, 0.0, 40.0, 25.0]); |
||||
|
||||
self.gl.draw(args.viewport(), |c, gl| { |
||||
clear(BLACK, gl); |
||||
|
||||
for obj in objs { |
||||
let transform = c |
||||
.transform |
||||
.trans(obj.pos[0], obj.pos[1]) |
||||
.rot_rad(obj.rotation) |
||||
.trans(-35.0, -12.5); |
||||
|
||||
rectangle(obj.color, square, transform, gl); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
fn calc_amount(vec: &mut Vec<f64>) -> f64 { |
||||
(vec[0].powi(2) + vec[1].powi(2)).sqrt() |
||||
} |
||||
|
||||
impl Object { |
||||
pub fn new( |
||||
color: [f32; 4], |
||||
rotation: f64, |
||||
pos: Vec<f64>, |
||||
vel: Vec<f64>, |
||||
border_dist: Vec<f64>, |
||||
window_size: Vec<f64>, |
||||
) -> Object { |
||||
Object { |
||||
color, |
||||
rotation, |
||||
pos, |
||||
vel, |
||||
border_dist, |
||||
window_size, |
||||
} |
||||
} |
||||
|
||||
pub fn new_rand(color: [f32; 4]) -> Object { |
||||
Object::new( |
||||
color, |
||||
rand::random::<f64>(), |
||||
vec![rand::random::<f64>(); 2], |
||||
vec![rand::random::<f64>(); 2], |
||||
vec![rand::random::<f64>(); 2], |
||||
vec![0.0, 0.0], |
||||
) |
||||
} |
||||
|
||||
fn get_pos(&mut self) -> Vec<f64> { |
||||
self.pos.clone() |
||||
} |
||||
|
||||
fn update_border_dist(&mut self, args: &RenderArgs) { |
||||
self.window_size = vec![args.width, args.height]; |
||||
|
||||
let mut middle: Vec<f64> = Vec::new(); |
||||
for size in &self.window_size { |
||||
middle.push(size / 2.0); |
||||
} |
||||
|
||||
for (i, pos) in &mut self.pos.iter().enumerate() { |
||||
if pos < &mut middle[i as usize] { |
||||
self.border_dist[i as usize] = *pos; |
||||
} else { |
||||
self.border_dist[i as usize] = self.window_size[i as usize] - *pos; |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn edge_repel(weighted_bd: f64, vel: f64, limiter: f64) -> f64 { |
||||
rand::random::<f64>() * 0.1 * vel.abs().round().min(4.0).max(2.0) / weighted_bd.max(limiter) |
||||
} |
||||
|
||||
fn mouse_attract(&mut self, mouse_pos: [f64; 2]) { |
||||
let pos: Vec<f64> = self.get_pos(); |
||||
let mut dist: Vec<f64> = vec![pos[0] - mouse_pos[0], pos[1] - mouse_pos[1]]; |
||||
let amount = calc_amount(&mut dist); |
||||
for (i, d) in dist.iter().enumerate() { |
||||
self.vel[i] -= 0.2 * d / amount.max(0.1); |
||||
self.vel[i] = self.vel[i].min(10.0).max(-10.0); |
||||
} |
||||
} |
||||
|
||||
fn attract(&mut self, objs: &mut Vec<Vec<f64>>) { |
||||
let this_pos: Vec<f64> = self.get_pos(); |
||||
let mut distances: Vec<Vec<f64>> = Vec::new(); |
||||
for obj_pos in objs { |
||||
let mut dist_vec: Vec<f64> = Vec::new(); |
||||
for (i, op) in obj_pos.iter().enumerate() { |
||||
dist_vec.push(op - this_pos[i]); |
||||
} |
||||
distances.push(dist_vec); |
||||
} |
||||
for mut dist in distances { |
||||
let amount = calc_amount(&mut dist); |
||||
for (i, d) in dist.iter().enumerate() { |
||||
self.vel[i] += 1.0 * (d / amount.max(0.01)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn repel(&mut self, obj_pos: &mut Vec<Vec<f64>>) { |
||||
let this_pos: Vec<f64> = self.get_pos(); |
||||
for pos in obj_pos { |
||||
let mut dist_vec: Vec<f64> = Vec::new(); |
||||
for i in 0..2 { |
||||
dist_vec.push(this_pos[i] - pos[i]); |
||||
} |
||||
let amount = calc_amount(&mut dist_vec); |
||||
|
||||
for (i, d) in dist_vec.iter().enumerate() { |
||||
self.vel[i] += 1.5 * d.min(150.0).max(-150.0) / (amount).max(0.01); |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn calc_vel(&mut self) -> Vec<f64> { |
||||
let mut vel: Vec<f64> = Vec::new(); |
||||
for i in 0..2 { |
||||
let weighted_bd: f64 = self.border_dist[i] / (self.window_size[i] / 2.0); |
||||
let mut change = Object::edge_repel(weighted_bd, self.vel[i], 0.1); |
||||
change *= change; |
||||
if self.pos[i] > self.window_size[i] / 2.0 { |
||||
change = -change; |
||||
} |
||||
vel.push(self.vel[i] + (change * weighted_bd)) |
||||
} |
||||
vel |
||||
} |
||||
|
||||
fn update_vel(&mut self, new_vel: Vec<f64>) { |
||||
for (i, d) in new_vel.iter().enumerate() { |
||||
self.vel[i] = ((self.vel[i] + d) / 2.0).max(-10.0).min(10.0); |
||||
} |
||||
let amount = calc_amount(&mut self.vel); |
||||
for i in 0..2 { |
||||
self.vel[i] *= 10.0 / amount; |
||||
} |
||||
} |
||||
|
||||
fn move_me(&mut self) { |
||||
for i in 0..2 { |
||||
if self.window_size[i] < self.pos[i] + self.vel[i] || self.pos[i] + self.vel[i] < 0.0 { |
||||
if self.pos[i] + self.vel[i] < 0.0 { |
||||
self.pos[i] = self.window_size[i]; |
||||
self.vel[i] *= 0.2; |
||||
} else { |
||||
self.pos[i] = 0.0; |
||||
} |
||||
} |
||||
self.pos[i] += self.vel[i]; |
||||
} |
||||
} |
||||
|
||||
fn calc_direction(&mut self) -> f64 { |
||||
let mut dir = (self.vel[0] / calc_amount(&mut self.vel)).acos(); |
||||
if self.vel[1].signum() < 0.0 { |
||||
dir = 2.0 * PI - dir; |
||||
} |
||||
dir |
||||
} |
||||
|
||||
fn update(&mut self) { |
||||
let new_vel = self.calc_vel(); |
||||
self.update_vel(new_vel); |
||||
self.move_me(); |
||||
let dir = self.calc_direction(); |
||||
self.rotation = dir; |
||||
} |
||||
} |
||||
|
||||
fn main() { |
||||
println!("Hello there!"); |
||||
let mut m_attract = false; |
||||
|
||||
const RED: [f32; 4] = [1.0, 0.0, 0.0, 0.8]; |
||||
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0]; |
||||
|
||||
const FRUNK: [f32; 4] = [0.0, 0.0, 1.0, 0.8]; |
||||
const GNORM: [f32; 4] = [1.0, 1.0, 0.0, 0.8]; |
||||
|
||||
const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 0.8]; |
||||
|
||||
let colors = [RED, FRUNK, GNORM, WHITE, GREEN]; |
||||
|
||||
let opengl = OpenGL::V3_2; |
||||
|
||||
let num_objs = 12; |
||||
|
||||
let mut window: Window = WindowSettings::new("Test", [200, 200]) |
||||
.opengl(opengl) |
||||
.exit_on_esc(true) |
||||
.build() |
||||
.unwrap(); |
||||
|
||||
let mut app = App { |
||||
gl: GlGraphics::new(opengl), |
||||
}; |
||||
|
||||
let mut objects = Vec::new(); |
||||
for _ in 0..num_objs { |
||||
objects.push(Object::new_rand( |
||||
*colors |
||||
.choose(&mut rand::thread_rng()) |
||||
.expect("Color failure!"), |
||||
)) |
||||
} |
||||
|
||||
let mut positions: Vec<Vec<f64>> = Vec::new(); |
||||
|
||||
let mut events = Events::new(EventSettings::new()); |
||||
while let Some(e) = events.next(&mut window) { |
||||
if let Some(r) = e.render_args() { |
||||
for obj in &mut objects { |
||||
obj.update_border_dist(&r); |
||||
obj.update(); |
||||
positions.push(obj.get_pos()); |
||||
} |
||||
app.render(&objects, &r); |
||||
} |
||||
|
||||
if let Some(_u) = e.update_args() { |
||||
for obj in &mut objects { |
||||
obj.attract(&mut positions); |
||||
obj.repel(&mut positions); |
||||
} |
||||
positions.clear() |
||||
} |
||||
|
||||
if let Some(p) = e.press_args() { |
||||
if p == Button::Mouse(MouseButton::Left) { |
||||
m_attract = true; |
||||
} |
||||
} |
||||
|
||||
if let Some(r) = e.release_args() { |
||||
if r == Button::Mouse(MouseButton::Left) { |
||||
m_attract = false; |
||||
} |
||||
} |
||||
|
||||
if let Some(c) = e.mouse_cursor_args() { |
||||
if m_attract { |
||||
for obj in &mut objects { |
||||
obj.mouse_attract(c); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue