|
@@ -3,10 +3,10 @@ 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 game;
|
|
|
pub mod snake;
|
|
|
|
|
|
fn main() {
|
|
@@ -20,7 +20,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_system(game::setup.system())
|
|
|
.add_startup_stage("game_setup", SystemStage::single(snake::spawn.system()))
|
|
|
.add_plugins(DefaultPlugins)
|
|
|
.add_system(
|
|
@@ -29,7 +29,7 @@ fn main() {
|
|
|
.label(c::SnakeMovement::Input)
|
|
|
.before(c::SnakeMovement::Movement),
|
|
|
)
|
|
|
- .add_system(game_over.system().after(c::SnakeMovement::Movement))
|
|
|
+ .add_system(snake::die.system().after(c::SnakeMovement::Movement))
|
|
|
.add_system_set(
|
|
|
SystemSet::new()
|
|
|
.with_run_criteria(FixedTimestep::step(0.3))
|
|
@@ -50,97 +50,15 @@ fn main() {
|
|
|
.add_system_set_to_stage(
|
|
|
CoreStage::PostUpdate,
|
|
|
SystemSet::new()
|
|
|
- .with_system(position_translation.system())
|
|
|
- .with_system(size_scaling.system()),
|
|
|
+ .with_system(game::position_translation.system())
|
|
|
+ .with_system(game::size_scaling.system()),
|
|
|
)
|
|
|
.add_system_set(
|
|
|
SystemSet::new()
|
|
|
.with_run_criteria(FixedTimestep::step(0.9))
|
|
|
- .with_system(food_spawner.system()),
|
|
|
+ .with_system(snake::food.system()),
|
|
|
)
|
|
|
.add_event::<c::GrowthEvent>()
|
|
|
.add_event::<c::GameOverEvent>()
|
|
|
.run();
|
|
|
}
|
|
|
-
|
|
|
-fn setup(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
|
|
|
- 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<c::Materials>,
|
|
|
- segments: Query<&c::Position, With<c::SnakeSegment>>,
|
|
|
-) {
|
|
|
- let snake_positions = segments.iter().collect::<Vec<&c::Position>>();
|
|
|
- // try three times, giving up if we still haven't found a free spot
|
|
|
- let mut x;
|
|
|
- let mut y;
|
|
|
- let mut attempts = 3;
|
|
|
- loop {
|
|
|
- x = (random::<f32>() * c::ARENA_WIDTH as f32) as i32;
|
|
|
- y = (random::<f32>() * c::ARENA_HEIGHT as f32) as i32;
|
|
|
- if !snake_positions.contains(&&c::Position {x, y}) {
|
|
|
- break;
|
|
|
- }
|
|
|
- attempts -= 1;
|
|
|
- if attempts == 0 {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- commands
|
|
|
- .spawn_bundle(SpriteBundle {
|
|
|
- material: materials.food_material.clone(),
|
|
|
- ..Default::default()
|
|
|
- })
|
|
|
- .insert(c::Food)
|
|
|
- .insert(c::Position { x, y })
|
|
|
- .insert(c::GridSize::square(0.8));
|
|
|
-}
|
|
|
-
|
|
|
-fn size_scaling(windows: Res<Windows>, 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<Windows>, 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,
|
|
|
- )
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-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);
|
|
|
- }
|
|
|
-}
|