main.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. use std::default::Default;
  2. use bevy::core::FixedTimestep;
  3. use bevy::prelude::*;
  4. use bevy::render::pass::ClearColor;
  5. use rand::prelude::random;
  6. pub mod components;
  7. use crate::components as c;
  8. pub mod snake;
  9. fn main() {
  10. App::build()
  11. .insert_resource(WindowDescriptor {
  12. title: "Snake!".to_string(),
  13. width: 500.0,
  14. height: 500.0,
  15. ..Default::default()
  16. })
  17. .insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04)))
  18. .insert_resource(c::SnakeSegments::default())
  19. .add_startup_system(setup.system())
  20. .add_startup_stage("game_setup", SystemStage::single(snake::spawn.system()))
  21. .add_plugins(DefaultPlugins)
  22. .add_system(
  23. snake::input
  24. .system()
  25. .label(c::SnakeMovement::Input)
  26. .before(c::SnakeMovement::Movement),
  27. )
  28. .add_system_set(
  29. SystemSet::new()
  30. .with_run_criteria(FixedTimestep::step(0.3))
  31. .with_system(snake::movement.system().label(c::SnakeMovement::Movement))
  32. .with_system(
  33. snake::eating
  34. .system()
  35. .label(c::SnakeMovement::Eating)
  36. .after(c::SnakeMovement::Movement),
  37. ),
  38. )
  39. .add_system_set_to_stage(
  40. CoreStage::PostUpdate,
  41. SystemSet::new()
  42. .with_system(position_translation.system())
  43. .with_system(size_scaling.system()),
  44. )
  45. .add_system_set(
  46. SystemSet::new()
  47. .with_run_criteria(FixedTimestep::step(0.9))
  48. .with_system(food_spawner.system()),
  49. )
  50. .add_event::<c::GrowthEvent>()
  51. .run();
  52. }
  53. fn setup(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
  54. commands.spawn_bundle(OrthographicCameraBundle::new_2d());
  55. commands.insert_resource(c::Materials {
  56. head_material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()),
  57. segment_material: materials.add(Color::rgb(0.3, 0.3, 0.3).into()),
  58. food_material: materials.add(Color::rgb(1.0, 0.0, 1.0).into()),
  59. });
  60. }
  61. fn food_spawner(mut commands: Commands, materials: Res<c::Materials>) {
  62. commands
  63. .spawn_bundle(SpriteBundle {
  64. material: materials.food_material.clone(),
  65. ..Default::default()
  66. })
  67. .insert(c::Food)
  68. .insert(c::Position {
  69. x: (random::<f32>() * c::ARENA_WIDTH as f32) as i32,
  70. y: (random::<f32>() * c::ARENA_HEIGHT as f32) as i32,
  71. })
  72. .insert(c::GridSize::square(0.8));
  73. }
  74. fn size_scaling(windows: Res<Windows>, mut q: Query<(&c::GridSize, &mut Sprite)>) {
  75. let window = windows.get_primary().unwrap();
  76. for (size, mut sprite) in q.iter_mut() {
  77. sprite.size = Vec2::new(
  78. size.width / c::ARENA_WIDTH as f32 * window.width() as f32,
  79. size.height / c::ARENA_HEIGHT as f32 * window.height() as f32,
  80. );
  81. }
  82. }
  83. fn position_translation(windows: Res<Windows>, mut q: Query<(&c::Position, &mut Transform)>) {
  84. fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 {
  85. let tile_size = bound_window / bound_game;
  86. pos / bound_game * bound_window - (bound_window / 2.0) + (tile_size / 2.0)
  87. }
  88. let window = windows.get_primary().unwrap();
  89. for (pos, mut tf) in q.iter_mut() {
  90. tf.translation = Vec3::new(
  91. convert(pos.x as f32, window.width() as f32, c::ARENA_WIDTH as f32),
  92. convert(pos.y as f32, window.height() as f32, c::ARENA_HEIGHT as f32),
  93. 0.0,
  94. )
  95. }
  96. }