use crate::blood::handle_blood_grain; use crate::bone::handle_bone_grain; use crate::grid::{Grid, GridPosition}; use crate::utils::constants::{GAME_RESOLUTION_X, GAME_RESOLUTION_Y, WINDOW_SIZE}; use crate::utils::remap::remap_cursor_position; use crate::utils::tick::TickCounter; use bevy::prelude::*; use bevy::sprite::Anchor; use rand::Rng; /* 🦀 Components. Learn more: https://bevy-cheatbook.github.io/programming/res.html */ #[derive(Component)] pub struct Grain { pub grain_type: GrainType, pub velocity: Vec2, // Physics-based movement pub mass: f32, pub is_simulated: bool, } #[derive(Component)] pub struct Lifetime(pub u32); #[derive(Component, Clone, Copy, Debug, PartialEq)] pub enum GrainType { Bone, Blood, } #[derive(Component, PartialEq)] pub enum Direction { Right, Left, None, } impl Default for Direction { fn default() -> Self { Direction::None } } #[derive(Bundle)] pub struct GrainBundle { pub grain: Grain, pub lifetime: Lifetime, pub direction: Direction, pub grid_position: GridPosition, pub sprite_bundle: SpriteBundle, } impl GrainBundle { pub fn new( grain_type: GrainType, x: i32, y: i32, color: Color, size: Vec2, ) -> Self { GrainBundle { grain: Grain { grain_type, velocity: Vec2::ZERO, mass: 1.0, is_simulated: true, }, lifetime: Lifetime(0), direction: Direction::None, grid_position: GridPosition::new(x, y), sprite_bundle: SpriteBundle { sprite: Sprite { color, custom_size: Some(size), anchor: Anchor::Center, ..default() }, transform: Transform::from_translation(Vec3::new(x as f32, y as f32, 0.0)), ..default() }, } } } pub fn spawn_grain( mut commands: Commands, mouse_button_input: Res>, windows: Query<&Window>, camera: Query<(&Camera, &GlobalTransform)>, ) { if mouse_button_input.just_pressed(MouseButton::Left) { let window = windows.single(); let (camera, camera_transform) = camera.single(); if let Some(cursor_position) = window.cursor_position() { if let Some(world_position) = camera.viewport_to_world(camera_transform, cursor_position) { let grid_pos = remap_cursor_position(world_position.origin.truncate()); commands.spawn(GrainBundle::new( GrainType::Blood, grid_pos.x, grid_pos.y, Color::RED, Vec2::splat(1.0), )); } } } if mouse_button_input.just_pressed(MouseButton::Right) { let window = windows.single(); let (camera, camera_transform) = camera.single(); if let Some(cursor_position) = window.cursor_position() { if let Some(world_position) = camera.viewport_to_world(camera_transform, cursor_position) { let grid_pos = remap_cursor_position(world_position.origin.truncate()); commands.spawn(GrainBundle::new( GrainType::Bone, grid_pos.x, grid_pos.y, Color::WHITE, Vec2::splat(1.0), )); } } } } pub fn update_grains( mut query: Query<(&mut Transform, &mut GridPosition, &mut Grain, &mut Lifetime, &mut Direction)>, mut grid: ResMut, time: Res