card-game/src/card/mod.rs

135 lines
3.6 KiB
Rust

use std::f32;
use crate::animation::transform::AnimatedTransform;
use bevy::prelude::*;
use drag::*;
pub mod drag;
pub struct CardPlugin;
#[derive(Component)]
pub struct Card;
#[derive(Component)]
pub struct CardInHand;
#[derive(Component)]
pub struct Hand(Vec<Entity>);
#[derive(Resource)]
pub struct CardImage(Handle<Image>);
#[derive(Event)]
pub struct AddCard;
#[derive(EntityEvent)]
pub struct InsertCard(Entity);
#[derive(Event)]
pub struct ClearCards;
impl Plugin for CardPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, hand_setup)
.add_systems(Update, card_arrange)
.add_observer(card_add)
.add_observer(card_clear)
.add_observer(insert_card);
app.insert_resource(MousePosition(Vec3::new(0., 0., 0.)))
.add_systems(PreUpdate, mouse_position_system)
.add_observer(card_drag_start)
.add_observer(card_drag)
.add_observer(card_drag_end);
}
}
fn hand_setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn((
Hand(Vec::new()),
Transform::from_xyz(0., -360., 0.),
InheritedVisibility::VISIBLE,
));
commands.insert_resource(CardImage(
asset_server.load::<Image>("sprites/cards/units/fosma.png"),
));
}
fn card_arrange(
mut query: Query<(&mut AnimatedTransform, &Sprite), With<CardInHand>>,
hand: Single<(Entity, &Hand, &Transform)>,
assets: Res<Assets<Image>>,
) {
let cards_amount = hand.1.0.len();
for (index, card) in hand.1.0.iter().enumerate() {
let Ok((mut transform, sprite)) = query.get_mut(card.clone()) else {
continue;
};
let size = assets.get(&sprite.image).unwrap().size_f32();
let left_boundary = -size.x * (cards_amount as f32) / 2.0 + size.x / 2.0;
transform.translation.x = left_boundary + size.x * index as f32 + hand.2.translation.x;
transform.translation.y = size.y / 2.0 + hand.2.translation.y;
}
}
fn card_add(
_: On<AddCard>,
mut commands: Commands,
card_image: Res<CardImage>,
mut hand: Single<&mut Hand>,
) {
let card = commands
.spawn((
Sprite::from_image(card_image.0.clone()),
Transform::from_xyz(0., 0., 0.),
AnimatedTransform::from_xyz(0., 0., 0.),
Card,
DraggableCard,
CardInHand,
Pickable::default(),
))
.id();
hand.0.push(card);
}
fn card_clear(_: On<ClearCards>, mut commands: Commands, mut hand: Single<&mut Hand>) {
for card in &hand.0 {
let entity = card.clone();
commands.entity(entity).despawn();
}
hand.0.clear();
}
fn insert_card(
event: On<InsertCard>,
mut hand_query: Single<(Entity, &mut Hand)>,
transform_query: Query<&Transform, With<Card>>,
) {
let Ok(inserted_transform) = transform_query.get(event.0) else {
return;
};
let mut decided_index: usize = 0;
let mut decided_diff: f32 = f32::INFINITY;
for (index, card) in hand_query.1.0.iter().enumerate() {
let Ok(card_transform) = transform_query.get(card.clone()) else {
continue;
};
let calculated_diff =
(inserted_transform.translation - card_transform.translation).length();
if decided_diff > calculated_diff {
decided_diff = calculated_diff;
decided_index = index;
}
}
if let Some(pos) = hand_query.1.0.iter().position(|ent| *ent == event.0) {
hand_query.1.0.remove(pos);
}
hand_query.1.0.insert(decided_index, event.0);
}