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