Algorithm for dragging objects on a fixed grid
        Posted  
        
            by FlyingStreudel
        on Stack Overflow
        
        See other posts from Stack Overflow
        
            or by FlyingStreudel
        
        
        
        Published on 2010-06-17T15:20:04Z
        Indexed on 
            2010/06/17
            15:23 UTC
        
        
        Read the original article
        Hit count: 322
        
Hello, I am working on a program for the mapping and playing of the popular tabletop game D&D :D Right now I am working on getting the basic functionality like dragging UI elements around, snapping to the grid and checking for collisions.
Right now every object when released from the mouse immediately snaps to the nearest grid point. This causes an issue when something like a player object snaps to a grid point that has a wall -or other- adjacent. So essentially when the player is dropped they wind up with some of the wall covering them. This is fine and working as intended, however the problem is that now my collision detection is tripped whenever you try to move this player because its sitting underneath a wall and because of this you cant drag the player anymore.
Here is the relevant code:
void UIObj_MouseMove(object sender, MouseEventArgs e)  
{  
            blocked = false;  
            if (dragging)  
            {  
                foreach (UIElement o in ((Floor)Parent).Children)  
                {  
                    if (o.GetType() != GetType() && o.GetType().BaseType == typeof(UIObj) &&  
                        Math.Sqrt(Math.Pow(((UIObj)o).cX - cX, 2) + Math.Pow(((UIObj)o).cY - cY, 2)) <  
                        Math.Max(r.Height + ((UIObj)o).r.Height, r.Width + ((UIObj)o).r.Width))  
                    {  
                        double Y = e.GetPosition((Floor)Parent).Y;  
                        double X = e.GetPosition((Floor)Parent).X;  
                        Geometry newRect = new RectangleGeometry(new Rect(Margin.Left + (X - prevX),  
                        Margin.Top + (Y - prevY), Margin.Right + (X - prevX), Margin.Bottom + (Y - prevY)));  
                        GeometryHitTestParameters ghtp = new GeometryHitTestParameters(newRect);  
                        VisualTreeHelper.HitTest(o, null, new HitTestResultCallback(MyHitTestResultCallback), ghtp);  
                    }  
                }  
                if (!blocked)  
                {  
                    Margin = new Thickness(Margin.Left + (e.GetPosition((Floor)Parent).X - prevX),  
                        Margin.Top + (e.GetPosition((Floor)Parent).Y - prevY),  
                        Margin.Right + (e.GetPosition((Floor)Parent).X - prevX),  
                        Margin.Bottom + (e.GetPosition((Floor)Parent).Y - prevY));  
                    InvalidateVisual();  
                }
                prevX = e.GetPosition((Floor)Parent).X;  
                prevY = e.GetPosition((Floor)Parent).Y;  
                cX = Margin.Left + r.Width / 2;  
                cY = Margin.Top + r.Height / 2;  
            }  
        }  
internal virtual void SnapToGrid()  
        {  
            double xPos = Margin.Left;  
            double yPos = Margin.Top;  
            double xMarg =  xPos % ((Floor)Parent).cellDim;  
            double yMarg =  yPos % ((Floor)Parent).cellDim;  
            if (xMarg < ((Floor)Parent).cellDim / 2)  
            {  
                if (yMarg < ((Floor)Parent).cellDim / 2)  
                {  
                    Margin = new Thickness(xPos - xMarg, yPos - yMarg, xPos - xMarg + r.Width, yPos - yMarg + r.Height);
                    }  
                else  
                {  
                    Margin = new Thickness(xPos - xMarg, yPos - yMarg + ((Floor)Parent).cellDim, xPos - xMarg + r.Width,
                        yPos - yMarg + ((Floor)Parent).cellDim + r.Height);  
                }  
            }  
            else  
            {
                if (yMarg < ((Floor)Parent).cellDim / 2)
                {
                    Margin = new Thickness(xPos - xMarg + ((Floor)Parent).cellDim, yPos - yMarg,
                        xPos - xMarg + ((Floor)Parent).cellDim + r.Width, yPos - yMarg + r.Height);
                }
                else
                {
                    Margin = new Thickness(xPos - xMarg + ((Floor)Parent).cellDim, yPos - yMarg + ((Floor)Parent).cellDim,
                        xPos - xMarg + ((Floor)Parent).cellDim + r.Width, yPos - yMarg + ((Floor)Parent).cellDim + r.Height);
                }
            }
        }
Essentially I am looking for a simple way to modify the existing code to allow the movement of a UI element that has another one sitting on top of it. Thanks!
© Stack Overflow or respective owner