initial commit

master
nkoch001 6 years ago
commit 9cc9512771
  1. 2
      .gitignore
  2. 1242
      Cargo.lock
  3. 12
      Cargo.toml
  4. 288
      src/main.rs

2
.gitignore vendored

@ -0,0 +1,2 @@
/target
**/*.rs.bk

1242
Cargo.lock generated

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…
Cancel
Save