XAML Collision detection

2019-07-18 16:00发布

I am working on a Windows Phone game and it is going swimmingly minus collision detection.

Is there a simple way that anyone could suggest detecting if two XAML objects are on top of each other?

The only method I know of is creating a list that contains the coords of every single collidable object in the game, then scanning the list to determine if there is a collision or not.

With all the cool XAML features like triggers, behaviors and such I thought there might be an easier way. However, search results are slim.

Any ideas? The simplest is what I am looking for. Nothing crazy needed. Just when my player collides with an object it disappears.

I don't know if it makes a difference but all my objects are images.

3条回答
2楼-- · 2019-07-18 16:44

So I installed Physics helper but the one that was offered above DOESN'T work with any windows phone build past mango. So I hunted down Physics Helper XAML which is not an install file and has to poor documentation to use it in the foreseeable future.

So I created my own XAML collision detection system. It is pretty simple, does what I need and is fast.

Most importantly though you can edit your canvas in Blend or in the WYSISYG editor and it not break the code.

First I create my nested canvas with the items I would like to be collidable

<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>

Then you can go to the code behind to do the rest ##NOTE THAT EVERY ITEM IS NAMED UNIQUELY##

Within the game loop I have the following methods declared to check for collision detection

 collisionChecks();
 handleCollisions();

So what is happening in the first method is this:

  1. All the elements from the collidable canvas are pulled into a list

  2. To save on checking items that aren't even on the screen I weed them out by saying if the Top of the element is on the screen add it to the collisionEnabled List otherwise forget it.

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

Now we can Handle the objects that are eligible for collisions

  1. First foreach loop checks to see if there is a collision between the player and each object that is in the collisionEnabled List.

  2. If there is a collision it gets added to the Collisions to handle list

  3. Once we have all the objects that are actually being collide with we can handle them individually based on their name to determine what to do with them. For example in this code I say if the name contains "star" then have it disappear and soon it will play a sound also. But I could also say if it contains "rocket" then change the player state to flying or what ever.

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

This isn't the cleanest way to implement a collision detection system but it is the smallest and fastest one I have ever come up with. Hope this helps anyone else interested in simple 2D Collision detection for XAML Objects

查看更多
Emotional °昔
3楼-- · 2019-07-18 16:45

There is no built in mechanism for collision detection with XAML objects. This makes sense, XAML is designed for creating application UIs - it is not a games engine!

You could try the Physics Helper framework:

http://physicshelper.codeplex.com/

This adds a physics engine that allows you to turn XAML objects into 'physics' objects via behaviours:

  <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>

I had a brief play with this framework a while back:

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

It was pretty good!

查看更多
Viruses.
4楼-- · 2019-07-18 16:49

Physics Helper XAML (http://physicshelperxaml.codeplex.com) says it's a rewrite of original Physics Helper (https://physicshelper.codeplex.com) that one could use for Silverlight (browser and WindowsPhone) via Blend Behaviors API.

The new one doesn't use Behaviors from what I understand since it was originally ported to early version of WinRT (http://www.spritehand.com/2011/09/physics-helper-xaml-for-metro-winrt.html?m=1) when there was no similar functionality yet available. Its author considers the new codebase simpler though (and that it could be back ported to Silverlight for browser and Windows Phone)

Another one is https://xamlphysics.codeplex.com which is also a wrapper around Farseer Physics engine and seems to use Attached Properties to attach physics properties to objects (which is a pattern I'd use too if I built such functionality)

Not sure if you can add such properties to Containers too, like set gravity in the parent to affect all its children

查看更多
登录 后发表回答