In a good-ish spot, going to save

main
Elijah C. Voigt 2 years ago
parent f0a64541e1
commit 609ae8ebb9

@ -33,7 +33,7 @@ invalid = "/sfx/3D/3DInvalidMove"
# Options: Off, Sample2, Sample4, Sample8 # Options: Off, Sample2, Sample4, Sample8
# Requires: display3d.ssoa.quality_level = "Off" # Requires: display3d.ssoa.quality_level = "Off"
### ###
msaa = "Off" msaa = "Sample4"
### ###
# Enable HDR lighting # Enable HDR lighting
@ -62,8 +62,8 @@ valid_move = "Valid Move Spot"
[display3d.models.animations] [display3d.models.animations]
intro_a = "GameCamIntro1" intro_a = "GameCamIntro1"
intro_b = "GameCamIntro2" intro_b = "GameCamIntro2"
turn_a = "GameCamSide2>1" turn_b = "GameCamSide2>1"
turn_b = "GameCamSide1>2" turn_a = "GameCamSide1>2"
[display3d.models.animations.pick_up] [display3d.models.animations.pick_up]
pawn = "PawnPiecePickup" pawn = "PawnPiecePickup"
@ -113,7 +113,7 @@ Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.0 }
# https://docs.rs/bevy/0.11.3/bevy/pbr/enum.FogFalloff.html # https://docs.rs/bevy/0.11.3/bevy/pbr/enum.FogFalloff.html
### ###
[display3d.fog.falloff] [display3d.fog.falloff]
Exponential = { density = 0.000 } Exponential = { density = 1.0 }
# Examples: # Examples:
# * Linear = { start = 1.0, end = 10.0 } # * Linear = { start = 1.0, end = 10.0 }
# * Exponential = { density = 1.0 } # * Exponential = { density = 1.0 }

