mod audio; mod credits; mod debug; mod display2d; mod display3d; mod game; mod loading; mod menu; mod prelude; use std::time::Duration; use bevy::{ asset::{ChangeWatcher, HandleId}, input::{keyboard::KeyboardInput, ButtonState}, }; use crate::prelude::*; fn main() { if std::env::var_os("CARGO_MANIFEST_DIR").is_none() { std::env::set_var("CARGO_MANIFEST_DIR", "."); } App::new() .add_state::() .add_systems(Update, state.run_if(resource_changed::>())) .add_systems(Update, loading.run_if(in_state(GameState::Loading))) .add_systems( Update, toggle_display_mode.run_if(on_event::()), ) .add_plugins(( DefaultPlugins .set(ImagePlugin::default_nearest()) .set(WindowPlugin { primary_window: Some(Window { title: "Martian Chess".into(), resolution: (640., 480.).into(), ..default() }), ..default() }) .set(AssetPlugin { watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(200)), ..default() }), audio::AudioPlugin, credits::CreditsPlugin, debug::DebugPlugin, display2d::Display2dPlugin, display3d::Display3dPlugin, game::GamePlugin, loading::LoadingPlugin, menu::MenuPlugin, )) .run(); } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States, Component)] pub enum GameState { #[default] Loading, Menu, Credits, Display2d, Display3d, } fn loading( server: Res, sprites: Res>, gltfs: Res>, mut next_state: ResMut>, ) { let s_ids = sprites .ids() .filter(|&id| matches!(id, HandleId::AssetPathId(_))) .collect::>(); let g_ids = gltfs .ids() .filter(|&id| matches!(id, HandleId::AssetPathId(_))) .collect::>(); debug!( "Sprite len: {:?} | GLTF len: {:?}", s_ids.len(), g_ids.len() ); if s_ids.len() > 0 && g_ids.len() > 0 { let s_ready = s_ids .iter() .all(|&id| server.get_load_state(id) == LoadState::Loaded); let g_ready = g_ids .iter() .all(|&id| server.get_load_state(id) == LoadState::Loaded); if s_ready && g_ready { next_state.set(GameState::Menu) } } } /// System for printing the current state /// /// Only runs when state is modified. fn state(state: Res>) { info!("State is {:?}", *state); } fn toggle_display_mode( mut events: EventReader, state: Res>, mut next_state: ResMut>, ) { events .iter() .filter( |KeyboardInput { key_code, state, .. }| (*key_code, *state) == (Some(KeyCode::Space), ButtonState::Pressed), ) .for_each(|_| match state.get() { GameState::Display2d => next_state.set(GameState::Display3d), GameState::Display3d => next_state.set(GameState::Display2d), _ => (), }) } fn activate( mut cameras: Query<&mut Camera, With>, mut entities: Query<&mut Visibility, With>, ) { cameras.iter_mut().for_each(|mut camera| { camera.is_active = true; }); entities.iter_mut().for_each(|mut visibility| { *visibility = Visibility::Visible; }); } fn deactivate( mut cameras: Query<&mut Camera, With>, mut entities: Query<&mut Visibility, With>, ) { cameras.iter_mut().for_each(|mut camera| { camera.is_active = false; }); entities.iter_mut().for_each(|mut visibility| { *visibility = Visibility::Hidden; }); } pub(crate) fn any_component_changed(q: Query>) -> bool { !q.is_empty() } pub(crate) fn any_component_added(q: Query>) -> bool { !q.is_empty() }