Fun SET! button

main
Elijah Voigt 1 year ago
parent 7468817292
commit a47cd06a93

@ -2,6 +2,7 @@ use std::{f32::consts::PI, ops::RangeInclusive};
use bevy::{ use bevy::{
animation::{animated_field, AnimationTarget, AnimationTargetId}, animation::{animated_field, AnimationTarget, AnimationTargetId},
color::palettes::css::{BLACK, BLUE, GREEN, PINK, RED},
prelude::*, prelude::*,
utils::HashMap, utils::HashMap,
}; };
@ -15,7 +16,10 @@ pub struct AnimationPlugin;
impl Plugin for AnimationPlugin { impl Plugin for AnimationPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, delayed_animation); app.add_systems(Update, delayed_animation).add_systems(
Update,
animate_button.run_if(any_with_component::<AnimateButton>),
);
} }
} }
@ -25,12 +29,11 @@ struct AnimationComplete;
#[derive(Resource, Default)] #[derive(Resource, Default)]
pub(crate) struct AnimationStore { pub(crate) struct AnimationStore {
pub store: HashMap<String, AnimationNodeIndex>, pub store: HashMap<String, AnimationNodeIndex>,
pub graph: AnimationGraphHandle, pub card_graph: AnimationGraphHandle,
} }
#[derive(Component)] #[derive(Component)]
pub(crate) struct DelayedAnimation { pub(crate) struct DelayedAnimation {
pub graph: AnimationGraphHandle,
pub animation_index: AnimationNodeIndex, pub animation_index: AnimationNodeIndex,
pub delay: Timer, pub delay: Timer,
} }
@ -126,13 +129,9 @@ pub(crate) fn setup_animations(
}); });
} }
animation_store.graph = AnimationGraphHandle(graphs.add(animation_graph)); animation_store.card_graph = AnimationGraphHandle(graphs.add(animation_graph));
commands.insert_resource(animation_store); commands.insert_resource(animation_store);
// TODO: (example: https://bevyengine.org/examples/animation/animated-transform/)
// Button Animations:
// active_button_animation = AnimationClip::default() // color and size
} }
pub(crate) fn play_selected_animation( pub(crate) fn play_selected_animation(
@ -168,10 +167,36 @@ fn delayed_animation(
delayed_animation.delay.tick(time.delta()); delayed_animation.delay.tick(time.delta());
if delayed_animation.delay.just_finished() { if delayed_animation.delay.just_finished() {
animation_player.start(delayed_animation.animation_index); animation_player.start(delayed_animation.animation_index);
commands commands.entity(entity).remove::<DelayedAnimation>();
.entity(entity)
.insert(delayed_animation.graph.clone())
.remove::<DelayedAnimation>();
} }
}); });
} }
#[derive(Component)]
pub(crate) struct AnimateButton;
pub(crate) fn animate_button(
query: Single<(&mut BackgroundColor, &mut Transform), With<AnimateButton>>,
time: Res<Time>,
) {
// t is a value in the range (0..=1)
let t = (f32::cos(time.elapsed_secs_wrapped()) + 1.0) / 2.0;
let (mut bg, mut tr) = query.into_inner();
// We want values from 0..3 for picking a color
bg.0 = match t * 3.0 {
0.0..=1.0 => Srgba::interpolate(&RED, &GREEN, t % 1.0).into(),
1.0..=2.0 => Srgba::interpolate(&GREEN, &BLUE, t % 1.0).into(),
2.0..=3.0 => Srgba::interpolate(&BLUE, &RED, t % 1.0).into(),
_ => todo!(),
};
// We want angles from -0.5..0.5 for angle
tr.rotation = Quat::from_axis_angle(Vec3::Z, (t / 2.0) - 0.25);
if t > 0.5 {
tr.scale += time.delta_secs() / 20.0;
} else {
tr.scale -= time.delta_secs() / 20.0;
}
}

@ -4,6 +4,7 @@ mod boot;
mod deck; mod deck;
mod menu; mod menu;
mod play; mod play;
mod run_conditions;
mod setup; mod setup;
mod view; mod view;

