123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- 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())
- .insert_resource(c::LastTailPosition::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(game_over.system().after(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),
- )
- .with_system(
- snake::growth
- .system()
- .label(c::SnakeMovement::Growth)
- .after(c::SnakeMovement::Eating),
- ),
- )
- .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::<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>) {
- commands
- .spawn_bundle(SpriteBundle {
- material: materials.food_material.clone(),
- ..Default::default()
- })
- .insert(c::Food)
- .insert(c::Position {
- x: (random::<f32>() * c::ARENA_WIDTH as f32) as i32,
- y: (random::<f32>() * c::ARENA_HEIGHT as f32) as i32,
- })
- .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);
- }
- }
|