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