Adds basic agent spawning

Adjusts camera to put viewport origin on the bottom left of the window
master
Joey Pollack 2 years ago
parent 9d5cb8d243
commit 36b60ada1d

37
Cargo.lock generated

@ -2076,6 +2076,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy_prototype_lyon", "bevy_prototype_lyon",
"rand",
] ]
[[package]] [[package]]
@ -2648,6 +2649,12 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.3.1" version = "1.3.1"
@ -2688,6 +2695,36 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17fd96390ed3feda12e1dfe2645ed587e0bea749e319333f104a33ff62f77a0b" checksum = "17fd96390ed3feda12e1dfe2645ed587e0bea749e319333f104a33ff62f77a0b"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]] [[package]]
name = "range-alloc" name = "range-alloc"
version = "0.1.3" version = "0.1.3"

@ -8,6 +8,7 @@ edition = "2021"
[dependencies] [dependencies]
bevy = "0.11.0" bevy = "0.11.0"
bevy_prototype_lyon = "0.9.0" bevy_prototype_lyon = "0.9.0"
rand = "0.8.5"
# Enable high optimizations for dependencies (incl. Bevy), but not for our code: # Enable high optimizations for dependencies (incl. Bevy), but not for our code:

@ -0,0 +1,19 @@
use bevy::{prelude::*};
#[derive(Component)]
pub struct Agent
{
pub pos_x: i32,
pub pos_y: i32,
}
impl Agent
{
pub fn new(x: i32, y: i32) -> Agent
{
Agent { pos_x: x, pos_y: y }
}
}

