3

我正在开发一款 Windows Phone 游戏,它在减去碰撞检测后运行流畅。

是否有任何人可以建议检测两个 XAML 对象是否相互重叠的简单方法?

我知道的唯一方法是创建一个列表,其中包含游戏中每个可碰撞对象的坐标,然后扫描列表以确定是否存在碰撞。

有了触发器、行为等所有很酷的 XAML 功能,我认为可能有更简单的方法。但是,搜索结果很少。

有任何想法吗?最简单的是我正在寻找的。没有什么疯狂的需要。就在我的播放器与物体碰撞时,它消失了。

我不知道这是否有所作为,但我所有的对象都是图像。

4

3 回答 3

3

没有用于与 XAML 对象进行冲突检测的内置机制。这是有道理的,XAML 是为创建应用程序 UI 而设计的——它不是游戏引擎!

你可以试试 Physics Helper 框架:

http://physicshelper.codeplex.com/

这添加了一个物理引擎,允许您通过行为将 XAML 对象转换为“物理”对象:

  <Ellipse Width="100" Height="100" Fill="Red"
            Canvas.Left="80" Canvas.Top="100">
    <!-- make the engine aware of this element -->
    <i:Interaction.Behaviors>
      <pb:PhysicsObjectBehavior />
    </i:Interaction.Behaviors>
  </Ellipse>

不久前,我对这个框架进行了一次简短的尝试:

http://www.scottlogic.co.uk/blog/colin/2011/12/a-festive-and-fun-windows-phone-7-maze-game/

这是相当不错的!

于 2013-02-24T08:11:02.753 回答
1

所以我安装了物理助手,但上面提供的那个不能与任何构建过去芒果的 Windows 手机一起使用。所以我找到了 Physics Helper XAML,它不是一个安装文件,并且在可预见的将来必须使用糟糕的文档才能使用它。

所以我创建了自己的 XAML 碰撞检测系统。它非常简单,可以满足我的需要并且速度很快。

最重要的是,尽管您可以在 Blend 或 WYSISYG 编辑器中编辑您的画布,但它不会破坏代码。

首先,我使用我希望可碰撞的项目创建嵌套画布

<Canvas x:Name="Collidables">
            <Image x:Name="star" Width="50" Height="50" Source="images/star.png" Canvas.Left="54" Canvas.Top="-132"/>
            <Image x:Name="star_Copy" Width="50" Height="50" Source="/images/star.png" Canvas.Left="158" Canvas.Top="-190"/>
            <Image x:Name="star_Copy1" Width="50" Height="50" Source="/images/star.png" Canvas.Left="268" Canvas.Top="-260"/>
            <Image x:Name="star_Copy2" Width="50" Height="50" Source="/images/star.png" Canvas.Left="372" Canvas.Top="-322"/>
            <Image x:Name="star_Copy3" Width="50" Height="50" Source="/images/star.png" Canvas.Left="54" Canvas.Top="-390"/>
            <Image x:Name="star_Copy4" Width="50" Height="50" Source="/images/star.png" Canvas.Left="158" Canvas.Top="-448"/>
            <Image x:Name="star_Copy5" Width="50" Height="50" Source="/images/star.png" Canvas.Left="268" Canvas.Top="-518"/>
            <Image x:Name="star_Copy6" Width="50" Height="50" Source="/images/star.png" Canvas.Left="372" Canvas.Top="-580"/>
            <Image x:Name="star_Copy7" Width="50" Height="50" Source="/images/star.png" Canvas.Left="372" Canvas.Top="-798"/>
            <Image x:Name="star_Copy8" Width="50" Height="50" Source="/images/star.png" Canvas.Left="268" Canvas.Top="-882"/>
            <Image x:Name="star_Copy9" Width="50" Height="50" Source="/images/star.png" Canvas.Left="158" Canvas.Top="-982"/>
            <Image x:Name="star_Copy10" Width="50" Height="50" Source="/images/star.png" Canvas.Left="54" Canvas.Top="-1060"/>
</canvas>

然后你可以去后面的代码做剩下的事情##注意每个项目都是唯一的##

在游戏循环中,我声明了以下方法来检查碰撞检测

 collisionChecks();
 handleCollisions();

所以第一种方法中发生的事情是这样的:

  1. 可碰撞画布中的所有元素都被拉到一个列表中

  2. 为了节省检查甚至不在屏幕上的项目,我通过说元素的顶部是否在屏幕上将其添加到碰撞启用列表中将其清除,否则忘记它。

    public void collisionChecks()
    {            
        List<UIElement> AllCollidables = Collidables.Children.ToList();
        collisionEnabled.Clear();
    
        foreach (UIElement item in AllCollidables)
        {
            if (Canvas.GetTop((Image)item) + canvasShift > 0)
                collisionEnabled.Add(item as Image);
        }
    }
    

现在我们可以处理符合碰撞条件的对象

  1. 第一个 foreach 循环检查玩家和碰撞启用列表中的每个对象之间是否存在碰撞。

  2. 如果发生碰撞,它会被添加到 Collisions to handle 列表中

  3. 一旦我们拥有所有实际发生碰撞的对象,我们就可以根据它们的名称单独处理它们以确定如何处理它们。例如,在这段代码中,我说如果名称包含“star”,那么让它消失,很快它也会播放声音。但我也可以说,如果它包含“火箭”,那么将玩家状态更改为飞行或其他。

    public void handleCollisions()
    {
    
        Rect player = new Rect();
        player.X = Canvas.GetLeft(Player);
        player.Y = Canvas.GetTop(Player);
        player.Height = Player.Height;
        player.Width = Player.Width;
    
    
        foreach (Image item in collisionEnabled)
        {
            if (item.Visibility == Visibility.Visible)
            {
                Rect obj = new Rect();
                obj.X = Canvas.GetLeft(item);
                obj.Y = Canvas.GetTop(item) + canvasShift;
                obj.Height = item.Height;
                obj.Width = item.Width;
    
                obj.Intersect(player);
    
                if (!obj.IsEmpty)
                {
                    collisionsToHandle.Add(item);
                }
            }
        }
        foreach (Image item in collisionsToHandle)
        {                
            item.Visibility = Visibility.Collapsed;
    
            if (item.Name.ToLower().Contains("star"))
            {
                score += 100;
            }
        }
        collisionsToHandle.Clear();
        collisionEnabled.Clear();}
    

这不是实现碰撞检测系统的最干净的方法,但它是我想出的最小和最快的方法。希望这可以帮助任何对 XAML 对象的简单 2D 碰撞检测感兴趣的人

于 2013-02-24T21:00:25.280 回答
0

Physics Helper XAML ( http://physicshelperxaml.codeplex.com ) 说这是对原始物理助手 ( https://physicshelper.codeplex.com ) 的重写,可以通过 Blend Behaviors API 用于 Silverlight(浏览器和 WindowsPhone)。

新的不使用我所理解的行为,因为它最初被移植到 WinRT 的早期版本(http://www.spritehand.com/2011/09/physics-helper-xaml-for-metro-winrt.html ?m=1 ) 当还没有类似的功能可用时。它的作者认为新的代码库更简单(并且可以将它移植到 Silverlight 以用于浏览器和 Windows Phone)

另一个是https://xamlphysics.codeplex.com,它也是 Farseer Physics 引擎的包装器,似乎使用 Attached Properties 将物理属性附加到对象(如果我构建这样的功能,我也会使用这种模式)

不确定您是否也可以将此类属性添加到容器中,例如在父级中设置重力以影响其所有子级

于 2015-05-11T08:25:41.777 回答