Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Collision Detection Issues  (Read 1538 times)

0 Members and 1 Guest are viewing this topic.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Collision Detection Issues
« on: May 02, 2014, 11:02:29 pm »
Seems sometimes it'll detect the collisions and sometimes it won't for some odd reason.  I've been taring apart an XNA Quadtree example and converting it to SFML and so far it is working but the issue seems to be SFML related I think but not sure.

Yes I'm working in C# but this is more of a general issue from what I can tell. :)
class TreeAbleSFMLSprite : RectangleShape, IQuadStorable
    {
        private Vector2f vel;
        private Color collisioncolor, normalcolor;

        public TreeAbleSFMLSprite(Vector2f pos, Vector2f vecd, Color collide, Color normal)
            : base()
        {
            this.Position = pos;
            Velocity = vecd;
            collisioncolor = collide;
            normalcolor = normal;
            this.FillColor = normalcolor;
        }
        public TreeAbleSFMLSprite(Vector2f pos, Vector2f vecd, Color collide, Color normal, Vector2f size)
            : base(size)
        {
            this.Position = pos;
            Velocity = vecd;
            collisioncolor = collide;
            normalcolor = normal;
            this.FillColor = normalcolor;
        }
        public TreeAbleSFMLSprite(TreeAbleSFMLSprite copy)
            : base(copy)
        {
            Velocity = copy.Velocity;
            collisioncolor = copy.collisioncolor;
            normalcolor = copy.normalcolor;
        }

        public Vector2f Velocity { get { return vel; } set { vel = value; } }

        public void UpdateSprite()
        {
            Move(Velocity);
           
        }

        public Boolean HasCollided(TreeAbleSFMLSprite otherrect)
        {
            return this.GetGlobalBounds().Intersects(otherrect.GetGlobalBounds());/* ||
                (this.ThisContains(otherrect) || otherrect.ThisContains(this))*/

        }

        public Boolean ThisContains(TreeAbleSFMLSprite otherrect)
        {
            return this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left, otherrect.GetGlobalBounds().Top) ||
                this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left + otherrect.GetGlobalBounds().Width, otherrect.GetGlobalBounds().Top) ||
                this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left, otherrect.GetGlobalBounds().Top + otherrect.GetGlobalBounds().Height) ||
                this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left + otherrect.GetGlobalBounds().Width, otherrect.GetGlobalBounds().Top + otherrect.GetGlobalBounds().Height);
        }


        public void ColoredCollisions(TreeAbleSFMLSprite otherrect)
        {
            if (this.HasCollided(otherrect))
            {
                this.FillColor = collisioncolor;
            }
            else
            {
                this.FillColor = normalcolor;
            }
        }

        public void Move(Vector2f vec)
        {
            if (vec.X != 0 && vec.Y != 0)
            {
                this.Position += vec;
                HasMoved = true;
            }
            else
            {
                HasMoved = false;
            }
        }

        public FloatRect Rect
        {
            get
            {
                return this.GetGlobalBounds();
            }
        }

       

        public bool HasMoved
        {
            get;
            private set;
        }
    }
 

