Tripper
Tripper

Reputation: 27

C# Delete UIElement whenever another UIElement passes him

I have made a Canvas (playArea) on which I added 1 Bee (by using playArea.children.Add(bee)). And I also add new box every X seconds at random points on the playArea. I'm able to move my bee from the current point to the point I click using Storyboard and DoubleAnimation.

What I want to do is I want to delete the box which bee is passing through (like it should just do playAre.Children.Remove(box). I just can't figure it out how to check it.

example

Here's an example. If I would click on A, my bee would go to that point and remove the 3 boxes on it's way. I was thinking I should probably use my own EventHandler (I'm not sure how to make my own yet, but that's another problem). So any ides what should I do, or what condition I should make?

EDIT: Here's how my methods I use looks like. What I do at the beggining, I just draw a bee and add it to my canvas, and every X seconds I just add a new box at random location

    //moving the bee to the position which I got from Point p = Mouse.GetPosition(playArea);
    public static void MoveBee(UIElement element, double toX, double toY)
    {
        double fromX = Canvas.GetLeft(element);
        double fromY = Canvas.GetTop(element);

        Storyboard storyboard = new Storyboard();
        DoubleAnimation animationX = CreateDoubleAnimation(element,
            fromX, toX, new PropertyPath(Canvas.LeftProperty));
        DoubleAnimation animationY = CreateDoubleAnimation(element,
            fromY, toY, new PropertyPath(Canvas.TopProperty));
        storyboard.Children.Add(animationX);
        storyboard.Children.Add(animationY);
        storyboard.Begin();
    }

    public static DoubleAnimation CreateDoubleAnimation(UIElement element,
        double from, double to, PropertyPath propertyToAnimate)
    {
        DoubleAnimation animation = new DoubleAnimation();
        Storyboard.SetTarget(animation, element);
        Storyboard.SetTargetProperty(animation, propertyToAnimate);
        animation.From = from;
        animation.To = to;
        animation.Duration = TimeSpan.FromSeconds(3);
        return animation;
    }

    public void DrawBox()
    {
        BoxControl newBox = new BoxControl();
        playArea.Children.Add(newBox);
        Canvas.SetTop(newBox, random.Next(0, 419));
        Canvas.SetLeft(newBox, random.Next(0, 792));
    }

Upvotes: 1

Views: 91

Answers (1)

Kyle Dev-ious
Kyle Dev-ious

Reputation: 72

You could use the CurrentTimeInvalidated event handler on your animations. See code below for details.

Valid XHTML


public partial class MainWindow : Window
{
    public Random Rng { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        Rng = new Random(0);

        do
        {
            AddBoxToRandomPointInPlayArea();
        } while (PlayArea.Children.Count < 10);

    }

    private void AddBoxToRandomPointInPlayArea()
    {
        var x = Rng.Next(0, Convert.ToInt32(PlayArea.Width));
        var y = Rng.Next(0, Convert.ToInt32(PlayArea.Height));

        var box = new Rectangle
        {
            Height = 10,
            Width = 30,
            Fill = Brushes.Brown
        };

        PlayArea.Children.Add(box);

        Canvas.SetLeft(box, x);
        Canvas.SetTop(box, y);
    }

    private void PlayArea_MouseDown(object sender, MouseButtonEventArgs e)
    {
        var x = Canvas.GetLeft(Bee);
        var y = Canvas.GetTop(Bee);

        var storyboard = new Storyboard();

        var xTranslation = new DoubleAnimation(x, e.GetPosition(PlayArea).X, new Duration(new TimeSpan(0, 0, 5)));
        Storyboard.SetTargetProperty(xTranslation, new PropertyPath(Canvas.LeftProperty));
        xTranslation.CurrentTimeInvalidated += CheckForCollidingBoxesAndRemoveIfNeeded;

        storyboard.Children.Add(xTranslation);

        var yTranslation = new DoubleAnimation(y, e.GetPosition(PlayArea).Y, new Duration(new TimeSpan(0, 0, 5)));
        Storyboard.SetTargetProperty(yTranslation, new PropertyPath(Canvas.TopProperty));
        yTranslation.CurrentTimeInvalidated += CheckForCollidingBoxesAndRemoveIfNeeded; 

        storyboard.Children.Add(yTranslation);

        Bee.BeginStoryboard(storyboard);
    }


    private void CheckForCollidingBoxesAndRemoveIfNeeded(object sender, EventArgs eventArgs)
    {
        var idxToRemoveAt = GetIndexOfBoxCollidingWithBee;
        if ( idxToRemoveAt != -1 )
        {
            PlayArea.Children.RemoveAt(idxToRemoveAt);
        }
    }

    /// <summary>
    /// returns 0 if no boxes collide, otherwise the number is the index of the box in the 
    /// </summary>
    public int GetIndexOfBoxCollidingWithBee
    {
        get
        {
            var beeTopLeft = PointToScreen(new Point(Canvas.GetLeft(Bee), Canvas.GetTop(Bee))); // local to world coordinates
            var beeCentroid = new Point((beeTopLeft.X + Bee.ActualWidth) * 0.5, (beeTopLeft.Y + Bee.ActualHeight) * 0.5); // center point of bee

            for (var idx = 0; idx < PlayArea.Children.Count; idx++)
            {
                var child = PlayArea.Children[idx];
                var currentBoxInSearch = child as Rectangle;
                if (currentBoxInSearch != null)
                {
                    var boxTopLeft = PointToScreen(new Point(Canvas.GetLeft(currentBoxInSearch), Canvas.GetTop(currentBoxInSearch))); // local to world coordinates
                    var boxCentroid = new Point((boxTopLeft.X + currentBoxInSearch.ActualWidth) * 0.5, (boxTopLeft.Y + currentBoxInSearch.ActualHeight) * 0.5); // center point of bee

                    var xCollided = false;
                    var yCollided = false;

                    if (Math.Abs(beeCentroid.X - boxCentroid.X) < Bee.ActualWidth*0.5)
                        xCollided = true;

                    if (Math.Abs(beeCentroid.Y - boxCentroid.Y) < Bee.ActualHeight*0.5)
                        yCollided = true;

                    if (xCollided && yCollided)
                        return idx;
                }
            }

            return -1;
        }
    }
}

Upvotes: 2

Related Questions