use bevy::prelude::*; const ARENA_WIDTH: u32 = 10; const ARENA_HEIGHT: u32 = 10; #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] struct Position { x: i32, y: i32, } struct Size { width: f32, height: f32, } impl Size { pub fn square(x: f32) -> Self { Self { width: x, height: x, } } } struct SnakeHead; struct Materials { head_material: Handle, } fn setup(commands: &mut Commands, mut materials: ResMut>) { commands.spawn(Camera2dBundle::default()); commands.insert_resource(Materials { head_material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()), }); } fn spawn_snake(commands: &mut Commands, materials: Res) { commands .spawn(SpriteBundle { material: materials.head_material.clone(), sprite: Sprite::new(Vec2::new(10.0, 10.0)), ..Default::default() }) .with(SnakeHead) .with(Position { x: 3, y: 3 }) .with(Size::square(0.8)); } fn snake_movement( keyboard_input: Res>, mut head_positions: Query<&mut Position, With>, ) { for mut pos in head_positions.iter_mut() { if keyboard_input.pressed(KeyCode::Left) { pos.x -= 1; } if keyboard_input.pressed(KeyCode::Right) { pos.x += 1; } if keyboard_input.pressed(KeyCode::Down) { pos.y -= 1; } if keyboard_input.pressed(KeyCode::Up) { pos.y += 1; } } } fn size_scaling(windows: Res, mut q: Query<(&Size, &mut Sprite)>) { let window = windows.get_primary().unwrap(); for (sprite_size, mut sprite) in q.iter_mut() { sprite.size = Vec2::new( sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32, sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32, ); } } fn position_translation(windows: Res, mut q: Query<(&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.) + (tile_size / 2.) } let window = windows.get_primary().unwrap(); for (pos, mut transform) in q.iter_mut() { transform.translation = Vec3::new( convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32), convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32), 0.0, ); } } fn main() { App::build() .add_startup_system(setup.system()) .add_startup_stage("game_setup", SystemStage::single(spawn_snake.system())) .add_system(snake_movement.system()) .add_system(position_translation.system()) .add_system(size_scaling.system()) .add_plugins(DefaultPlugins) .run(); }