返回

c#-如何检测WPF中两个形状是否发生碰撞

发布时间:2022-06-20 05:57:27 244
# flask

我有这段代码可以让用户在 WPF 的画布上绘制圆形、正方形或矩形。我需要这样做,这样一旦按下换档按钮,形状就会相互反弹。让形状从窗户的墙壁上反弹很容易,但我不知道如何让它们相互反弹。这是当前代码:

MainWindow.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Windows.Threading;
    
namespace ShapeAnimator
{
    ///
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        bool isFirstClick = true;
        double x1, y1, x2, y2, x3, y3;
        int shapeChoice =0;
        Ellipse centerMark;
        Ellipse tempCircle = new Ellipse();
        Rectangle tempRect = new Rectangle();

        List circles = new List();
        List rectangles = new List();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void SquareButton_Click(object sender, RoutedEventArgs e)
        {
            shapeChoice = 1;
        }

        private void CircleButton_Click(object sender, RoutedEventArgs e)
        {
            shapeChoice = 0;
        }

        private void RectButton_Click(object sender, RoutedEventArgs e)
        {
            shapeChoice = 2;
        }

        private void ShiftButton_Click(object sender, RoutedEventArgs e)
        {
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(2);
            timer.Tick += Timer_Tick;
            timer.Start();
        }

        void Timer_Tick(object sender, EventArgs e)
        {
            Shift();
        }

        public void Shift()
        {
            foreach (Circle c in circles)
            {
                c.Shift(ShapeCanvas);
            }
            foreach (Rect r in rectangles)
            {
                r.Shift(ShapeCanvas);
            }
        }

        private void ShapeCanvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (isFirstClick)
            {
                // This is the first click
                // This is the CENTER coordinates (NOT the TOPLEFT)
                x1 = e.GetPosition(this).X;
                y1 = e.GetPosition(this).Y;

                if(shapeChoice == 0)
                {
                    centerMark = new Ellipse();
                    centerMark.Width = 4;
                    centerMark.Height = 4;
                    centerMark.Stroke = Brushes.Red;
                    ShapeCanvas.Children.Add(centerMark);
                    Canvas.SetLeft(centerMark, x1 - 2);
                    Canvas.SetTop(centerMark, y1 - 2);

                    ShapeCanvas.Children.Add(tempCircle);
                }
                else if (shapeChoice == 1)
                {
                    ShapeCanvas.Children.Add(tempRect);
                }
                else if (shapeChoice == 2)
                {
                    ShapeCanvas.Children.Add(tempRect);
                }

            }
            else
            {
                // THis is the second click
                double x2 = e.GetPosition(this).X;
                double y2 = e.GetPosition(this).Y;

                if (shapeChoice == 0)
                {
                    double radius = Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

                    Circle c = new Circle(x1, y1, radius);
                    c.Draw(ShapeCanvas);
                    circles.Add(c);

                    // remove the temp geometry
                    ShapeCanvas.Children.Remove(tempCircle);
                    ShapeCanvas.Children.Remove(centerMark);
                }
                else if(shapeChoice == 1)
                {
                    double x3 = Math.Min(x1, x2);
                    double y3 = Math.Min(y1, y2);

                    double width = Math.Max(x1, x2) - x3;
                    double height = width;

                    Rect rec = new Rect(x3, y3, width, height);
                    rec.Draw(ShapeCanvas);
                    rectangles.Add(rec);

                    // remove the temp geometry
                    ShapeCanvas.Children.Remove(tempRect);
                }
                else if (shapeChoice == 2)
                {
                    double x3 = Math.Min(x1, x2);
                    double y3 = Math.Min(y1, y2);

                    double width = Math.Max(x1, x2) - x3;
                    double height = Math.Max(y1, y2) - y3;

                    Rect rec = new Rect(x3, y3, width, height);
                    rec.Draw(ShapeCanvas);
                    rectangles.Add(rec);

                    // remove the temp geometry
                    ShapeCanvas.Children.Remove(tempRect);
                }


            }

