不规则图形的碰撞检测

public static class CheckHit
{
    public static bool CheckCollision(FrameworkElement control1, FrameworkElement controlElem1, FrameworkElement control2, FrameworkElement controlElem2)
    {
        // first see if sprite rectangles collide
        Rect rect1 = UserControlBounds(control1);
        Rect rect2 = UserControlBounds(control2);
        rect1.Intersect(rect2);
        if (rect1 == Rect.Empty)
        {
            // no collision - GET OUT!
            return false;
        }
        else
        {
            bool bCollision = false;
            Point ptCheck = new Point();
            // NOTE that creating the writeablebitmap is a bit intense
            // so we will do this once and store results in Tag property
            // in a real game, you might abstract this into a Sprite class.

            if (controlElem1 is Image)
                controlElem1.Tag = GetWriteableBitmap(control1);
            if (controlElem2 is Image)
                controlElem2.Tag = GetWriteableBitmap(control2);

            // now we do a more accurate pixel hit test

            for (int x = Convert.ToInt32(rect1.X); x < Convert.ToInt32(rect1.X + rect1.Width); x++)
            {
                for (int y = Convert.ToInt32(rect1.Y); y < Convert.ToInt32(rect1.Y + rect1.Height); y++)
                {
                    ptCheck.X = x;
                    ptCheck.Y = y;

                    if (CheckCollisionPoint(ptCheck, control1, controlElem1))
                        if (CheckCollisionPoint(ptCheck, control2, controlElem2))
                        {
                            bCollision = true;
                            break;
                        }
                }
                if (bCollision) break;
            }
            return bCollision;
        }
    }

    private static bool CheckCollisionPoint(Point pt, FrameworkElement control, FrameworkElement controlElem)
    {
        if (controlElem is Image)
        {
            // NOTE that we saved the WB in the Tag object for performance.
            // in a real app, you would abstract this in your sprite class.
            WriteableBitmap wb = controlElem.Tag as WriteableBitmap;
            int width = wb.PixelWidth;
            double offSetX = Convert.ToDouble(control.GetValue(Canvas.LeftProperty));
            double offSetY = Convert.ToDouble(control.GetValue(Canvas.TopProperty));
            pt.X = pt.X - offSetX;
            pt.Y = pt.Y - offSetY;
            int offset = Convert.ToInt32((width * pt.Y) + pt.X);
            return (wb.Pixels[offset] != 0);
        }
        else
        {

            List<UIElement> hits = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(pt, controlElem) as List<UIElement>;
            return (hits.Contains(controlElem));
        }

    }

    private static WriteableBitmap GetWriteableBitmap(FrameworkElement control)
    {
        WriteableBitmap wb = new WriteableBitmap((int)control.Width, (int)control.Height);
        wb.Render(control, new TranslateTransform());
        wb.Invalidate();

        return wb;
    }

    private static Rect UserControlBounds(FrameworkElement control)
    {
        Point ptTopLeft = new Point(Convert.ToDouble(control.GetValue(Canvas.LeftProperty)), Convert.ToDouble(control.GetValue(Canvas.TopProperty)));
        Point ptBottomRight = new Point(Convert.ToDouble(control.GetValue(Canvas.LeftProperty)) + control.Width, Convert.ToDouble(control.GetValue(Canvas.TopProperty)) + control.Height);

        return new Rect(ptTopLeft, ptBottomRight);
    }
}

posted @ 2010-02-07 16:32  王喆(nasa)  阅读(1744)  评论(0编辑  收藏  举报