use std::default::Default; use bevy::core::FixedTimestep; use bevy::prelude::*; use bevy::render::pass::ClearColor; use rand::prelude::random; pub mod components; use crate::components as c; pub mod snake; fn main() { App::build() .insert_resource(WindowDescriptor { title: "Snake!".to_string(), width: 500.0, height: 500.0, ..Default::default() }) .insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04))) .insert_resource(c::SnakeSegments::default()) .add_startup_system(setup.system()) .add_startup_stage("game_setup", SystemStage::single(snake::spawn.system())) .add_plugins(DefaultPlugins) .add_system( snake::input .system() .label(c::SnakeMovement::Input) .before(c::SnakeMovement::Movement), ) .add_system_set( SystemSet::new() .with_run_criteria(FixedTimestep::step(0.3)) .with_system(snake::movement.system().label(c::SnakeMovement::Movement)) .with_system( snake::eating .system() .label(c::SnakeMovement::Eating) .after(c::SnakeMovement::Movement), ), ) .add_system_set_to_stage( CoreStage::PostUpdate, SystemSet::new() .with_system(position_translation.system()) .with_system(size_scaling.system()), ) .add_system_set( SystemSet::new() .with_run_criteria(FixedTimestep::step(0.9)) .with_system(food_spawner.system()), ) .add_event::() .run(); } fn setup(mut commands: Commands, mut materials: ResMut>) { commands.spawn_bundle(OrthographicCameraBundle::new_2d()); commands.insert_resource(c::Materials { head_material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()), segment_material: materials.add(Color::rgb(0.3, 0.3, 0.3).into()), food_material: materials.add(Color::rgb(1.0, 0.0, 1.0).into()), }); } fn food_spawner(mut commands: Commands, materials: Res) { commands .spawn_bundle(SpriteBundle { material: materials.food_material.clone(), ..Default::default() }) .insert(c::Food) .insert(c::Position { x: (random::() * c::ARENA_WIDTH as f32) as i32, y: (random::() * c::ARENA_HEIGHT as f32) as i32, }) .insert(c::GridSize::square(0.8)); } fn size_scaling(windows: Res, mut q: Query<(&c::GridSize, &mut Sprite)>) { let window = windows.get_primary().unwrap(); for (size, mut sprite) in q.iter_mut() { sprite.size = Vec2::new( size.width / c::ARENA_WIDTH as f32 * window.width() as f32, size.height / c::ARENA_HEIGHT as f32 * window.height() as f32, ); } } fn position_translation(windows: Res, mut q: Query<(&c::Position, &mut Transform)>) { fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { let tile_size = bound_window / bound_game; pos / bound_game * bound_window - (bound_window / 2.0) + (tile_size / 2.0) } let window = windows.get_primary().unwrap(); for (pos, mut tf) in q.iter_mut() { tf.translation = Vec3::new( convert(pos.x as f32, window.width() as f32, c::ARENA_WIDTH as f32), convert(pos.y as f32, window.height() as f32, c::ARENA_HEIGHT as f32), 0.0, ) } }