They are very rough, but easy enough to improve with some simple
parsing.
selection-refactor
Elijah Voigt 2 years ago
parent 8a9b47be6b
commit 2c17ecb1cd

@ -0,0 +1,27 @@
# Martian Chess
An Icehouse game by Andrew Looney
Art by Sam Hall
Programming by Elijah Voigt
---
# Third Party Tools
Bevy Engine: bevyengine.org
FMOD/FMOD Studio: fmod.com
---
# Art Assets
Image Textures retrieved from textures.com:
Concrete Energy Pole - https://www.textures.com/download/PBR0340/136381
Space Blanket Folds - https://www.textures.com/download/PBR0152/133187
Background 2D art by NASA: LINK HERE

@ -0,0 +1,152 @@
use std::str::Utf8Error;
use bevy::{
asset::{AssetLoader, LoadContext, LoadedAsset},
reflect::{TypePath, TypeUuid},
utils::BoxedFuture,
};
use crate::prelude::*;
pub(crate) struct CreditsPlugin;
impl Plugin for CreditsPlugin {
fn build(&self, app: &mut App) {
app.add_asset::<CreditsText>()
.init_asset_loader::<CreditsTextLoader>()
.add_systems(Startup, init_credits_ui)
.add_systems(
Update,
(
update_credits.run_if(on_event::<AssetEvent<CreditsText>>()),
menu::exit_to_menu.run_if(in_state(GameState::Credits)),
),
)
.add_systems(
OnEnter(GameState::Credits),
activate::<Credits, CreditsCamera>,
)
.add_systems(
OnExit(GameState::Credits),
deactivate::<Credits, CreditsCamera>,
);
}
}
#[derive(Debug, TypeUuid, TypePath)]
#[uuid = "43df4a09-b5f0-4619-9223-8cf67dc9e844"]
pub struct CreditsText {
sections: Vec<TextSection>,
}
#[derive(Default)]
struct CreditsTextLoader;
impl AssetLoader for CreditsTextLoader {
fn load<'a>(
&'a self,
bytes: &'a [u8],
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), bevy::asset::Error>> {
Box::pin(async move {
let custom_asset = parse_credits(bytes)?;
load_context.set_default_asset(LoadedAsset::new(custom_asset));
Ok(())
})
}
fn extensions(&self) -> &[&str] {
&["credits.txt"]
}
}
fn parse_credits(bytes: &[u8]) -> Result<CreditsText, Utf8Error> {
let s = std::str::from_utf8(bytes)?;
let sections: Vec<TextSection> = s
.split('\n')
.filter(|l| l.len() > 0)
.map(|l| TextSection {
value: String::from(l),
..default()
})
.collect();
info!("Split lines: {:?}", s);
Ok(CreditsText { sections })
}
#[derive(Debug, Component)]
struct Credits;
#[derive(Debug, Component)]
struct CreditsCamera;
fn init_credits_ui(mut commands: Commands, server: Res<AssetServer>) {
commands.spawn((
CreditsCamera,
Camera2dBundle {
camera: Camera {
is_active: false,
..default()
},
..default()
},
UiCameraConfig { show_ui: true },
));
commands
.spawn((
Credits,
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
position_type: PositionType::Absolute,
..default()
},
visibility: Visibility::Hidden,
..default()
},
))
.with_children(|parent| {
let handle: Handle<CreditsText> = server.load("marian-chess.credits.txt");
parent.spawn((
handle.clone(),
TextBundle {
text: Text {
alignment: TextAlignment::Center,
sections: vec![],
..default()
},
background_color: Color::BLACK.with_a(0.5).into(),
..default()
},
));
});
}
fn update_credits(
mut reader: EventReader<AssetEvent<CreditsText>>,
credits_texts: Res<Assets<CreditsText>>,
mut query: Query<(&mut Text, &Handle<CreditsText>)>,
) {
reader.iter().for_each(|event| match event {
AssetEvent::Created { handle } | AssetEvent::Modified { handle } => {
query
.iter_mut()
.filter(|(_, this_handle)| handle.clone() == (*this_handle).clone())
.for_each(|(mut text, this_handle)| {
if let Some(credits_text) = credits_texts.get(this_handle) {
text.sections = credits_text.sections.clone();
}
});
}
AssetEvent::Removed { .. } => {
info!("Removed Credit resource... we don't handle that...");
}
})
}