class SFMLXNAQuadRunner
    {
        private QuadTree<TreeAbleSFMLSprite> quadtree;
        private List<TreeAbleSFMLSprite> spritelist;
        private RenderWindow window;
        private VideoMode vid;
        private Random rand = new Random();
        private Text text, text2;
        System.Diagnostics.Stopwatch gametimer = new System.Diagnostics.Stopwatch();
        long timestarted = 0;
        float currentfps = 0, framecount = 0, wantedfps = 60;
        int maxdepth;
        public SFMLXNAQuadRunner()
        {
            vid = new VideoMode(600, 600);
            window = new RenderWindow(vid, "Quad Testing");
            quadtree = new QuadTree<TreeAbleSFMLSprite>(0, 0, (int)vid.Width, (int)vid.Height);
            spritelist = new List<TreeAbleSFMLSprite>();
            window.Closed += new EventHandler(OnClosed);
            text = new Text("Test", new Font("Fonts/00Starmap/00TT.TTF"),20);
            text2 = new Text("Test", new Font("Fonts/00Starmap/00TT.TTF"), 20);
            text2.Position = new Vector2f(text2.Position.X, text2.Position.Y + 20);
        }


        public void GenerateSprites(int amount)
        {

            for (int i = 0; i < amount; i++)
            {
                float x = rand.Next(-5, 5), y = rand.Next(-5, 5);
                if(x == 0.0 || (x < 1 && x > -1))
                {
                    x = 1;
                }
                if (y == 0.0 || (y < 1 && y > -1))
                {
                    y = -1;
                }
                TreeAbleSFMLSprite tasfmls = new TreeAbleSFMLSprite(new Vector2f(rand.Next(100, (int)vid.Width - 100), rand.Next(100, (int)vid.Height - 100)),
                    new Vector2f(x, y),
                    Color.Red, Color.Green,
                    new Vector2f(rand.Next(5,20), rand.Next(5,20)));
                //TreeAbleSFMLSprite tasfmls = new TreeAbleSFMLSprite(new Vector2f(vid.Width / 2, vid.Height / 2), new Vector2f(), Color.Red, Color.Green, new Vector2f(10, 10));
                spritelist.Add(tasfmls);
                quadtree.Add(tasfmls);
            }
       
        }


        public void UpdateLoop()
        {
           
            if (spritelist != null && spritelist.Count() > 0)
            {
                foreach (TreeAbleSFMLSprite item in spritelist)
                {
                    item.UpdateSprite();
                    if (item.GetGlobalBounds().Top < 0 || item.GetGlobalBounds().Top + item.GetGlobalBounds().Height > (int)vid.Height)
                    {
                        item.Velocity = new Vector2f(item.Velocity.X, item.Velocity.Y * -1);
                    }
                    if (item.GetGlobalBounds().Left < 0 || item.GetGlobalBounds().Left + item.GetGlobalBounds().Width > (int)vid.Width)
                    {
                        item.Velocity = new Vector2f(item.Velocity.X * -1, item.Velocity.Y);
                    }
                    quadtree.Move(item);
                }
            }
            text.DisplayedString = "Quad Count: " + quadtree.Count() + " Sprite Count: " + spritelist.Count();
            text2.DisplayedString = "FPS: " + currentfps + " Max Depth: " + maxdepth;
            //quadtree.
        }
        public void RenderLoop(ref RenderWindow win)
        {
           
            if (spritelist != null && spritelist.Count() > 0)
            {
                foreach (TreeAbleSFMLSprite item in spritelist)
                {
                    win.Draw(item);
                }
            }
            //RecursiveDrawQuad(ref window, quadtree, 0);
            win.Draw(text);
            win.Draw(text2);

        }
        public void MainThreadLoop()
        {
            GenerateSprites(rand.Next(1000,10000));
            window.SetFramerateLimit(60);
            gametimer.Start();
            while(window.IsOpen())
            {
                window.DispatchEvents();

                framecount++;
                if (gametimer.ElapsedMilliseconds > timestarted + 1000)
                {
                    timestarted = gametimer.ElapsedMilliseconds;
                    currentfps = framecount;
                    framecount = 0;
                }
                //Console.WriteLine(currentfps);
                UpdateLoop();
                RecursiveCollisionQuadCheck(quadtree, 0);
                //LoopTLoopCollision();
                window.Clear();
                //RecursiveCollisionQuadCheck(quadtree, 0);
               
                RenderLoop(ref window);
                //RecursiveCollisionQuadCheck(quadtree, 0);
                window.Display();
            }
        }

        void OnClosed(object sender, EventArgs e)
        {
            window.Close();
        }



        private void RecursiveDrawQuad(ref RenderWindow win, QuadTree<TreeAbleSFMLSprite> tree, int depth)
        {
            if(tree != null)
            {
                RecursiveDrawQuad(ref win, tree.RootQuad, depth);
            }
        }

        private void RecursiveDrawQuad(ref RenderWindow win, QuadTreeNode<TreeAbleSFMLSprite> node, int depth)
        {
           
            if(node != null)
            {
                RectangleShape rect = new RectangleShape(new Vector2f(node.QuadRect.Width,node.QuadRect.Height));
                rect.Position = new Vector2f(node.QuadRect.Left, node.QuadRect.Top);
                rect.FillColor = new Color(0,0,0,0);
                rect.OutlineColor = new Color(255,255,255);
                rect.OutlineThickness = 1;
                win.Draw(rect);

                RecursiveDrawQuad(ref win, node.TopLeftChild, depth+1);
                RecursiveDrawQuad(ref win, node.TopRightChild, depth+1);
                RecursiveDrawQuad(ref win, node.BottomLeftChild, depth+1);
                RecursiveDrawQuad(ref win, node.BottomRightChild, depth+1);
            }
        }

        private void LoopTLoopCollision()
        {
            foreach (var item in spritelist)
            {
                if (item != null)
                {
                    foreach (var item2 in spritelist)
                    {
                        if ((item2 != null) && (!item.Equals(item2)))
                        {
                            item.ColoredCollisions(item2);
                            item2.ColoredCollisions(item);
                        }
                    }
                }
            }
        }

        private void RecursiveCollisionQuadCheck(QuadTree<TreeAbleSFMLSprite> tree, int depth)
        {
            maxdepth = 0;
            if (tree != null)
            {
                RecursiveCollisionQuadCheck(tree.RootQuad, depth);
            }
        }
        private void RecursiveCollisionQuadCheck(QuadTreeNode<TreeAbleSFMLSprite> node, int depth)
        {
            if (node != null)
            {

                if (node.TopLeftChild == null && node.TopRightChild == null && node.BottomLeftChild == null && node.BottomRightChild == null)
                {
                    if (node.Objects != null)
                    {
                        foreach (var item in node.Objects)
                        {
                            if (item != null && item.Data != null)
                            {
                                foreach (var item2 in node.Objects)
                                {
                                    if ((item2 != null && item.Data != null) && (!item.Equals(item2) && !item.Data.Equals(item2.Data)))
                                    {
                                        item.Data.ColoredCollisions(item2.Data);
                                        item2.Data.ColoredCollisions(item.Data);

                                    }
                                }
                            }
                        }
                    }
                    //node.Objects
                }

                maxdepth = Math.Max(maxdepth, depth);
                RecursiveCollisionQuadCheck(node.TopLeftChild, depth + 1);
                RecursiveCollisionQuadCheck(node.TopRightChild, depth + 1);
                RecursiveCollisionQuadCheck(node.BottomLeftChild, depth + 1);
                RecursiveCollisionQuadCheck(node.BottomRightChild, depth + 1);
            }

        }
    }
 

