Browse Source

some reord + game over

Getty Ritter 2 years ago
parent
commit
9e3f5a91a5
3 changed files with 87 additions and 20 deletions
  1. 34 20
      src/components.rs
  2. 25 0
      src/main.rs
  3. 28 0
      src/snake.rs

+ 34 - 20
src/components.rs

@@ -1,16 +1,10 @@
 use bevy::prelude::{ColorMaterial, Entity, Handle, SystemLabel};
 
+// constants
 pub const ARENA_WIDTH: u32 = 10;
 pub const ARENA_HEIGHT: u32 = 10;
 
-pub struct SnakeHead {
-    pub direction: Direction,
-}
-
-pub struct Food;
-
-pub struct GrowthEvent;
-
+// basic game components
 #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
 pub struct Position {
     pub x: i32,
@@ -31,12 +25,6 @@ impl GridSize {
     }
 }
 
-pub struct Materials {
-    pub head_material: Handle<ColorMaterial>,
-    pub segment_material: Handle<ColorMaterial>,
-    pub food_material: Handle<ColorMaterial>,
-}
-
 #[derive(PartialEq, Copy, Clone)]
 pub enum Direction {
     Left,
@@ -56,17 +44,43 @@ impl Direction {
     }
 }
 
-#[derive(SystemLabel, Debug, Hash, PartialEq, Eq, Clone)]
-pub enum SnakeMovement {
-    Input,
-    Movement,
-    Eating,
-    Growth,
+// material resource
+pub struct Materials {
+    pub head_material: Handle<ColorMaterial>,
+    pub segment_material: Handle<ColorMaterial>,
+    pub food_material: Handle<ColorMaterial>,
+}
+
+// food!
+pub struct Food;
+
+// snake-related components
+pub struct SnakeHead {
+    pub direction: Direction,
 }
 
 pub struct SnakeSegment;
 
+// snake-related resources
 #[derive(Default)]
 pub struct SnakeSegments {
     pub segments: Vec<Entity>,
 }
+
+#[derive(Default)]
+pub struct LastTailPosition {
+    pub pos: Option<Position>,
+}
+
+// snake phase labels
+#[derive(SystemLabel, Debug, Hash, PartialEq, Eq, Clone)]
+pub enum SnakeMovement {
+    Input,
+    Movement,
+    Eating,
+    Growth,
+}
+
+// events
+pub struct GrowthEvent;
+pub struct GameOverEvent;

+ 25 - 0
src/main.rs

@@ -19,6 +19,7 @@ fn main() {
         })
         .insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04)))
         .insert_resource(c::SnakeSegments::default())
+        .insert_resource(c::LastTailPosition::default())
         .add_startup_system(setup.system())
         .add_startup_stage("game_setup", SystemStage::single(snake::spawn.system()))
         .add_plugins(DefaultPlugins)
@@ -28,6 +29,7 @@ fn main() {
                 .label(c::SnakeMovement::Input)
                 .before(c::SnakeMovement::Movement),
         )
+        .add_system(game_over.system().after(c::SnakeMovement::Movement))
         .add_system_set(
             SystemSet::new()
                 .with_run_criteria(FixedTimestep::step(0.3))
@@ -37,6 +39,12 @@ fn main() {
                         .system()
                         .label(c::SnakeMovement::Eating)
                         .after(c::SnakeMovement::Movement),
+                )
+                .with_system(
+                    snake::growth
+                        .system()
+                        .label(c::SnakeMovement::Growth)
+                        .after(c::SnakeMovement::Eating),
                 ),
         )
         .add_system_set_to_stage(
@@ -51,6 +59,7 @@ fn main() {
                 .with_system(food_spawner.system()),
         )
         .add_event::<c::GrowthEvent>()
+        .add_event::<c::GameOverEvent>()
         .run();
 }
 
@@ -102,3 +111,19 @@ fn position_translation(windows: Res<Windows>, mut q: Query<(&c::Position, &mut
         )
     }
 }
+
+fn game_over(
+    mut commands: Commands,
+    mut reader: EventReader<c::GameOverEvent>,
+    materials: Res<c::Materials>,
+    segments_res: ResMut<c::SnakeSegments>,
+    food: Query<Entity, With<c::Food>>,
+    segments: Query<Entity, With<c::SnakeSegment>>,
+) {
+    if reader.iter().next().is_some() {
+        for ent in food.iter().chain(segments.iter()) {
+            commands.entity(ent).despawn();
+        }
+        snake::spawn(commands, materials, segments_res);
+    }
+}

+ 28 - 0
src/snake.rs

@@ -64,6 +64,8 @@ pub fn input(keyboard_input: Res<Input<KeyCode>>, mut heads: Query<&mut c::Snake
 
 pub fn movement(
     segments: ResMut<c::SnakeSegments>,
+    mut last_tail_position: ResMut<c::LastTailPosition>,
+    mut game_over_writer: EventWriter<c::GameOverEvent>,
     mut heads: Query<(Entity, &c::SnakeHead)>,
     mut positions: Query<&mut c::Position>,
 ) {
@@ -80,12 +82,22 @@ pub fn movement(
             c::Direction::Up => head_pos.y += 1,
             c::Direction::Down => head_pos.y -= 1,
         }
+        if head_pos.x < 0
+            || head_pos.y < 0
+            || head_pos.x as u32 > c::ARENA_WIDTH
+            || head_pos.y as u32 > c::ARENA_HEIGHT
+            || segment_positions.contains(&head_pos)
+        {
+            game_over_writer.send(c::GameOverEvent);
+        }
+
         segment_positions
             .iter()
             .zip(segments.segments.iter().skip(1))
             .for_each(|(pos, segment)| {
                 *positions.get_mut(*segment).unwrap() = *pos;
             });
+        last_tail_position.pos = Some(*segment_positions.last().unwrap());
     }
 }
 
@@ -104,3 +116,19 @@ pub fn eating(
         }
     }
 }
+
+pub fn growth(
+    commands: Commands,
+    last_tail_position: Res<c::LastTailPosition>,
+    mut segments: ResMut<c::SnakeSegments>,
+    mut growth_reader: EventReader<c::GrowthEvent>,
+    materials: Res<c::Materials>,
+) {
+    if growth_reader.iter().next().is_some() {
+        segments.segments.push(spawn_segment(
+            commands,
+            &materials.segment_material,
+            last_tail_position.pos.unwrap(),
+        ));
+    }
+}