Algorithm for dragging objects on a fixed grid
- by FlyingStreudel
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!