代码之家  ›  专栏  ›  技术社区  ›  FlyingStreudel

在固定网格上拖动对象的算法

  •  3
  • FlyingStreudel  · 技术社区  · 15 年前

    我正在开发一个程序,用于绘制和播放流行的桌面游戏d&d:d,现在我正在开发基本功能,如拖动UI元素、捕捉网格和检查碰撞。

    现在,从鼠标中释放的每个对象都会立即捕捉到最近的网格点。当类似于播放器对象的对象捕捉到具有墙或其他相邻的网格点时,这会导致问题。所以基本上,当玩家被扔下时,他们会被一些墙覆盖起来。这很好,可以按预期工作,但是问题是,现在每当你试图移动这个播放器时,我的碰撞检测就会被触发,因为它位于墙下,因此你不能再拖动它了。

    相关代码如下:

    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);
                    }
                }
            }
    

    本质上,我正在寻找一种简单的方法来修改现有的代码,以允许一个UI元素的移动,而另一个元素则位于该元素之上。谢谢!

    3 回复  |  直到 9 年前
        1
  •  0
  •   Task    15 年前

    我想花点时间提出另一个解决方案…
    使用现有经过充分测试的实施方案: MapTool!

    当然,如果您特别需要或想要自己实现它(绝对是一个有趣的个人项目),这个解决方案是无用的,但是我认为应该提到它。8)

        2
  •  0
  •   sbenderli    15 年前

    为什么不将您希望仍然能够在碰撞检测代码中移动对象的情况包括进来呢?我在考虑碰撞检测代码中的简单if语句。我不能告诉你没有看到碰撞检测代码的MROE。

    另外,什么设置/更改“被阻止”?

        3
  •  0
  •   Staffan E    15 年前

    如果墙砖与相邻单元重叠,这会导致触发碰撞,则应使用较小的碰撞形状,而不重叠。

    理想情况下,碰撞形状应该正好是所占网格单元的大小,与视觉外观无关,对吗?

    推荐文章