@ -36,7 +36,7 @@ impl Plugin for AudioPlugin {
#[derive(Event, Debug, PartialEq, Component, Clone)] #[derive(Event, Debug, PartialEq, Component, Clone)]
pub enum AudioEvent { pub enum AudioEvent {
MainMusic, MainMusic,
StopMainMusic, _StopMainMusic,
MenuHover, MenuHover,
MenuSelect, MenuSelect,
PickUp, PickUp,
@ -56,7 +56,7 @@ fn play_audio(mut events: Query<&AudioSource, Added<AudioSource>>) {
fn audio_trigger( fn audio_trigger(
mut events: EventReader<AudioEvent>, mut events: EventReader<AudioEvent>,
sources: Query<(&AudioSource, &AudioEvent)>, sources: Query<(Entity, &AudioSource, &AudioEvent)>,
studio: Res<FmodStudio>, studio: Res<FmodStudio>,
mut commands: Commands, mut commands: Commands,
server: Res<AssetServer>, server: Res<AssetServer>,
@ -69,7 +69,7 @@ fn audio_trigger(
let state = display_state.get(); let state = display_state.get();
events.read().for_each(|event| { events.read().for_each(|event| {
let aud = match event { let aud = match event {
AudioEvent::MainMusic | AudioEvent::StopMainMusic => { AudioEvent::MainMusic | AudioEvent::_StopMainMusic => {
tweak.get::<String>("audio_music_main").unwrap() tweak.get::<String>("audio_music_main").unwrap()
} }
AudioEvent::MenuHover => tweak.get::<String>("audio_menu_hover").unwrap(), AudioEvent::MenuHover => tweak.get::<String>("audio_menu_hover").unwrap(),
@ -79,7 +79,7 @@ fn audio_trigger(
AudioEvent::Idle | AudioEvent::StopIdle => tweak.get::<String>("audio_display3d_idle").unwrap(), AudioEvent::Idle | AudioEvent::StopIdle => tweak.get::<String>("audio_display3d_idle").unwrap(),
AudioEvent::Invalid => tweak.get::<String>("audio_display3d_invalid").unwrap(), AudioEvent::Invalid => tweak.get::<String>("audio_display3d_invalid").unwrap(),
}; };
// There is an event for this // There is an event, play an audio
if !aud.is_empty() { if !aud.is_empty() {
let event_str = format!("event:{}", aud); let event_str = format!("event:{}", aud);
if let Ok(event_description) = studio.0.get_event(event_str.as_str()) { if let Ok(event_description) = studio.0.get_event(event_str.as_str()) {
@ -90,25 +90,28 @@ fn audio_trigger(
AudioEvent::StopIdle => { AudioEvent::StopIdle => {
sources sources
.iter() .iter()
.filter(|(_, source_event)| **source_event == AudioEvent::Idle) .filter(|(_, _, source_event)| **source_event == AudioEvent::Idle)
.for_each(|(source, _)| { .for_each(|(entity, source, _)| {
info!("Stopping audio {}", event_str); info!("Stopping audio {}", event_str);
source.stop(); source.stop();
commands.entity(entity).despawn_recursive();
}); });
} }
// Find and stop playing instances of main music // Find and stop playing instances of main music
AudioEvent::StopMainMusic => { AudioEvent::_StopMainMusic => {
sources sources
.iter() .iter()
.filter(|(_, source_event)| **source_event == AudioEvent::MainMusic) .filter(|(_, _, source_event)| **source_event == AudioEvent::MainMusic)
.for_each(|(source, _)| { .for_each(|(entity, source, _)| {
info!("Stopping audio {}", event_str); info!("Stopping audio {}", event_str);
source.stop(); source.stop();
commands.entity(entity).despawn_recursive();
}); });
} }
// we are playing a sound // we are playing a sound
_ => { _ => {
info!("Playing audio {}", event_str); info!("Playing audio {}", event_str);
// TODO: Can we batch spawn all sounds at startup? Then Start/Stop/Reset at runtime?
commands.spawn((audio_source, event.clone())); commands.spawn((audio_source, event.clone()));
} }
} }

@ -32,7 +32,7 @@ impl Plugin for Display3dPlugin {
.insert_resource(Msaa::Off) .insert_resource(Msaa::Off)
.add_systems( .add_systems(
OnExit(GameState::Loading), OnExit(GameState::Loading),
(initialize, fix_skybox.before(initialize)), (initialize, fix_skybox.before(initialize), update_tweaks.run_if(resource_exists::<tweak::GameTweaks>()),),
) )
.add_systems( .add_systems(
Update, Update,
@ -44,9 +44,10 @@ impl Plugin for Display3dPlugin {
set_piece_model.run_if(any_component_added::<Piece>), set_piece_model.run_if(any_component_added::<Piece>),
set_board_model.run_if(any_component_added::<game::BoardComponent>), set_board_model.run_if(any_component_added::<game::BoardComponent>),
set_board_model.run_if(any_component_added::<TilesComponent>), set_board_model.run_if(any_component_added::<TilesComponent>),
set_valid_move_model.run_if(any_component_added::<game::ValidMove>),
set_tile_hitbox.run_if(any_component_added::<game::Tile>), set_tile_hitbox.run_if(any_component_added::<game::Tile>),
set_piece_position.run_if(any_component_changed::<BoardIndex>), set_piece_position.run_if(any_component_changed::<BoardIndex>),
set_piece_texture.run_if(any_component_changed::<Side>), set_piece_texture.run_if(any_component_changed::<Side>).run_if(resource_exists::<tweak::GameTweaks>()),
select select
.run_if(in_state(GameState::Play)) .run_if(in_state(GameState::Play))
.run_if(in_state(DisplayState::Display3d)) .run_if(in_state(DisplayState::Display3d))
@ -56,8 +57,7 @@ impl Plugin for Display3dPlugin {
switch_sides switch_sides
.run_if(in_state(GameState::Play)) .run_if(in_state(GameState::Play))
.run_if(state_changed::<game::TurnState>()), .run_if(state_changed::<game::TurnState>()),
set_valid_move_model.run_if(any_component_added::<game::ValidMove>), update_tweaks.run_if(on_event::<AssetEvent<Tweaks>>()).run_if(resource_exists::<tweak::GameTweaks>()),
update_tweaks.run_if(on_event::<AssetEvent<Tweaks>>()),
scale_lighting.run_if( scale_lighting.run_if(
any_component_added::<DirectionalLight> any_component_added::<DirectionalLight>
.or_else(any_component_added::<SpotLight>) .or_else(any_component_added::<SpotLight>)
@ -84,11 +84,10 @@ impl Plugin for Display3dPlugin {
OnEnter(DisplayState::Display3d), OnEnter(DisplayState::Display3d),
( (
activate::<Display3d>, activate::<Display3d>,
set_piece_texture, set_piece_texture.run_if(resource_exists::<tweak::GameTweaks>()),
opening_animation opening_animation
.run_if(run_once()) .run_if(run_once())
.run_if(in_state(GameState::Play)), .run_if(in_state(GameState::Play)),
update_tweaks,
), ),
) )
.add_systems(OnExit(DisplayState::Display3d), deactivate::<Display3d>) .add_systems(OnExit(DisplayState::Display3d), deactivate::<Display3d>)
@ -97,6 +96,7 @@ impl Plugin for Display3dPlugin {
( (
activate::<Display3d>.run_if(in_state(DisplayState::Display3d)), activate::<Display3d>.run_if(in_state(DisplayState::Display3d)),
set_piece_texture, set_piece_texture,
update_tweaks.run_if(resource_exists::<tweak::GameTweaks>()),
opening_animation opening_animation
.run_if(run_once()) .run_if(run_once())
.run_if(in_state(DisplayState::Display3d)), .run_if(in_state(DisplayState::Display3d)),
@ -160,6 +160,8 @@ fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<Asset
// Hitboxes // Hitboxes
game::tiles().for_each(|(index, tile)| { game::tiles().for_each(|(index, tile)| {
let side = Board::side(index).expect("Spawn valid side");
parent.spawn(( parent.spawn((
Display3d, Display3d,
index, index,
@ -170,12 +172,15 @@ fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<Asset
visibility: Visibility::Hidden, visibility: Visibility::Hidden,
..default() ..default()
}, },
side,
game::Selectable, game::Selectable,
)); ));
}); });
// Valid move indicators // Valid move indicators
game::tiles().for_each(|(index, _)| { game::tiles().for_each(|(index, _)| {
let side = Board::side(index).expect("Spawn valid side");
parent.spawn(( parent.spawn((
Display3d, Display3d,
index, index,
@ -184,6 +189,7 @@ fn initialize(mut commands: Commands, board: Res<game::Board>, assets: Res<Asset
transform: Transform::from_translation(board_translation(&index)), transform: Transform::from_translation(board_translation(&index)),
..default() ..default()
}, },
side,
game::ValidMove, game::ValidMove,
)); ));
}); });
@ -232,7 +238,7 @@ fn hydrate_camera(
DisplayState::Display3d, DisplayState::Display3d,
Camera3dBundle { Camera3dBundle {
camera: Camera { camera: Camera {
is_active: false, is_active: true,
hdr: tweak.get::<bool>("display3d_hdr").unwrap(), hdr: tweak.get::<bool>("display3d_hdr").unwrap(),
..default() ..default()
}, },
@ -732,9 +738,10 @@ fn select(
meshes: Res<Assets<Mesh>>, meshes: Res<Assets<Mesh>>,
cameras: Query<(&Camera, &GlobalTransform)>, cameras: Query<(&Camera, &GlobalTransform)>,
windows: Query<&Window, With<PrimaryWindow>>, windows: Query<&Window, With<PrimaryWindow>>,
selectable: Query<(Entity, &BoardIndex), (With<game::Selectable>, With<Display3d>)>, selectable: Query<(Entity, &BoardIndex, &Side, Option<&Piece>), (With<game::Selectable>, With<Display3d>)>,
children: Query<&Children>, children: Query<&Children>,
mut selections: EventWriter<game::Selection>, mut selections: EventWriter<game::Selection>,
state: Res<State<game::TurnState>>,
) { ) {
events events
.read() .read()
@ -753,15 +760,20 @@ fn select(
hit::intersects3d(&ray, mesh, &gt).and_then(|_hit| { hit::intersects3d(&ray, mesh, &gt).and_then(|_hit| {
selectable selectable
.iter() .iter()
.find_map(|(e, &board_index)| { .find_map(|(e, &board_index, &side, piece_ish)| {
// A child was hit (pieces) // Check if this piece is on the active side
let primary = entity == e; let side_check = piece_ish.is_some() && *state.get() == side;
// This entity was hit (tile hitboxes) // This entity was hit (tile hitboxes)
let primary = entity == e;
// A child was hit (pieces)
let secondary = children let secondary = children
.iter_descendants(e) .iter_descendants(e)
.any(|child| child == entity); .any(|child| child == entity);
(primary || secondary).then_some(board_index) (side_check && (primary || secondary)).then_some(board_index)
}) })
.iter() .iter()
.for_each(|&board_index| { .for_each(|&board_index| {
@ -804,7 +816,7 @@ fn moves_gizmo(
} }
fn set_valid_move_model( fn set_valid_move_model(
mut events: Query<&mut Handle<Scene>, (With<Display3d>, Added<game::ValidMove>)>, mut events: Query<(&mut Handle<Scene>, &mut Visibility), (With<Display3d>, Added<game::ValidMove>)>,
gltfs: Res<Assets<Gltf>>, gltfs: Res<Assets<Gltf>>,
tweaks: Res<Assets<Tweaks>>, tweaks: Res<Assets<Tweaks>>,
tweaks_file: Res<tweak::GameTweaks>, tweaks_file: Res<tweak::GameTweaks>,
@ -816,7 +828,7 @@ fn set_valid_move_model(
.get_handle::<Gltf>("display3d_models_assets_file") .get_handle::<Gltf>("display3d_models_assets_file")
.unwrap(); .unwrap();
if let Some(gltf) = gltfs.get(assets_handle) { if let Some(gltf) = gltfs.get(assets_handle) {
events.iter_mut().for_each(|mut handle| { events.iter_mut().for_each(|(mut handle, mut visibility)| {
*handle = gltf *handle = gltf
.named_scenes .named_scenes
.get( .get(
@ -826,7 +838,9 @@ fn set_valid_move_model(
.as_str(), .as_str(),
) )
.unwrap() .unwrap()
.clone() .clone();
*visibility = Visibility::Hidden;
}) })
} }
} }

@ -12,6 +12,7 @@ impl Plugin for GamePlugin {
.add_state::<TurnState>() .add_state::<TurnState>()
.insert_resource(Score { ..default() }) .insert_resource(Score { ..default() })
.add_systems(Startup, setup_board) .add_systems(Startup, setup_board)
.add_systems(OnEnter(GameState::Play), hide_valid_moves)
.add_systems( .add_systems(
Update, Update,
( (
@ -24,9 +25,6 @@ impl Plugin for GamePlugin {
buttons.just_pressed(MouseButton::Right) buttons.just_pressed(MouseButton::Right)
}), }),
handle_selection.run_if(on_event::<Selection>()), handle_selection.run_if(on_event::<Selection>()),
switch_sides.run_if(|input: Res<Input<KeyCode>>| -> bool {
input.just_pressed(KeyCode::N)
}),
show_valid_moves.run_if(any_component_added::<Selected>), show_valid_moves.run_if(any_component_added::<Selected>),
hide_valid_moves.run_if(any_component_removed::<Selected>()), hide_valid_moves.run_if(any_component_removed::<Selected>()),
manage_score.run_if(any_component_added::<Captured>), manage_score.run_if(any_component_added::<Captured>),
@ -45,11 +43,34 @@ impl Plugin for GamePlugin {
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)] #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
pub(crate) enum TurnState { pub(crate) enum TurnState {
#[default]
SideA, SideA,
// HACK: Opening animation starts on B side
#[default]
SideB, SideB,
} }
impl std::ops::Not for TurnState {
type Output = Self;
fn not(self) -> Self::Output {
match self {
TurnState::SideA => TurnState::SideB,
TurnState::SideB => TurnState::SideA,
}
}
}
// Allow comparison between turn state and sides
impl PartialEq<Side> for TurnState {
fn eq(&self, other: &Side) -> bool {
match (self, other) {
(TurnState::SideA, Side::A) | (TurnState::SideB, Side::B) => true,
(TurnState::SideB, Side::A) | (TurnState::SideA, Side::B) => false,
}
}
}
#[derive(Debug, Component, Clone, PartialEq, Copy, Hash)] #[derive(Debug, Component, Clone, PartialEq, Copy, Hash)]
pub(crate) enum Piece { pub(crate) enum Piece {
Pawn, Pawn,
@ -481,18 +502,25 @@ pub(crate) fn update_board(
selected: Query<Entity, With<Selected>>, selected: Query<Entity, With<Selected>>,
mut commands: Commands, mut commands: Commands,
mut played: Local<bool>, mut played: Local<bool>,
curr_state: Res<State<TurnState>>,
mut next_state: ResMut<NextState<TurnState>>,
) { ) {
events.read().for_each(|Move { from, to, .. }| { events.read().for_each(|Move { from, to, .. }| {
pieces.iter_mut().for_each(|(entity, mut index)| { pieces.iter_mut().for_each(|(entity, mut index)| {
if *index == *from { if *index == *from {
match to { match to {
Some(to_idx) => { Some(to_idx) => {
info!("Moving piece {:?} to {:?}", entity, to_idx); info!("Moving piece {:?} {:?} -> {:?}", entity, from, to_idx);
*index = to_idx.clone(); *index = to_idx.clone();
if !(*played) { if !(*played) {
audio_events.send(audio::AudioEvent::PutDown); audio_events.send(audio::AudioEvent::PutDown);
audio_events.send(audio::AudioEvent::StopIdle); audio_events.send(audio::AudioEvent::StopIdle);
*played = true; *played = true;
if *from != *to_idx {
let ns = !*curr_state.get() ;
info!("Piece moved, switching sides: {:?}", ns);
next_state.set(ns);
}
} }
} }
None => { None => {
@ -650,26 +678,19 @@ fn asserts<T: Component>(
} }
} }
fn switch_sides(state: Res<State<TurnState>>, mut next: ResMut<NextState<TurnState>>) {
match state.get() {
TurnState::SideA => next.set(TurnState::SideB),
TurnState::SideB => next.set(TurnState::SideA),
}
}
/// Spawn "Valid move" indicators when a piece is selected /// Spawn "Valid move" indicators when a piece is selected
/// Another system registers these new entities and associates the correct models and plays animations. /// Another system registers these new entities and associates the correct models and plays animations.
fn show_valid_moves( fn show_valid_moves(
events: Query<&BoardIndex, (With<Piece>, Added<Selected>)>, events: Query<&BoardIndex, (With<Piece>, Added<Selected>)>,
board: Res<Board>, board: Res<Board>,
mut valid_moves: Query<(&BoardIndex, &mut Visibility), With<ValidMove>>, mut indicators: Query<(&BoardIndex, &mut Visibility), With<ValidMove>>,
) { ) {
// When a piece is selected // When a piece is selected
events.iter().for_each(|idx| { events.iter().for_each(|idx| {
// Iterate over all ValidMove entities // Iterate over all ValidMove entities
// For each one with a ValidMove index, make it visible // For each one with a ValidMove index, make it visible
board.valid_moves(*idx).iter().for_each(|idx| { board.valid_moves(*idx).iter().for_each(|idx| {
valid_moves.iter_mut().for_each(|(i, mut vis)| { indicators.iter_mut().for_each(|(i, mut vis)| {
if i == idx { if i == idx {
*vis = Visibility::Inherited; *vis = Visibility::Inherited;
} }
@ -680,12 +701,9 @@ fn show_valid_moves(
/// Hide "Valid Move" indicators when a piece is de-selected /// Hide "Valid Move" indicators when a piece is de-selected
fn hide_valid_moves( fn hide_valid_moves(
mut events: RemovedComponents<Selected>, mut indicators: Query<&mut Visibility, With<ValidMove>>,
mut valid_moves: Query<&mut Visibility, With<ValidMove>>,
) { ) {
events.read().for_each(|_| { indicators.iter_mut().for_each(|mut visibility| {
valid_moves.iter_mut().for_each(|mut visibility| { *visibility = Visibility::Hidden;
*visibility = Visibility::Hidden;
});
}); });
} }

@ -1,8 +1,6 @@
use bevy::{ use bevy::render::{
render::{ mesh::{MeshVertexAttribute, VertexAttributeValues},
mesh::{MeshVertexAttribute, VertexAttributeValues}, render_resource::VertexFormat,
render_resource::VertexFormat,
},
}; };
use crate::prelude::*; use crate::prelude::*;

@ -101,7 +101,7 @@ fn toggle_display_camera(
} }
fn activate<Marker: Component>( fn activate<Marker: Component>(
mut entities: Query<&mut Visibility, (With<Marker>, Without<game::Captured>)>, mut entities: Query<&mut Visibility, (With<Marker>, Without<game::Captured>, Without<game::ValidMove>)>,
) { ) {
entities.iter_mut().for_each(|mut visibility| { entities.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Visible; *visibility = Visibility::Visible;

@ -50,6 +50,16 @@ fn init_menu_ui(mut commands: Commands) {
}, },
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(
TextBundle::from_section(
"M A R T I A N C H E S S",
TextStyle {
font_size: 48.0,
color: Color::ORANGE_RED,
..default()
},
)
);
parent parent
.spawn(( .spawn((
GameState::Play, GameState::Play,

Loading…
Cancel
Save