@ -11,9 +11,8 @@ use std::time::Instant;
mod world; mod world;
mod neural_net; mod neural_net;
mod agent;
#[derive(Component)] use agent::Agent;
struct Agent;
#[derive(Component)] #[derive(Component)]
struct FpsText; struct FpsText;
@ -60,7 +59,8 @@ fn main()
WorldPlugin { WorldPlugin {
grid_width: 100., grid_width: 100.,
grid_height: 100., grid_height: 100.,
top_margin: 50.0 top_margin: 50.0,
num_agents: 100,
}, },
ShapePlugin ShapePlugin
)) ))
@ -75,18 +75,25 @@ fn main()
fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>) fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>)
{ {
// Camera // Camera
commands.spawn(Camera2dBundle::default()); //commands.spawn(Camera2dBundle::default());
commands.spawn(Camera2dBundle{
projection: OrthographicProjection {
viewport_origin: Vec2 { x: 0.0, y: 0.0 },
..default()
},
..default()
});
// Circle // Circle
commands.spawn(( // commands.spawn((
MaterialMesh2dBundle { // MaterialMesh2dBundle {
mesh: meshes.add(shape::Circle::new(50.).into()).into(), // mesh: meshes.add(shape::Circle::new(50.).into()).into(),
material: materials.add(ColorMaterial::from(Color::PURPLE)), // material: materials.add(ColorMaterial::from(Color::PURPLE)),
transform: Transform::from_translation(Vec3::new(-150., 0., 0.)), // transform: Transform::from_translation(Vec3::new(0., 0., 0.)),
..default() // ..default()
}, // },
Agent // Agent::new(0, 0)
)); // ));
// UI // UI
// Text with multiple sections // Text with multiple sections
@ -112,6 +119,7 @@ fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials
} }
fn tick_simulation(mut state: ResMut<SimulationState>, delta_time: Res<Time>, mut query: Query<&mut Transform, With<Agent>>) fn tick_simulation(mut state: ResMut<SimulationState>, delta_time: Res<Time>, mut query: Query<&mut Transform, With<Agent>>)
//fn tick_simulation(mut state: ResMut<SimulationState>, delta_time: Res<Time>)
{ {
let now = Instant::now(); let now = Instant::now();
@ -120,22 +128,23 @@ fn tick_simulation(mut state: ResMut<SimulationState>, delta_time: Res<Time>, mu
// Tick the neural net // Tick the neural net
// Process agent actions // Process agent actions
let mut agent_transform = query.single_mut(); //let mut agent_transform = query.single_mut();
agent_transform.translation.x += 50.0 * delta_time.delta_seconds(); //agent_transform.translation.x += 100.0 * delta_time.delta_seconds();
//agent_transform.translation.y += 100.0 * delta_time.delta_seconds();
let elapsed_time = now.elapsed(); // let elapsed_time = now.elapsed();
state.last_gen_time += state.last_step_time; // state.last_gen_time += state.last_step_time;
state.last_step_time = elapsed_time.as_secs_f32(); // state.last_step_time = elapsed_time.as_secs_f32();
state.generation_step += 1; // state.generation_step += 1;
if state.generation_step >= state.max_gen_steps // if state.generation_step >= state.max_gen_steps
{ // {
// Move on to the next generation // // Move on to the next generation
state.generation += 1; // state.generation += 1;
} // }
} }
fn ui_update(mut state: Res<SimulationState>, diagnostics: Res<DiagnosticsStore>, mut query: Query<&mut Text, With<FpsText>>) fn ui_update(mut state: Res<SimulationState>, diagnostics: Res<DiagnosticsStore>, mut query: Query<&mut Text, With<FpsText>>)

@ -1,6 +1,8 @@
use bevy::{prelude::*, window::WindowResized}; use bevy::{prelude::*, window::WindowResized};
use bevy_prototype_lyon::prelude::*; use bevy_prototype_lyon::prelude::*;
use rand::prelude::*;
use crate::agent::Agent;
#[derive(Component)] #[derive(Component)]
struct GridLine; struct GridLine;
@ -14,6 +16,7 @@ struct WorldPluginState
grid_height: f32, grid_height: f32,
top_margin: f32, top_margin: f32,
num_agents: i32,
} }
pub struct WorldPlugin pub struct WorldPlugin
@ -21,6 +24,8 @@ pub struct WorldPlugin
pub grid_width: f32, pub grid_width: f32,
pub grid_height: f32, pub grid_height: f32,
pub top_margin: f32, pub top_margin: f32,
pub num_agents: i32,
} }
impl Plugin for WorldPlugin impl Plugin for WorldPlugin
@ -40,6 +45,7 @@ impl Plugin for WorldPlugin
grid_width: self.grid_width, grid_width: self.grid_width,
grid_height: self.grid_height, grid_height: self.grid_height,
top_margin: self.top_margin, top_margin: self.top_margin,
num_agents: self.num_agents,
}) })
.add_systems(Update, on_resize) .add_systems(Update, on_resize)
.add_systems(Startup, setup); .add_systems(Startup, setup);
@ -54,20 +60,71 @@ fn setup(mut commands: Commands, settings: Res<WorldPluginState>)
let cell_width = settings.window_width / (settings.grid_width - 1.0); let cell_width = settings.window_width / (settings.grid_width - 1.0);
let cell_height = (settings.window_height - settings.top_margin) / (settings.grid_height - 1.0); let cell_height = (settings.window_height - settings.top_margin) / (settings.grid_height - 1.0);
let line_size = 2.0; let line_size = 2.0;
let half_screen_width = settings.window_width / 2.0; // let half_screen_width = settings.window_width / 2.0;
let half_screen_height = (settings.window_height - settings.top_margin) / 2.0; // let half_screen_height = (settings.window_height - settings.top_margin) / 2.0;
// for i in 0..settings.grid_width as i32
// {
// let point_a = Vec2::new(i as f32 * cell_width - half_screen_width, -half_screen_height - settings.top_margin);
// let point_b = Vec2::new(i as f32 * cell_width - half_screen_width, half_screen_height - settings.top_margin);
// add_line(&mut commands, point_a, point_b, line_size);
// }
// for i in 0..settings.grid_height as i32
// {
// let point_a = Vec2::new(-half_screen_width, i as f32 * cell_height - half_screen_height - settings.top_margin);
// let point_b = Vec2::new(half_screen_width, i as f32 * cell_height - half_screen_height - settings.top_margin);
// add_line(&mut commands, point_a, point_b, line_size);
// }
draw_grid(&mut commands, &settings);
// Generate new agents
info!("Generating Agents...");
let mut rng = rand::thread_rng();
for i in 0..settings.num_agents
{
// new Agent with random grid index
let x: i32 = rng.gen_range(0..settings.grid_width as i32);
let y: i32 = rng.gen_range(0..settings.grid_height as i32);
let agent = Agent::new(x, y);
// convert index to screen coords
let screen_x = x as f32 * cell_width + cell_width / 2.0;
let screen_y = y as f32 * cell_height + cell_height / 2.0;
// spawn agents in random grid locations
let circle = shapes::Circle{radius: cell_width / 2.0 - line_size, center: Vec2::new(screen_x, screen_y)};
commands.spawn((ShapeBundle{
path: GeometryBuilder::build_as(&circle),
..default()
},
Fill::color(Color::GREEN),
agent,
));
}
}
fn draw_grid(commands: &mut Commands, settings: &Res<WorldPluginState>)
{
let cell_width = settings.window_width / (settings.grid_width - 1.0);
let cell_height = (settings.window_height - settings.top_margin) / (settings.grid_height - 1.0);
let line_size = 2.0;
// let half_screen_width = settings.window_width / 2.0;
// let half_screen_height = (settings.window_height - settings.top_margin) / 2.0;
for i in 0..settings.grid_width as i32 for i in 0..settings.grid_width as i32
{ {
let point_a = Vec2::new(i as f32 * cell_width - half_screen_width, -half_screen_height - settings.top_margin); let point_a = Vec2::new(i as f32 * cell_width, 0.0);
let point_b = Vec2::new(i as f32 * cell_width - half_screen_width, half_screen_height - settings.top_margin); let point_b = Vec2::new(i as f32 * cell_width, settings.window_height - settings.top_margin);
add_line(&mut commands, point_a, point_b, line_size); add_line(commands, point_a, point_b, line_size);
} }
for i in 0..settings.grid_height as i32 for i in 0..settings.grid_height as i32
{ {
let point_a = Vec2::new(-half_screen_width, i as f32 * cell_height - half_screen_height - settings.top_margin); let point_a = Vec2::new(0.0, i as f32 * cell_height);
let point_b = Vec2::new(half_screen_width, i as f32 * cell_height - half_screen_height - settings.top_margin); let point_b = Vec2::new(settings.window_width, i as f32 * cell_height);
add_line(&mut commands, point_a, point_b, line_size); add_line(commands, point_a, point_b, line_size);
} }
} }
@ -78,6 +135,7 @@ fn add_line(commands: &mut Commands, point_a: Vec2, point_b: Vec2, line_size: f3
commands.spawn(( commands.spawn((
ShapeBundle { ShapeBundle {
path: GeometryBuilder::build_as(&line), path: GeometryBuilder::build_as(&line),
//transform: Transform::from_translation(Vec3::new(0., 0., -1.0)),
..default() ..default()
}, },
Stroke::new(Color::BLACK, line_size), Stroke::new(Color::BLACK, line_size),
@ -87,18 +145,25 @@ fn add_line(commands: &mut Commands, point_a: Vec2, point_b: Vec2, line_size: f3
fn on_resize(mut commands: Commands, mut settings: ResMut<WorldPluginState>, mut resize_reader: EventReader<WindowResized>, mut grid: Query<(Entity, &GridLine)> ) fn on_resize(mut commands: Commands, mut settings: ResMut<WorldPluginState>, mut resize_reader: EventReader<WindowResized>, mut grid: Query<(Entity, &GridLine)> )
{ {
let mut has_event = false;
for e in resize_reader.iter() for e in resize_reader.iter()
{ {
// When resolution is being changed // When resolution is being changed
// info!("new window size: {:.1} x {:.1}", e.width, e.height); // info!("new window size: {:.1} x {:.1}", e.width, e.height);
settings.window_width = e.width; settings.window_width = e.width;
settings.window_height = e.height; settings.window_height = e.height;
has_event = true;
} }
for (entity, line) in &grid if has_event
{ {
commands.entity(entity).despawn(); for (entity, line) in &grid
{
commands.entity(entity).despawn();
}
draw_grid(&mut commands, &settings.into());
info!("Redrawing");
} }
setup(commands, settings.into());
} }
Loading…
Cancel
Save