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 = [
"bevy",
"bevy_prototype_lyon",
"rand",
]
[[package]]
@ -2648,6 +2649,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@ -2688,6 +2695,36 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "range-alloc"
version = "0.1.3"

@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
bevy = "0.11.0"
bevy_prototype_lyon = "0.9.0"
rand = "0.8.5"
# 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 neural_net;
#[derive(Component)]
struct Agent;
mod agent;
use agent::Agent;
#[derive(Component)]
struct FpsText;
@ -60,7 +59,8 @@ fn main()
WorldPlugin {
grid_width: 100.,
grid_height: 100.,
top_margin: 50.0
top_margin: 50.0,
num_agents: 100,
},
ShapePlugin
))
@ -75,18 +75,25 @@ fn main()
fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>)
{
// 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
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes.add(shape::Circle::new(50.).into()).into(),
material: materials.add(ColorMaterial::from(Color::PURPLE)),
transform: Transform::from_translation(Vec3::new(-150., 0., 0.)),
..default()
},
Agent
));
// commands.spawn((
// MaterialMesh2dBundle {
// mesh: meshes.add(shape::Circle::new(50.).into()).into(),
// material: materials.add(ColorMaterial::from(Color::PURPLE)),
// transform: Transform::from_translation(Vec3::new(0., 0., 0.)),
// ..default()
// },
// Agent::new(0, 0)
// ));
// UI
// 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>)
{
let now = Instant::now();
@ -120,22 +128,23 @@ fn tick_simulation(mut state: ResMut<SimulationState>, delta_time: Res<Time>, mu
// Tick the neural net
// 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();
state.last_gen_time += state.last_step_time;
state.last_step_time = elapsed_time.as_secs_f32();
state.generation_step += 1;
// let elapsed_time = now.elapsed();
// state.last_gen_time += state.last_step_time;
// state.last_step_time = elapsed_time.as_secs_f32();
// state.generation_step += 1;
if state.generation_step >= state.max_gen_steps
{
// Move on to the next generation
state.generation += 1;
// if state.generation_step >= state.max_gen_steps
// {
// // Move on to the next generation
// state.generation += 1;
}
// }
}
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_prototype_lyon::prelude::*;
use rand::prelude::*;
use crate::agent::Agent;
#[derive(Component)]
struct GridLine;
@ -14,6 +16,7 @@ struct WorldPluginState
grid_height: f32,
top_margin: f32,
num_agents: i32,
}
pub struct WorldPlugin
@ -21,6 +24,8 @@ pub struct WorldPlugin
pub grid_width: f32,
pub grid_height: f32,
pub top_margin: f32,
pub num_agents: i32,
}
impl Plugin for WorldPlugin
@ -40,6 +45,7 @@ impl Plugin for WorldPlugin
grid_width: self.grid_width,
grid_height: self.grid_height,
top_margin: self.top_margin,
num_agents: self.num_agents,
})
.add_systems(Update, on_resize)
.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_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;
// 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
// {
// 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
{
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);
let point_a = Vec2::new(i as f32 * cell_width, 0.0);
let point_b = Vec2::new(i as f32 * cell_width, settings.window_height - settings.top_margin);
add_line(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);
let point_a = Vec2::new(0.0, i as f32 * cell_height);
let point_b = Vec2::new(settings.window_width, i as f32 * cell_height);
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((
ShapeBundle {
path: GeometryBuilder::build_as(&line),
//transform: Transform::from_translation(Vec3::new(0., 0., -1.0)),
..default()
},
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)> )
{
let mut has_event = false;
for e in resize_reader.iter()
{
// When resolution is being changed
// info!("new window size: {:.1} x {:.1}", e.width, e.height);
settings.window_width = e.width;
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