initial commit
This commit is contained in:
commit
9cc9512771
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
1242
Cargo.lock
generated
Normal file
1242
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -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"
|
288
src/main.rs
Normal file
288
src/main.rs
Normal file
@ -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
Block a user