            isFirstClick = !isFirstClick;
        }

        private void ShapeCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (isFirstClick)
            {
                return;
            }

            x3 = e.GetPosition(this).X;
            y3 = e.GetPosition(this).Y;

            if(shapeChoice == 0)
            {
                double radius = Math.Sqrt((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1));

                tempCircle.Width = radius * 2;
                tempCircle.Height = radius * 2;
                tempCircle.Stroke = Brushes.Red;
                //ShapeCanvas.Children.Add(ellipse);
                Canvas.SetLeft(tempCircle, x1 - radius);
                Canvas.SetTop(tempCircle, y1 - radius);
            }
            else if(shapeChoice == 1)
            {
                double x2 =  Math.Min(x1, x3);
                double y2 =  Math.Min(y1, y3);

                double width = Math.Max(x1, x3) - x2;
                double height = Math.Max(y1, y3) - y2;

                tempRect.Width = width;
                tempRect.Height = width;
                tempRect.Stroke = Brushes.Blue;
                Canvas.SetLeft(tempRect, x2);
                Canvas.SetTop(tempRect, y2);
            }
            else if (shapeChoice == 2)
            {
                double x2 = Math.Min(x1, x3);
                double y2 = Math.Min(y1, y3);

                double width = Math.Max(x1, x3) - x2;
                double height = Math.Max(y1, y3) - y2;

                tempRect.Width = width;
                tempRect.Height = height;
                tempRect.Stroke = Brushes.Green;
                Canvas.SetLeft(tempRect, x2);
                Canvas.SetTop(tempRect, y2);
            }


        }

    }
}

Circle.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;


namespace ShapeAnimator
{
    internal class Circle
    {
        public Ellipse Ell = new Ellipse();
        public double X;
        public double Y;
        public double Radius;
        public int DeltaX = 1;
        public int DeltaY = 1;

        public Circle(double x, double y, double r)
        {
            X = x; Y = y; Radius = r;
        }

        public void Draw(Canvas canvas)
        {
            Ell.Width = 2 * Radius;
            Ell.Height = 2 * Radius;
            Ell.Stroke = Brushes.Red;
            Canvas.SetLeft(Ell, X - Radius);
            Canvas.SetTop(Ell, Y - Radius);
            canvas.Children.Add(Ell);
        }

        public void Shift(Canvas canvas)
        {
            // Flip direction if hitting left & right walls
            if (X + Radius > canvas.ActualWidth
                || X - Radius < 0)
            {
                DeltaX = -DeltaX;
            }

            // Flip direction if hitting left & right walls
            if (Y + Radius > canvas.ActualHeight
                || Y - Radius < 0)
            {
                DeltaY = -DeltaY;
            }


            X = X + DeltaX;
            Y = Y + DeltaY;
            Canvas.SetLeft(Ell, X - Radius);
            Canvas.SetTop(Ell, Y - Radius);
        }
    }
}

Rect.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace ShapeAnimator
{
    internal class Rect
    {
        public Rectangle Rec = new Rectangle();
        public double X;
        public double Y;
        public double Width;
        public double Height;
        public int DeltaX = 1;
        public int DeltaY = 1;

        public Rect(double x, double y, double width, double height)
        {
            X = x; Y = y; Width = width; Height = height;
        }

        public void Draw(Canvas canvas)
        {
            Rec.Width = Width;
            Rec.Height = Height;
            if (Rec.Width == Rec.Height)
                Rec.Stroke = Brushes.Blue;
            else
                Rec.Stroke = Brushes.Green;
            Canvas.SetLeft(Rec, X);
            Canvas.SetTop(Rec, Y);
            canvas.Children.Add(Rec);
        }

        public void Shift(Canvas canvas)
        {

            // Flip direction if hitting left & right walls
            if (X + Width > canvas.ActualWidth
                || X < 0)
            {
                DeltaX = -DeltaX;
            }

            // Flip direction if hitting left & right walls
            if (Y + Height > canvas.ActualHeight
                || Y < 0)
            {
                DeltaY = -DeltaY;
            }

            

            X = X + DeltaX;
            Y = Y + DeltaY;
            Canvas.SetLeft(Rec, X);
            Canvas.SetTop(Rec, Y);
        }

    }
}
MainWindow.xaml

<Window x:Class="ShapeAnimator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ShapeAnimator"
        mc:Ignorable="d"
        Title="Shape Animator" Height="450" Width="800"
        Background="Black">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Canvas Name="ShapeCanvas" 
                Grid.Column="0" Grid.Row="0"
                Background="Black"
                Height="380"
                MouseUp="ShapeCanvas_MouseUp"
                MouseMove="ShapeCanvas_MouseMove"
                >
            
        </Canvas>
        <WrapPanel Grid.Column="0" Grid.Row="1" 
                   VerticalAlignment="Bottom" HorizontalAlignment="Center"
                   Margin="10">
            <Button Width="150" Height="30" Click="CircleButton_Click">Circle</Button>
            <Button Width="150" Margin="15 0" Click="SquareButton_Click">Square</Button>
            <Button Width="150" Click="RectButton_Click">Rectangle</Button>
            <Button Width="150" Click="ShiftButton_Click" Margin="15 0" >Shift</Button>
        </WrapPanel>
    </Grid>
</Window>
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(1)
按点赞数排序
用户头像