@ -52,8 +52,14 @@ impl Plugin for Display2dPlugin {
set_transform, set_transform,
), ),
) )
.add_systems(OnEnter(GameState::Display2d), activate) .add_systems(
.add_systems(OnExit(GameState::Display2d), deactivate); OnEnter(GameState::Display2d),
activate::<Board2d, Display2dCamera>,
)
.add_systems(
OnExit(GameState::Display2d),
deactivate::<Board2d, Display2dCamera>,
);
} }
} }
@ -242,30 +248,6 @@ fn set_transform(
}); });
} }
fn activate(
mut cameras: Query<&mut Camera, With<Display2dCamera>>,
mut boards: Query<&mut Visibility, With<Board2d>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = true;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Visible;
});
}
fn deactivate(
mut cameras: Query<&mut Camera, With<Display2dCamera>>,
mut boards: Query<&mut Visibility, With<Board2d>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Hidden;
});
}
fn active_tile( fn active_tile(
mut events: EventReader<CursorMoved>, mut events: EventReader<CursorMoved>,
sprite_q: Query<( sprite_q: Query<(

@ -21,8 +21,14 @@ impl Plugin for Display3dPlugin {
.run_if(in_state(GameState::Display3d)) .run_if(in_state(GameState::Display3d))
.run_if(resource_exists::<debug::DebugEnabled>()), .run_if(resource_exists::<debug::DebugEnabled>()),
) )
.add_systems(OnEnter(GameState::Display3d), activate) .add_systems(
.add_systems(OnExit(GameState::Display3d), deactivate); OnEnter(GameState::Display3d),
activate::<Board3d, Display3dCamera>,
)
.add_systems(
OnExit(GameState::Display3d),
deactivate::<Board3d, Display3dCamera>,
);
} }
} }
@ -32,8 +38,12 @@ struct Board3d;
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub(crate) struct Piece3d; pub(crate) struct Piece3d;
#[derive(Debug, Component)]
struct Display3dCamera;
fn initialize_camera(mut commands: Commands) { fn initialize_camera(mut commands: Commands) {
commands.spawn(( commands.spawn((
Display3dCamera,
Camera3dBundle { Camera3dBundle {
camera: Camera { camera: Camera {
is_active: false, is_active: false,
@ -160,32 +170,6 @@ fn set_piece_position(
}); });
} }
/// Make this the active state
fn activate(
mut cameras: Query<&mut Camera, With<Camera3d>>,
mut boards: Query<&mut Visibility, With<Board3d>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = true;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Visible;
});
}
/// Make this the non-active state
fn deactivate(
mut cameras: Query<&mut Camera, With<Camera3d>>,
mut boards: Query<&mut Visibility, With<Board3d>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Hidden;
});
}
/// Given a board index returns the Vec3 location in space /// Given a board index returns the Vec3 location in space
fn board_translation(&BoardIndex { x, y }: &BoardIndex) -> Vec3 { fn board_translation(&BoardIndex { x, y }: &BoardIndex) -> Vec3 {
// Scale x down by 4 to account for -4..4 scaling // Scale x down by 4 to account for -4..4 scaling

@ -1,4 +1,5 @@
mod audio; mod audio;
mod credits;
mod debug; mod debug;
mod display2d; mod display2d;
mod display3d; mod display3d;
@ -10,7 +11,6 @@ use std::time::Duration;
use bevy::{ use bevy::{
asset::{ChangeWatcher, HandleId}, asset::{ChangeWatcher, HandleId},
gltf::{GltfMesh, GltfNode},
input::{keyboard::KeyboardInput, ButtonState}, input::{keyboard::KeyboardInput, ButtonState},
}; };
@ -50,15 +50,17 @@ fn main() {
display3d::Display3dPlugin, display3d::Display3dPlugin,
game::GamePlugin, game::GamePlugin,
menu::MenuPlugin, menu::MenuPlugin,
credits::CreditsPlugin,
)) ))
.run(); .run();
} }
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)] #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States, Component)]
pub enum GameState { pub enum GameState {
#[default] #[default]
Loading, Loading,
Menu, Menu,
Credits,
Display2d, Display2d,
Display3d, Display3d,
} }
@ -123,3 +125,27 @@ fn toggle_display_mode(
_ => (), _ => (),
}) })
} }
fn activate<E: Component, C: Component>(
mut cameras: Query<&mut Camera, With<C>>,
mut entities: Query<&mut Visibility, With<E>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = true;
});
entities.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Visible;
});
}
fn deactivate<E: Component, C: Component>(
mut cameras: Query<&mut Camera, With<C>>,
mut entities: Query<&mut Visibility, With<E>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false;
});
entities.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Hidden;
});
}

