Init
This commit is contained in:
		
							
								
								
									
										22
									
								
								.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					[target.x86_64-unknown-linux-gnu]
 | 
				
			||||||
 | 
					linker = "clang"
 | 
				
			||||||
 | 
					rustflags = [
 | 
				
			||||||
 | 
					    "-C", "link-arg=-fuse-ld=lld",
 | 
				
			||||||
 | 
					    "-C", "link-arg=-lxkbcommon",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[target.x86_64-pc-windows-msvc]
 | 
				
			||||||
 | 
					linker = "rust-lld.exe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[target.x86_64-apple-darwin]
 | 
				
			||||||
 | 
					rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/opt/llvm/bin/ld64.lld"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# [unstable]
 | 
				
			||||||
 | 
					# codegen-backend = true
 | 
				
			||||||
 | 
					# [profile.dev]
 | 
				
			||||||
 | 
					# codegen-backend = "cranelift"
 | 
				
			||||||
 | 
					# [profile.dev.package."*"]
 | 
				
			||||||
 | 
					# codegen-backend = "llvm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[build]
 | 
				
			||||||
 | 
					rustflags = ["-Z", "share-generics=y"]
 | 
				
			||||||
							
								
								
									
										45
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					# Rust
 | 
				
			||||||
 | 
					/target
 | 
				
			||||||
 | 
					app-bevy/target
 | 
				
			||||||
 | 
					lib-utils/target
 | 
				
			||||||
 | 
					**/*.rs.bk
 | 
				
			||||||
 | 
					Cargo.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Nix
 | 
				
			||||||
 | 
					result
 | 
				
			||||||
 | 
					.direnv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Editor-Specific
 | 
				
			||||||
 | 
					.vscode/
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					*.swo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# OS
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					Thumbs.db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Bevy
 | 
				
			||||||
 | 
					/assets
 | 
				
			||||||
 | 
					app-bevy/assets
 | 
				
			||||||
 | 
					lib-utils/assets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Misc
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					tmp/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Logs
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build artifacts
 | 
				
			||||||
 | 
					*.o
 | 
				
			||||||
 | 
					*.so
 | 
				
			||||||
 | 
					*.dylib
 | 
				
			||||||
 | 
					*.dll
 | 
				
			||||||
 | 
					*.wasm
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					node_modules/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Backup Files
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										0
									
								
								.projectile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.projectile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										33
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					[workspace]
 | 
				
			||||||
 | 
					members = [
 | 
				
			||||||
 | 
					    "app-bevy",
 | 
				
			||||||
 | 
					    "lib-utils",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					resolver = "2" # wgpu/bevy need this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[workspace.package]
 | 
				
			||||||
 | 
					version = "0.14.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[workspace.dependencies]
 | 
				
			||||||
 | 
					bevy = { version = "0.15.0", features = ["dynamic_linking", "wayland"] }
 | 
				
			||||||
 | 
					log = { version = "*", features = ["max_level_debug", "release_max_level_warn"] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[profile.dev]
 | 
				
			||||||
 | 
					opt-level = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[profile.dev.package."*"]
 | 
				
			||||||
 | 
					opt-level = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[profile.release]
 | 
				
			||||||
 | 
					codegen-units = 1
 | 
				
			||||||
 | 
					lto = "thin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[profile.wasm-release]
 | 
				
			||||||
 | 
					inherits = "release"
 | 
				
			||||||
 | 
					opt-level = "s"
 | 
				
			||||||
 | 
					lto = "thin"
 | 
				
			||||||
 | 
					strip = "debuginfo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[workspace.metadata.rust-analyzer]
 | 
				
			||||||
 | 
					rustc_private = true
 | 
				
			||||||
							
								
								
									
										16
									
								
								app-bevy/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app-bevy/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# Rust
 | 
				
			||||||
 | 
					/target
 | 
				
			||||||
 | 
					**/*.rs.bk
 | 
				
			||||||
 | 
					Cargo.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Nix
 | 
				
			||||||
 | 
					result
 | 
				
			||||||
 | 
					.direnv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Editor-specific for people using these
 | 
				
			||||||
 | 
					.vscode
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# OS-specific for people using these
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					Thumbs.db
 | 
				
			||||||
							
								
								
									
										19
									
								
								app-bevy/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app-bevy/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "autonomous-agents"
 | 
				
			||||||
 | 
					version = { workspace = true }
 | 
				
			||||||
 | 
					edition = { workspace = true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					bevy = { workspace = true }
 | 
				
			||||||
 | 
					log = { workspace = true }
 | 
				
			||||||
 | 
					lib-utils = { path = "../lib-utils" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[features]
 | 
				
			||||||
 | 
					default = ["bevy/dynamic_linking", "bevy/wayland"]
 | 
				
			||||||
 | 
					nightly = ["bevy/dynamic_linking", "bevy/wayland"] # Remove dynamic_linking when shipping!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[package.metadata.rust-analyzer]
 | 
				
			||||||
 | 
					rustc_private = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[unstable]
 | 
				
			||||||
 | 
					codegen-backend = true
 | 
				
			||||||
							
								
								
									
										419
									
								
								app-bevy/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										419
									
								
								app-bevy/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,419 @@
 | 
				
			|||||||
 | 
					#![allow(dead_code)]
 | 
				
			||||||
 | 
					use bevy::math::bounding::{Aabb2d, BoundingVolume, IntersectsVolume};
 | 
				
			||||||
 | 
					use bevy::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component, Default)]
 | 
				
			||||||
 | 
					#[require(Transform)]
 | 
				
			||||||
 | 
					struct Position(Vec2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component, Default)]
 | 
				
			||||||
 | 
					struct Velocity(Vec2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const BALL_SPEED: f32 = 2.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					#[require(Position, Velocity, Collider)]
 | 
				
			||||||
 | 
					struct Ball;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					#[require(Position, Collider)]
 | 
				
			||||||
 | 
					struct Paddle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Copy, Clone)]
 | 
				
			||||||
 | 
					enum Collision {
 | 
				
			||||||
 | 
					    Left,
 | 
				
			||||||
 | 
					    Right,
 | 
				
			||||||
 | 
					    Top,
 | 
				
			||||||
 | 
					    Bottom,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component, Default)]
 | 
				
			||||||
 | 
					struct Collider(Rectangle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					struct Player;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					struct Ai;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Resource)]
 | 
				
			||||||
 | 
					struct Score {
 | 
				
			||||||
 | 
					    player: u32,
 | 
				
			||||||
 | 
					    ai: u32,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Event)]
 | 
				
			||||||
 | 
					struct Scored {
 | 
				
			||||||
 | 
					    scorer: Entity,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					struct PlayerScore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					struct AiScore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    App::new()
 | 
				
			||||||
 | 
					        .add_plugins(DefaultPlugins)
 | 
				
			||||||
 | 
					        .insert_resource(Score { player: 0, ai: 0 })
 | 
				
			||||||
 | 
					        .add_event::<Scored>()
 | 
				
			||||||
 | 
					        .add_systems(
 | 
				
			||||||
 | 
					            Startup,
 | 
				
			||||||
 | 
					            (
 | 
				
			||||||
 | 
					                spawn_ball,
 | 
				
			||||||
 | 
					                spawn_camera,
 | 
				
			||||||
 | 
					                spawn_paddles,
 | 
				
			||||||
 | 
					                spawn_gutters,
 | 
				
			||||||
 | 
					                spawn_scoreboard,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .add_systems(
 | 
				
			||||||
 | 
					            FixedUpdate,
 | 
				
			||||||
 | 
					            (
 | 
				
			||||||
 | 
					                move_ball,
 | 
				
			||||||
 | 
					                handle_collisions,
 | 
				
			||||||
 | 
					                project_positions,
 | 
				
			||||||
 | 
					                handle_player_input,
 | 
				
			||||||
 | 
					                move_paddles,
 | 
				
			||||||
 | 
					                constrain_paddle_position,
 | 
				
			||||||
 | 
					                reset_ball,
 | 
				
			||||||
 | 
					                update_score,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					                .chain(),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .run();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const BALL_SIZE: f32 = 25.;
 | 
				
			||||||
 | 
					const BALL_SHAPE: Circle = Circle::new(BALL_SIZE);
 | 
				
			||||||
 | 
					const BALL_COLOR: Color = Color::srgb(1., 0., 0.);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn spawn_ball(
 | 
				
			||||||
 | 
					    mut commands: Commands,
 | 
				
			||||||
 | 
					    mut meshes: ResMut<Assets<Mesh>>,
 | 
				
			||||||
 | 
					    mut materials: ResMut<Assets<ColorMaterial>>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    let mesh = meshes.add(BALL_SHAPE);
 | 
				
			||||||
 | 
					    let material = materials.add(BALL_COLOR);
 | 
				
			||||||
 | 
					    commands.spawn((
 | 
				
			||||||
 | 
					        Ball,
 | 
				
			||||||
 | 
					        Mesh2d(mesh),
 | 
				
			||||||
 | 
					        MeshMaterial2d(material),
 | 
				
			||||||
 | 
					        Position(Vec2::ZERO),
 | 
				
			||||||
 | 
					        Velocity(Vec2::new(-BALL_SPEED, BALL_SPEED)),
 | 
				
			||||||
 | 
					        Collider(Rectangle::new(BALL_SIZE, BALL_SIZE)),
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn move_ball(ball: Single<(&mut Position, &Velocity), With<Ball>>) {
 | 
				
			||||||
 | 
					    let (mut position, velocity) = ball.into_inner();
 | 
				
			||||||
 | 
					    position.0 += velocity.0 * BALL_SPEED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn spawn_camera(mut commands: Commands) {
 | 
				
			||||||
 | 
					    commands.spawn((Camera2d, Transform::from_xyz(0., 0., 0.)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PADDLE_SHAPE: Rectangle = Rectangle {
 | 
				
			||||||
 | 
					    half_size: Vec2::new(10., 25.),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					const PADDLE_COLOR: Color = Color::srgb(0., 1., 0.);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn spawn_paddles(
 | 
				
			||||||
 | 
					    mut commands: Commands,
 | 
				
			||||||
 | 
					    mut meshes: ResMut<Assets<Mesh>>,
 | 
				
			||||||
 | 
					    mut materials: ResMut<Assets<ColorMaterial>>,
 | 
				
			||||||
 | 
					    window: Single<&Window>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    let mesh = meshes.add(PADDLE_SHAPE);
 | 
				
			||||||
 | 
					    let material = materials.add(PADDLE_COLOR);
 | 
				
			||||||
 | 
					    let half_window_size = window.resolution.size() / 2.;
 | 
				
			||||||
 | 
					    let padding = 20.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let player_position = Vec2::new(-half_window_size.x + padding, 0.);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commands.spawn((
 | 
				
			||||||
 | 
					        Player,
 | 
				
			||||||
 | 
					        Paddle,
 | 
				
			||||||
 | 
					        Mesh2d(mesh.clone()),
 | 
				
			||||||
 | 
					        MeshMaterial2d(material.clone()),
 | 
				
			||||||
 | 
					        Position(player_position),
 | 
				
			||||||
 | 
					        Velocity(Vec2::ZERO),
 | 
				
			||||||
 | 
					        Collider(PADDLE_SHAPE),
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let ai_position = Vec2::new(half_window_size.x - padding, 0.);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commands.spawn((
 | 
				
			||||||
 | 
					        Ai,
 | 
				
			||||||
 | 
					        Paddle,
 | 
				
			||||||
 | 
					        Mesh2d(mesh.clone()),
 | 
				
			||||||
 | 
					        MeshMaterial2d(material.clone()),
 | 
				
			||||||
 | 
					        Position(ai_position),
 | 
				
			||||||
 | 
					        Velocity(Vec2::ZERO),
 | 
				
			||||||
 | 
					        Collider(PADDLE_SHAPE),
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn project_positions(mut positionables: Query<(&mut Transform, &Position)>) {
 | 
				
			||||||
 | 
					    for (mut transform, position) in &mut positionables {
 | 
				
			||||||
 | 
					        transform.translation = position.0.extend(0.);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn collide_with_side(ball: Aabb2d, wall: Aabb2d) -> Option<Collision> {
 | 
				
			||||||
 | 
					    if !ball.intersects(&wall) {
 | 
				
			||||||
 | 
					        return None;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let closest_point = wall.closest_point(ball.center());
 | 
				
			||||||
 | 
					    let offset = ball.center() - closest_point;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let side = if offset.x.abs() > offset.y.abs() {
 | 
				
			||||||
 | 
					        if offset.x < 0. {
 | 
				
			||||||
 | 
					            Collision::Left
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Collision::Right
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else if offset.y > 0. {
 | 
				
			||||||
 | 
					        Collision::Top
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        Collision::Bottom
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Some(side)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Collider {
 | 
				
			||||||
 | 
					    fn half_size(&self) -> Vec2 {
 | 
				
			||||||
 | 
					        self.0.half_size
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn handle_collisions(
 | 
				
			||||||
 | 
					    ball: Single<(&mut Velocity, &Position, &Collider), With<Ball>>,
 | 
				
			||||||
 | 
					    other_things: Query<(&Position, &Collider), Without<Ball>>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    let (mut ball_velocity, ball_position, ball_collider) = ball.into_inner();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (other_position, other_collider) in &other_things {
 | 
				
			||||||
 | 
					        if let Some(collision) = collide_with_side(
 | 
				
			||||||
 | 
					            Aabb2d::new(ball_position.0, ball_collider.half_size()),
 | 
				
			||||||
 | 
					            Aabb2d::new(other_position.0, other_collider.half_size()),
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            match collision {
 | 
				
			||||||
 | 
					                Collision::Left => {
 | 
				
			||||||
 | 
					                    ball_velocity.0.x *= -1.;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Collision::Right => {
 | 
				
			||||||
 | 
					                    ball_velocity.0.x *= -1.;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Collision::Top => {
 | 
				
			||||||
 | 
					                    ball_velocity.0.y *= -1.;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Collision::Bottom => {
 | 
				
			||||||
 | 
					                    ball_velocity.0.y *= -1.;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Component)]
 | 
				
			||||||
 | 
					#[require(Position, Collider)]
 | 
				
			||||||
 | 
					struct Gutter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GUTTER_COLOR: Color = Color::srgb(0., 0., 1.);
 | 
				
			||||||
 | 
					const GUTTER_HEIGHT: f32 = 20.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn spawn_gutters(
 | 
				
			||||||
 | 
					    mut commands: Commands,
 | 
				
			||||||
 | 
					    mut meshes: ResMut<Assets<Mesh>>,
 | 
				
			||||||
 | 
					    mut materials: ResMut<Assets<ColorMaterial>>,
 | 
				
			||||||
 | 
					    window: Single<&Window>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    let material = materials.add(GUTTER_COLOR);
 | 
				
			||||||
 | 
					    let padding = 20.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let gutter_shape = Rectangle::new(window.resolution.width(), GUTTER_HEIGHT);
 | 
				
			||||||
 | 
					    let mesh = meshes.add(gutter_shape);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let top_gutter_position = Vec2::new(0., window.resolution.height() / 2. - padding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commands.spawn((
 | 
				
			||||||
 | 
					        Gutter,
 | 
				
			||||||
 | 
					        Mesh2d(mesh.clone()),
 | 
				
			||||||
 | 
					        MeshMaterial2d(material.clone()),
 | 
				
			||||||
 | 
					        Position(top_gutter_position),
 | 
				
			||||||
 | 
					        Collider(gutter_shape),
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let bottom_gutter_position = Vec2::new(0., -window.resolution.height() / 2. + padding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commands.spawn((
 | 
				
			||||||
 | 
					        Gutter,
 | 
				
			||||||
 | 
					        Mesh2d(mesh.clone()),
 | 
				
			||||||
 | 
					        MeshMaterial2d(material.clone()),
 | 
				
			||||||
 | 
					        Position(bottom_gutter_position),
 | 
				
			||||||
 | 
					        Collider(gutter_shape),
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PADDLE_SPEED: f32 = 5.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn handle_player_input(
 | 
				
			||||||
 | 
					    keyboard_input: Res<ButtonInput<KeyCode>>,
 | 
				
			||||||
 | 
					    mut paddle_velocity: Single<&mut Velocity, With<Player>>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    if keyboard_input.pressed(KeyCode::ArrowUp) {
 | 
				
			||||||
 | 
					        paddle_velocity.0.y = PADDLE_SPEED;
 | 
				
			||||||
 | 
					    } else if keyboard_input.pressed(KeyCode::ArrowDown) {
 | 
				
			||||||
 | 
					        paddle_velocity.0.y = -PADDLE_SPEED;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        paddle_velocity.0.y = 0.;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn move_paddles(mut paddles: Query<(&mut Position, &Velocity), With<Paddle>>) {
 | 
				
			||||||
 | 
					    for (mut position, velocity) in &mut paddles {
 | 
				
			||||||
 | 
					        position.0 += velocity.0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn constrain_paddle_position(
 | 
				
			||||||
 | 
					    mut paddles: Query<(&mut Position, &Collider), (With<Paddle>, Without<Gutter>)>,
 | 
				
			||||||
 | 
					    gutters: Query<(&Position, &Collider), (With<Gutter>, Without<Paddle>)>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    for (mut paddle_position, paddle_collider) in &mut paddles {
 | 
				
			||||||
 | 
					        for (gutter_position, gutter_collider) in &gutters {
 | 
				
			||||||
 | 
					            let paddle_aabb = Aabb2d::new(paddle_position.0, paddle_collider.half_size());
 | 
				
			||||||
 | 
					            let gutter_aabb = Aabb2d::new(gutter_position.0, gutter_collider.half_size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if let Some(collision) = collide_with_side(paddle_aabb, gutter_aabb) {
 | 
				
			||||||
 | 
					                match collision {
 | 
				
			||||||
 | 
					                    Collision::Top => {
 | 
				
			||||||
 | 
					                        paddle_position.0.y = gutter_position.0.y
 | 
				
			||||||
 | 
					                            + gutter_collider.half_size().y
 | 
				
			||||||
 | 
					                            + paddle_collider.half_size().y;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    Collision::Bottom => {
 | 
				
			||||||
 | 
					                        paddle_position.0.y = gutter_position.0.y
 | 
				
			||||||
 | 
					                            - gutter_collider.half_size().y
 | 
				
			||||||
 | 
					                            - paddle_collider.half_size().y;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    _ => {}
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn detect_goal(
 | 
				
			||||||
 | 
					    ball: Single<(&Position, &Collider), With<Ball>>,
 | 
				
			||||||
 | 
					    player: Query<Entity, (With<Player>, Without<Ai>)>,
 | 
				
			||||||
 | 
					    ai: Query<Entity, (With<Ai>, Without<Player>)>,
 | 
				
			||||||
 | 
					    window: Single<&Window>,
 | 
				
			||||||
 | 
					    mut scored_events: EventWriter<Scored>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    let (ball_position, ball_collider) = ball.into_inner();
 | 
				
			||||||
 | 
					    let half_window_size = window.resolution.size() / 2.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ball_position.0.x - ball_collider.half_size().x > half_window_size.x {
 | 
				
			||||||
 | 
					        if let Ok(player_entity) = player.get_single() {
 | 
				
			||||||
 | 
					            scored_events.send(Scored {
 | 
				
			||||||
 | 
					                scorer: player_entity,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ball_position.0.x + ball_collider.half_size().x < -half_window_size.x {
 | 
				
			||||||
 | 
					        if let Ok(ai_entity) = ai.get_single() {
 | 
				
			||||||
 | 
					            scored_events.send(Scored { scorer: ai_entity });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn reset_ball(
 | 
				
			||||||
 | 
					    mut scored_events: ResMut<Events<Scored>>,
 | 
				
			||||||
 | 
					    ball: Single<(&mut Position, &mut Velocity), With<Ball>>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    let mut reader = scored_events.get_reader();
 | 
				
			||||||
 | 
					    for _event in reader.read(&scored_events) {
 | 
				
			||||||
 | 
					        let (mut ball_position, mut ball_velocity) = ball.into_inner();
 | 
				
			||||||
 | 
					        ball_position.0 = Vec2::ZERO;
 | 
				
			||||||
 | 
					        ball_velocity.0 = Vec2::new(-BALL_SPEED, BALL_SPEED);
 | 
				
			||||||
 | 
					        // Clear the event after handling to prevent repeated processing
 | 
				
			||||||
 | 
					        scored_events.clear();
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn update_score(
 | 
				
			||||||
 | 
					    mut events: EventReader<Scored>,
 | 
				
			||||||
 | 
					    mut score: ResMut<Score>,
 | 
				
			||||||
 | 
					    is_ai: Query<&Ai>,
 | 
				
			||||||
 | 
					    is_player: Query<&Player>,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    for event in events.read() {
 | 
				
			||||||
 | 
					        if is_ai.get(event.scorer).is_ok() {
 | 
				
			||||||
 | 
					            score.ai += 1;
 | 
				
			||||||
 | 
					            info!("AI scored! {} - {}", score.player, score.ai);
 | 
				
			||||||
 | 
					        } else if is_player.get(event.scorer).is_ok() {
 | 
				
			||||||
 | 
					            score.player += 1;
 | 
				
			||||||
 | 
					            info!("Player scored! {} - {}", score.player, score.ai);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn spawn_scoreboard(mut commands: Commands) {
 | 
				
			||||||
 | 
					    // Create a container that will center everything
 | 
				
			||||||
 | 
					    let container = Node {
 | 
				
			||||||
 | 
					        width: percent(100.0),
 | 
				
			||||||
 | 
					        height: percent(100.0),
 | 
				
			||||||
 | 
					        justify_content: JustifyContent::Center,
 | 
				
			||||||
 | 
					        ..default()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Then add a container for the text
 | 
				
			||||||
 | 
					    let header = Node {
 | 
				
			||||||
 | 
					        width: px(200.),
 | 
				
			||||||
 | 
					        height: px(100.),
 | 
				
			||||||
 | 
					        ..default()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The players score on the left hand side
 | 
				
			||||||
 | 
					    let player_score = (
 | 
				
			||||||
 | 
					        PlayerScore,
 | 
				
			||||||
 | 
					        Text::new("0"),
 | 
				
			||||||
 | 
					        TextFont::from_font_size(72.0),
 | 
				
			||||||
 | 
					        TextColor(Color::WHITE),
 | 
				
			||||||
 | 
					        TextLayout::new_with_justify(Justify::Center),
 | 
				
			||||||
 | 
					        Node {
 | 
				
			||||||
 | 
					            position_type: PositionType::Absolute,
 | 
				
			||||||
 | 
					            top: px(5.0),
 | 
				
			||||||
 | 
					            left: px(25.0),
 | 
				
			||||||
 | 
					            ..default()
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The AI score on the right hand side
 | 
				
			||||||
 | 
					    let ai_score = (
 | 
				
			||||||
 | 
					        AiScore,
 | 
				
			||||||
 | 
					        Text::new("0"),
 | 
				
			||||||
 | 
					        TextFont::from_font_size(72.0),
 | 
				
			||||||
 | 
					        TextColor(Color::WHITE),
 | 
				
			||||||
 | 
					        TextLayout::new_with_justify(Justify::Center),
 | 
				
			||||||
 | 
					        Node {
 | 
				
			||||||
 | 
					            position_type: PositionType::Absolute,
 | 
				
			||||||
 | 
					            top: px(5.0),
 | 
				
			||||||
 | 
					            right: px(25.0),
 | 
				
			||||||
 | 
					            ..default()
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commands.spawn((
 | 
				
			||||||
 | 
					        container,
 | 
				
			||||||
 | 
					        children![(header, children![player_score, ai_score])],
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										96
									
								
								flake.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								flake.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "nodes": {
 | 
				
			||||||
 | 
					    "flake-utils": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "systems": "systems"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1710146030,
 | 
				
			||||||
 | 
					        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nixpkgs": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1725103162,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=",
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "ref": "nixos-unstable",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nixpkgs_2": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1718428119,
 | 
				
			||||||
 | 
					        "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=",
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "ref": "nixpkgs-unstable",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "root": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "flake-utils": "flake-utils",
 | 
				
			||||||
 | 
					        "nixpkgs": "nixpkgs",
 | 
				
			||||||
 | 
					        "rust-overlay": "rust-overlay"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "rust-overlay": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "nixpkgs": "nixpkgs_2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1725243956,
 | 
				
			||||||
 | 
					        "narHash": "sha256-0A5ZP8uDCyBdYUzayZfy6JFdTefP79oZVAjyqA/yuSI=",
 | 
				
			||||||
 | 
					        "owner": "oxalica",
 | 
				
			||||||
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
 | 
					        "rev": "a10c8092d5f82622be79ed4dd12289f72011f850",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "oxalica",
 | 
				
			||||||
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "systems": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "root": "root",
 | 
				
			||||||
 | 
					  "version": 7
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										70
									
								
								flake.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								flake.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  description = "Minimal Rust development environment for Bevy project";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inputs = {
 | 
				
			||||||
 | 
					    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
 | 
				
			||||||
 | 
					    rust-overlay.url = "github:oxalica/rust-overlay";
 | 
				
			||||||
 | 
					    flake-utils.url = "github:numtide/flake-utils";
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  outputs =
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      nixpkgs,
 | 
				
			||||||
 | 
					      rust-overlay,
 | 
				
			||||||
 | 
					      flake-utils,
 | 
				
			||||||
 | 
					      ...
 | 
				
			||||||
 | 
					    }:
 | 
				
			||||||
 | 
					    flake-utils.lib.eachDefaultSystem (
 | 
				
			||||||
 | 
					      system:
 | 
				
			||||||
 | 
					      let
 | 
				
			||||||
 | 
					        overlays = [ (import rust-overlay) ];
 | 
				
			||||||
 | 
					        pkgs = import nixpkgs { inherit system overlays; };
 | 
				
			||||||
 | 
					        rustToolchain = pkgs.rust-bin.stable.latest.default.override {
 | 
				
			||||||
 | 
					          extensions = [
 | 
				
			||||||
 | 
					            "rust-src"
 | 
				
			||||||
 | 
					            "rust-analyzer"
 | 
				
			||||||
 | 
					            "clippy"
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      in
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        devShells.default = pkgs.mkShell {
 | 
				
			||||||
 | 
					          nativeBuildInputs = with pkgs; [ pkg-config ];
 | 
				
			||||||
 | 
					          buildInputs = with pkgs; [
 | 
				
			||||||
 | 
					            rustup
 | 
				
			||||||
 | 
					            rustToolchain
 | 
				
			||||||
 | 
					            clang
 | 
				
			||||||
 | 
					            llvmPackages_latest.bintools
 | 
				
			||||||
 | 
					            udev
 | 
				
			||||||
 | 
					            alsa-lib
 | 
				
			||||||
 | 
					            vulkan-loader
 | 
				
			||||||
 | 
					            xorg.libX11
 | 
				
			||||||
 | 
					            xorg.libXcursor
 | 
				
			||||||
 | 
					            xorg.libXi
 | 
				
			||||||
 | 
					            xorg.libXrandr
 | 
				
			||||||
 | 
					            libxkbcommon
 | 
				
			||||||
 | 
					            wayland
 | 
				
			||||||
 | 
					            glibc.dev
 | 
				
			||||||
 | 
					            glib.dev
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          shellHook = ''
 | 
				
			||||||
 | 
					            export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
 | 
				
			||||||
 | 
					            export LD_LIBRARY_PATH=${
 | 
				
			||||||
 | 
					              pkgs.lib.makeLibraryPath [
 | 
				
			||||||
 | 
					                pkgs.vulkan-loader
 | 
				
			||||||
 | 
					                pkgs.libxkbcommon
 | 
				
			||||||
 | 
					                pkgs.wayland
 | 
				
			||||||
 | 
					                pkgs.alsa-lib
 | 
				
			||||||
 | 
					                pkgs.udev
 | 
				
			||||||
 | 
					              ]
 | 
				
			||||||
 | 
					            }:$LD_LIBRARY_PATH
 | 
				
			||||||
 | 
					            export LIBCLANG_PATH="${pkgs.llvmPackages_latest.libclang.lib}/lib"
 | 
				
			||||||
 | 
					            export BINDGEN_EXTRA_CLANG_ARGS="-I${pkgs.glibc.dev}/include -I${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include -I${pkgs.glib.dev}/include/glib-2.0 -I${pkgs.glib.out}/lib/glib-2.0/include/"
 | 
				
			||||||
 | 
					            export RUSTFLAGS="-C link-arg=-fuse-ld=lld"
 | 
				
			||||||
 | 
					            echo "Bevy development environment loaded!"
 | 
				
			||||||
 | 
					          '';
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								lib-utils/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								lib-utils/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "lib-utils"
 | 
				
			||||||
 | 
					version = { workspace = true }
 | 
				
			||||||
 | 
					edition = { workspace = true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					bevy = { workspace = true }
 | 
				
			||||||
 | 
					log = { workspace = true }
 | 
				
			||||||
							
								
								
									
										13
									
								
								lib-utils/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib-utils/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					use bevy::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn print_hello_world() {
 | 
				
			||||||
 | 
					    println!("Hello from utils crate!");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct UtilsPlugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Plugin for UtilsPlugin {
 | 
				
			||||||
 | 
					    fn build(&self, app: &mut App) {
 | 
				
			||||||
 | 
					        app.add_systems(Startup, print_hello_world);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								rust-toolchain.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								rust-toolchain.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[toolchain]
 | 
				
			||||||
 | 
					channel = "nightly"
 | 
				
			||||||
 | 
					components = ["rustfmt", "clippy"]
 | 
				
			||||||
		Reference in New Issue
	
	Block a user