|
|
|
@ -6,9 +6,11 @@ pub struct PlayPlugin;
|
|
|
|
|
|
|
|
|
|
|
|
impl Plugin for PlayPlugin {
|
|
|
|
impl Plugin for PlayPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.add_observer(serve_new_cards)
|
|
|
|
app.add_event::<ServeCards>()
|
|
|
|
.add_systems(OnEnter(GameState::Main), serve_cards)
|
|
|
|
.add_observer(serve_cards)
|
|
|
|
.add_systems(Update, rotate_cards);
|
|
|
|
.add_observer(fill_cards)
|
|
|
|
|
|
|
|
.add_systems(OnEnter(GameState::Main), deal_table)
|
|
|
|
|
|
|
|
.add_systems(Update, spin_cards);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -32,7 +34,7 @@ pub(crate) struct PlayLocation {
|
|
|
|
pub(crate) struct SetNumber(pub u8);
|
|
|
|
pub(crate) struct SetNumber(pub u8);
|
|
|
|
|
|
|
|
|
|
|
|
/// Debug system rotating selected cards for visual flare
|
|
|
|
/// Debug system rotating selected cards for visual flare
|
|
|
|
fn rotate_cards(mut query: Query<&mut Transform, (With<Card>, With<Selected>)>, time: Res<Time>) {
|
|
|
|
fn spin_cards(mut query: Query<&mut Transform, (With<Card>, With<Selected>)>, time: Res<Time>) {
|
|
|
|
let dt = time.delta().as_secs_f32();
|
|
|
|
let dt = time.delta().as_secs_f32();
|
|
|
|
query.iter_mut().for_each(|mut t| {
|
|
|
|
query.iter_mut().for_each(|mut t| {
|
|
|
|
t.rotate_z(dt * 0.5);
|
|
|
|
t.rotate_z(dt * 0.5);
|
|
|
|
@ -116,12 +118,17 @@ fn is_set((a, b, c): (&Card, &Card, &Card)) -> bool {
|
|
|
|
color && number && pattern && shape
|
|
|
|
color && number && pattern && shape
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Event, Clone)]
|
|
|
|
|
|
|
|
struct ServeCards;
|
|
|
|
|
|
|
|
|
|
|
|
/// When requested, fill in empty spots on the board with cards
|
|
|
|
/// When requested, fill in empty spots on the board with cards
|
|
|
|
fn serve_cards(
|
|
|
|
fn serve_cards(
|
|
|
|
|
|
|
|
_trigger: Trigger<ServeCards>,
|
|
|
|
cards: Query<(Entity, &DeckOrder)>,
|
|
|
|
cards: Query<(Entity, &DeckOrder)>,
|
|
|
|
spots: Query<&PlayLocation>,
|
|
|
|
spots: Query<&PlayLocation>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
|
|
|
|
info!("Serving cards");
|
|
|
|
let mut target = (cards.iter().len() - 1) as u8;
|
|
|
|
let mut target = (cards.iter().len() - 1) as u8;
|
|
|
|
// Iterate over every x, y play location
|
|
|
|
// Iterate over every x, y play location
|
|
|
|
for this_x in 0..=3 {
|
|
|
|
for this_x in 0..=3 {
|
|
|
|
@ -148,36 +155,16 @@ fn serve_cards(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn serve_new_cards(
|
|
|
|
/// Trigger dealing cards when the game starts
|
|
|
|
_trigger: Trigger<OnAdd, SetNumber>,
|
|
|
|
fn deal_table(mut commands: Commands) {
|
|
|
|
cards: Query<(Entity, &DeckOrder)>,
|
|
|
|
info!("Dealing table");
|
|
|
|
spots: Query<&PlayLocation>,
|
|
|
|
commands.trigger(ServeCards);
|
|
|
|
mut commands: Commands,
|
|
|
|
}
|
|
|
|
) {
|
|
|
|
|
|
|
|
let mut target = (cards.iter().len() - 1) as u8;
|
|
|
|
/// Trigger serving cards when a new set is created
|
|
|
|
// Iterate over every x, y play location
|
|
|
|
fn fill_cards(_trigger: Trigger<OnAdd, SetNumber>, mut commands: Commands) {
|
|
|
|
for this_x in 0..=3 {
|
|
|
|
info!("Filling cards");
|
|
|
|
for this_y in 0..=3 {
|
|
|
|
commands.trigger(ServeCards);
|
|
|
|
// If this spot does not have a card
|
|
|
|
|
|
|
|
if spots
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.find(|PlayLocation { x, y }| *x == (this_x as u8) && *y == (this_y as u8))
|
|
|
|
|
|
|
|
.is_none()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if let Some((e, _)) = cards.iter().find(|(_, deck_order)| deck_order.0 == target) {
|
|
|
|
|
|
|
|
// Set the selected card to this play location and remove from the deck
|
|
|
|
|
|
|
|
commands
|
|
|
|
|
|
|
|
.entity(e)
|
|
|
|
|
|
|
|
.remove::<DeckOrder>()
|
|
|
|
|
|
|
|
.insert(PlayLocation {
|
|
|
|
|
|
|
|
x: this_x,
|
|
|
|
|
|
|
|
y: this_y,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
target = target - 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// When a card is added to the board, place it on the screen
|
|
|
|
/// When a card is added to the board, place it on the screen
|
|
|
|
@ -207,7 +194,7 @@ pub(crate) fn check_for_sets(
|
|
|
|
selected: Query<Entity, With<Selected>>,
|
|
|
|
selected: Query<Entity, With<Selected>>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
cards
|
|
|
|
let candidate = cards
|
|
|
|
// Iterate over all combinations of cards on the board
|
|
|
|
// Iterate over all combinations of cards on the board
|
|
|
|
.iter_combinations()
|
|
|
|
.iter_combinations()
|
|
|
|
// Only find combinations including currently selected cards
|
|
|
|
// Only find combinations including currently selected cards
|
|
|
|
@ -237,17 +224,19 @@ pub(crate) fn check_for_sets(
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|(a, b, c)| {
|
|
|
|
|
|
|
|
if !selected.contains(*a) {
|
|
|
|
|
|
|
|
commands.entity(*a).insert(Selected);
|
|
|
|
|
|
|
|
} else if !selected.contains(*b) {
|
|
|
|
|
|
|
|
commands.entity(*b).insert(Selected);
|
|
|
|
|
|
|
|
} else if !selected.contains(*c) {
|
|
|
|
|
|
|
|
commands.entity(*c).insert(Selected);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
info!("I cannot hold your hand further...");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some((a, b, c)) = candidate {
|
|
|
|
|
|
|
|
if !selected.contains(a) {
|
|
|
|
|
|
|
|
commands.entity(a).insert(Selected);
|
|
|
|
|
|
|
|
} else if !selected.contains(b) {
|
|
|
|
|
|
|
|
commands.entity(b).insert(Selected);
|
|
|
|
|
|
|
|
} else if !selected.contains(c) {
|
|
|
|
|
|
|
|
commands.entity(c).insert(Selected);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
info!("I cannot hold your hand further...");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
info!("No sets!");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|