@ -14,15 +14,15 @@ impl Plugin for MenuPlugin {
.add_systems( .add_systems(
Update, Update,
( (
handle_menu_start, handle_menu_button,
handle_menu_quit, handle_menu_quit,
bevy::window::close_on_esc, bevy::window::close_on_esc,
interactive_button, interactive_button,
) )
.run_if(in_state(GameState::Menu)), .run_if(in_state(GameState::Menu)),
) )
.add_systems(OnEnter(GameState::Menu), activate) .add_systems(OnEnter(GameState::Menu), activate::<MenuRoot, MenuCamera>)
.add_systems(OnExit(GameState::Menu), deactivate); .add_systems(OnExit(GameState::Menu), deactivate::<MenuRoot, MenuCamera>);
} }
} }
@ -32,9 +32,6 @@ struct MenuCamera;
#[derive(Debug, Component)] #[derive(Debug, Component)]
struct MenuRoot; struct MenuRoot;
#[derive(Debug, Component)]
struct Start;
#[derive(Debug, Component)] #[derive(Debug, Component)]
struct Quit; struct Quit;
@ -72,7 +69,7 @@ fn init_menu_ui(mut commands: Commands) {
.with_children(|parent| { .with_children(|parent| {
parent parent
.spawn(( .spawn((
Start, GameState::Display2d,
ButtonBundle { ButtonBundle {
style: Style { style: Style {
padding: UiRect::all(Val::Px(5.0)), padding: UiRect::all(Val::Px(5.0)),
@ -85,7 +82,7 @@ fn init_menu_ui(mut commands: Commands) {
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(( parent.spawn((
Start, GameState::Display2d,
TextBundle::from_section( TextBundle::from_section(
"Start", "Start",
TextStyle { TextStyle {
@ -97,6 +94,33 @@ fn init_menu_ui(mut commands: Commands) {
)); ));
}); });
parent
.spawn((
GameState::Credits,
ButtonBundle {
style: Style {
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::ORANGE.with_a(0.5).into(),
..default()
},
))
.with_children(|parent| {
parent.spawn((
GameState::Credits,
TextBundle::from_section(
"Credits",
TextStyle {
color: Color::BLACK,
font_size: 32.0,
..default()
},
),
));
});
parent parent
.spawn(( .spawn((
Quit, Quit,
@ -126,38 +150,14 @@ fn init_menu_ui(mut commands: Commands) {
}); });
} }
fn activate( fn handle_menu_button(
mut cameras: Query<&mut Camera, With<MenuCamera>>, events: Query<(&Interaction, &GameState), (With<Button>, Changed<Interaction>)>,
mut boards: Query<&mut Visibility, With<MenuRoot>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = true;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Visible;
});
}
fn deactivate(
mut cameras: Query<&mut Camera, With<MenuCamera>>,
mut boards: Query<&mut Visibility, With<MenuRoot>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Hidden;
});
}
fn handle_menu_start(
events: Query<&Interaction, (With<Start>, With<Button>, Changed<Interaction>)>,
mut next_state: ResMut<NextState<GameState>>, mut next_state: ResMut<NextState<GameState>>,
) { ) {
events events
.iter() .iter()
.filter(|&interaction| *interaction == Interaction::Pressed) .filter(|(&interaction, _)| interaction == Interaction::Pressed)
.for_each(|_| next_state.set(GameState::Display2d)) .for_each(|(_, s)| next_state.set(s.clone()))
} }
fn handle_menu_quit( fn handle_menu_quit(

Loading…
Cancel
Save