the two files above are mine.

Here's the quadtree I've been ripping apart. :P
Had to post it in an attachment because it was too big. >.>
« Last Edit: May 02, 2014, 11:04:42 pm by StormWingDelta »
I have many ideas but need the help of others to find way to make use of them.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Collision Detection Issues
« Reply #1 on: May 02, 2014, 11:11:50 pm »
"It doesn't work" + big code is the worst thing you can do on a forum to get help ;)

Show us that you tried hard to solve the problem on your own before posting: provide a minimal (and complete) code that reproduces the problem, tell us precisely what's wrong and where you think the problem is, etc.

And how could a collision detection issue be related to SFML, given that SFML has nothing to do with collision detection? ???
Laurent Gomila - SFML developer

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Collision Detection Issues
« Reply #2 on: May 03, 2014, 02:47:19 am »
It isn't that it doesn't work but it isn't working fully.  For example if I got enough sprites on the screen it can miss collisions for some odd reason.  So far I know it is in the collision code itself.

Here.
public Boolean HasCollided(TreeAbleSFMLSprite otherrect)
        {
            return this.GetGlobalBounds().Intersects(otherrect.GetGlobalBounds());/* ||
                (this.ThisContains(otherrect) || otherrect.ThisContains(this))*/

        }

        public Boolean ThisContains(TreeAbleSFMLSprite otherrect)
        {
            return this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left, otherrect.GetGlobalBounds().Top) ||
                this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left + otherrect.GetGlobalBounds().Width, otherrect.GetGlobalBounds().Top) ||
                this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left, otherrect.GetGlobalBounds().Top + otherrect.GetGlobalBounds().Height) ||
                this.GetGlobalBounds().Contains(otherrect.GetGlobalBounds().Left + otherrect.GetGlobalBounds().Width, otherrect.GetGlobalBounds().Top + otherrect.GetGlobalBounds().Height);
        }
 

and here
private void RecursiveCollisionQuadCheck(QuadTree<TreeAbleSFMLSprite> tree, int depth)
        {
            maxdepth = 0;
            if (tree != null)
            {
                RecursiveCollisionQuadCheck(tree.RootQuad, depth);
            }
        }
        private void RecursiveCollisionQuadCheck(QuadTreeNode<TreeAbleSFMLSprite> node, int depth)
        {
            if (node != null)
            {

                if (node.TopLeftChild == null && node.TopRightChild == null && node.BottomLeftChild == null && node.BottomRightChild == null)
                {
                    if (node.Objects != null)
                    {
                        foreach (var item in node.Objects)
                        {
                            if (item != null && item.Data != null)
                            {
                                foreach (var item2 in node.Objects)
                                {
                                    if ((item2 != null && item.Data != null) && (!item.Equals(item2) && !item.Data.Equals(item2.Data)))
                                    {
                                        item.Data.ColoredCollisions(item2.Data);
                                        item2.Data.ColoredCollisions(item.Data);

                                    }
                                }
                            }
                        }
                    }
                    //node.Objects
                }

                maxdepth = Math.Max(maxdepth, depth);
                RecursiveCollisionQuadCheck(node.TopLeftChild, depth + 1);
                RecursiveCollisionQuadCheck(node.TopRightChild, depth + 1);
                RecursiveCollisionQuadCheck(node.BottomLeftChild, depth + 1);
                RecursiveCollisionQuadCheck(node.BottomRightChild, depth + 1);
            }

        }
 

If enough sprites get on the screen it starts missing checks or if it gets them.
Here's what it looks like.  Most of the green visible should be red but isn't.

I'm starting to think it has more to do with the quadtree not reallocating the sections but not sure but here's what it looks like if I use the two for loop checking.
private void LoopTLoopCollision()
        {
            foreach (var item in spritelist)
            {
                if (item != null)
                {
                    foreach (var item2 in spritelist)
                    {
                        if ((item2 != null) && (!item.Equals(item2)))
                        {
                            item.ColoredCollisions(item2);
                            item2.ColoredCollisions(item);
                        }
                    }
                }
            }
        }
 

There are several places it should be checking and showing red but isn't for some reason.
I have many ideas but need the help of others to find way to make use of them.

 

anything