@ -178,6 +178,9 @@ fn setup(mut commands: Commands, server: Res<AssetServer>) {
#[derive(Component)] #[derive(Component)]
pub(crate) struct SetCounter; pub(crate) struct SetCounter;
#[derive(Component)]
pub(crate) struct SetButton;
fn setup_play(mut commands: Commands, server: Res<AssetServer>) { fn setup_play(mut commands: Commands, server: Res<AssetServer>) {
commands commands
.spawn(( .spawn((
@ -277,6 +280,7 @@ fn setup_play(mut commands: Commands, server: Res<AssetServer>) {
}, },
BorderColor(WHITE.into()), BorderColor(WHITE.into()),
GlobalZIndex(1), GlobalZIndex(1),
SetButton,
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(Text("Set!".to_string())); parent.spawn(Text("Set!".to_string()));

@ -1,9 +1,10 @@
use bevy::{prelude::*, utils::RandomState}; use bevy::{prelude::*, utils::RandomState};
use crate::{ use crate::{
animation::{AnimationStore, DelayedAnimation}, animation::{animate_button, AnimateButton, AnimationStore, DelayedAnimation},
deck::{Card, Deck}, deck::{Card, Deck},
menu::{SetCounter, UiMessage}, menu::{SetButton, SetCounter, UiMessage},
run_conditions::any_component_added,
setup::TopCard, setup::TopCard,
view::ViewState, view::ViewState,
GameState, GameState,
@ -14,6 +15,12 @@ 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_event::<ServeCards>() app.add_event::<ServeCards>()
.add_systems(
Update,
update_trigger_button_animation
.run_if(any_component_added::<Selected>.or(any_component_removed::<Selected>))
.after(animate_button),
)
.add_systems(Update, serve_cards) .add_systems(Update, serve_cards)
.add_systems(OnEnter(GameState::NewGame), (reset_game, reset_set_counter)) .add_systems(OnEnter(GameState::NewGame), (reset_game, reset_set_counter))
.add_systems(OnEnter(ViewState::Play), deal_cards) .add_systems(OnEnter(ViewState::Play), deal_cards)
@ -94,7 +101,6 @@ pub(crate) fn check_set(
.remove::<Selected>() .remove::<Selected>()
.insert(DelayedAnimation { .insert(DelayedAnimation {
delay: Timer::from_seconds(0.1, TimerMode::Once), delay: Timer::from_seconds(0.1, TimerMode::Once),
graph: animation_store.graph.clone(),
animation_index: animation_index.clone(), animation_index: animation_index.clone(),
}) })
.insert(SetNumber(set_number)) .insert(SetNumber(set_number))
@ -287,7 +293,6 @@ pub(crate) fn place_card(
commands.entity(entity).insert(DelayedAnimation { commands.entity(entity).insert(DelayedAnimation {
animation_index: animation_index.clone(), animation_index: animation_index.clone(),
delay: Timer::from_seconds(delay, TimerMode::Once), delay: Timer::from_seconds(delay, TimerMode::Once),
graph: animation_store.graph.clone(),
}); });
// Set it to visible // Set it to visible
@ -381,3 +386,20 @@ fn reset_game(
fn reset_set_counter(mut query: Query<&mut Text, With<SetCounter>>) { fn reset_set_counter(mut query: Query<&mut Text, With<SetCounter>>) {
query.single_mut().0 = "##".into(); query.single_mut().0 = "##".into();
} }
fn update_trigger_button_animation(
button: Single<(Entity, &mut BackgroundColor, &mut Transform), With<SetButton>>,
selected: Query<Entity, With<Selected>>,
mut commands: Commands,
) {
info!("Stopping trigger button animation");
let (entity, mut bg, mut tr) = button.into_inner();
if selected.iter().len() == 3 {
commands.entity(entity).insert(AnimateButton);
} else {
bg.0 = Color::BLACK.with_alpha(0.9).into();
tr.rotation = Quat::IDENTITY;
tr.scale = Vec3::ONE;
commands.entity(entity).remove::<AnimateButton>();
}
}

@ -0,0 +1,5 @@
use bevy::prelude::*;
pub fn any_component_added<T: Component>(additions: Query<Entity, Added<T>>) -> bool {
!additions.is_empty()
}

@ -117,7 +117,7 @@ pub(crate) fn setup_cards(
this_sprite, this_sprite,
this_transform, this_transform,
visibility, visibility,
animation_store.graph.clone(), animation_store.card_graph.clone(),
)) ))
.observe(play::shuffle_card) .observe(play::shuffle_card)
.observe(play::place_card) .observe(play::place_card)

@ -1,10 +1,5 @@
TODO: TODO:
* Make "set" button visually interesting when 3 cards selected * Make "set" button visually interesting when 3 cards selected
* Make "how to play" fit on smaller screen resolution.
* I think scrolling makes the most sense... unfortunately
* Make background scale with window
* Scale cards with window resolution
* Genuinely not sure how to do this...
Later: Later:
* Make button(s) look pretty * Make button(s) look pretty

Loading…
Cancel
Save