extern crate amethyst; extern crate amethyst_rhusics; extern crate collision; extern crate genmesh; extern crate rand; extern crate rhusics_core; extern crate rhusics_ecs; extern crate shred; #[macro_use] extern crate shred_derive; use std::time::{Duration, Instant}; use amethyst::assets::{Handle, Loader}; use amethyst::core::cgmath::{Array, One, Point2, Quaternion, Vector3}; use amethyst::core::{GlobalTransform, Transform, TransformBundle}; use amethyst::ecs::prelude::{Builder, Entity, World}; use amethyst::input::{is_close_requested, is_key_down}; use amethyst::prelude::{ Application, Config, GameData, GameDataBuilder, SimpleState, SimpleTrans, StateData, StateEvent, Trans, }; use amethyst::renderer::{ Camera, DisplayConfig, DrawFlat, Material, MaterialDefaults, Mesh, Pipeline, PosTex, RenderBundle, Stage, VirtualKeyCode, }; use amethyst::ui::{DrawUi, UiBundle}; use amethyst::utils::fps_counter::FPSCounterBundle; use amethyst_rhusics::{setup_2d_arena, time_sync, DefaultPhysicsBundle2}; use collision::primitive::{Primitive2, Rectangle}; use collision::Aabb2; use rhusics_core::CollisionShape; use rhusics_ecs::physics2d::BodyPose2; use self::boxes::{ create_ui, update_ui, BoxSimulationBundle2, Emitter, Graphics, KillRate, ObjectType, }; mod boxes; #[derive(Default)] pub struct Emitting { fps: Option, num: Option, collision: Option, } pub type Shape = CollisionShape, BodyPose2, Aabb2, ObjectType>; impl<'a, 'b> SimpleState<'a, 'b> for Emitting { fn on_start(&mut self, data: StateData) { let StateData { world, .. } = data; world.write_resource::().0 = 0.01; initialise_camera(world); let g = Graphics { mesh: initialise_mesh(world), }; let (num_display, fps_display, collisions_display) = create_ui(world); self.num = Some(num_display); self.fps = Some(fps_display); self.collision = Some(collisions_display); world.add_resource(g); setup_2d_arena( Point2::new(-1., -1.), Point2::new(1., 1.), ( ObjectType::Wall, ObjectType::Wall, ObjectType::Wall, ObjectType::Wall, ), world, ); initialise_emitters(world); } fn handle_event(&mut self, _: StateData, event: StateEvent) -> SimpleTrans<'a, 'b> { match event { StateEvent::Window(ref event) if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) => { Trans::Quit } _ => Trans::None, } } fn update(&mut self, data: &mut StateData) -> SimpleTrans<'a, 'b> { time_sync(&data.world); update_ui::>( data.world, self.num.unwrap(), self.fps.unwrap(), self.collision.unwrap(), ); data.data.update(data.world); Trans::None } } fn initialise_camera(world: &mut World) { world .create_entity() .with(Camera::standard_2d()) .with(Transform { rotation: Quaternion::one(), scale: Vector3::from_value(1.), translation: Vector3::new(0., 0., 5.), }).with(GlobalTransform::default()) .build(); } fn initialise_mesh(world: &mut World) -> Handle { use genmesh::generators::Cube; use genmesh::{MapToVertices, Triangulate, Vertices}; let vertices = Cube::new() .vertex(|v| PosTex { position: v.pos.into(), tex_coord: [0.1, 0.1], }).triangulate() .vertices() .collect::>(); world .read_resource::() .load_from_data(vertices.into(), (), &world.read_resource()) } fn initialise_material(world: &mut World, r: f32, g: f32, b: f32) -> Material { let albedo = world.read_resource::().load_from_data( [r, g, b, 1.0].into(), (), &world.read_resource(), ); Material { albedo, ..world.read_resource::().0.clone() } } fn emitter(p: Point2, d: Duration, material: Material) -> Emitter> { Emitter { location: p, emission_interval: d, last_emit: Instant::now(), material, emitted: 0, } } fn initialise_emitters(world: &mut World) { let mat = initialise_material(world, 0.3, 1.0, 0.3); world .create_entity() .with(emitter( Point2::new(-0.4, 0.), Duration::new(0, 50_000_000), mat, )).build(); let mat = initialise_material(world, 0.3, 0.0, 0.3); world .create_entity() .with(emitter( Point2::new(0.4, 0.), Duration::new(0, 75_000_000), mat, )).build(); let mat = initialise_material(world, 1.0, 1.0, 1.0); world .create_entity() .with(emitter( Point2::new(0., -0.4), Duration::new(0, 100_000_000), mat, )).build(); let mat = initialise_material(world, 1.0, 0.3, 0.3); world .create_entity() .with(emitter( Point2::new(0., 0.4), Duration::new(1, 25_000_000), mat, )).build(); } fn run() -> Result<(), amethyst::Error> { amethyst::start_logger(amethyst::LoggerConfig::default()); let path = format!( "{}/../resources/display_config.ron", env!("CARGO_MANIFEST_DIR") ); let config = DisplayConfig::load(&path); let pipe = Pipeline::build().with_stage( Stage::with_backbuffer() .clear_target([0., 0., 0., 1.0], 1.0) .with_pass(DrawFlat::::new()) .with_pass(DrawUi::new()), ); let game_data = GameDataBuilder::default() .with_bundle(FPSCounterBundle::default())? .with_bundle(DefaultPhysicsBundle2::::new().with_spatial())? .with_bundle(BoxSimulationBundle2::new(Rectangle::new(0.1, 0.1).into()))? .with_bundle(TransformBundle::new().with_dep(&["sync_system", "emission_system"]))? .with_bundle(UiBundle::::new())? .with_bundle(RenderBundle::new(pipe, Some(config)))?; let mut game = Application::new("./", Emitting::default(), game_data)?; game.run(); Ok(()) } fn main() { if let Err(e) = run() { println!("Error occurred during game execution: {}", e); ::std::process::exit(1); } }