Jump to content

VB.net Picture box intersection question....

So basically after days of researching i finally found a way to detect if my player(green square) is intersecting with another picturebox.

 

but my code makes it so that i have to write down which picturebox it is thats intersecting.

 

Private Function IntersectWith() As Boolean
        Dim recInter As Rectangle
        recInter.Location = MyPlayer.PointToScreen(New Point(0D, 0D))
        recInter.Size = New Size(MyPlayer.Width, MyPlayer.Height)

        Dim ChkPass As Rectangle
        ChkPass.Location = Floor2.PointToScreen(New Point(0D, 0D))
        ChkPass.Size = New Size(Floor2.Width, Floor2.Height)

        Dim doesIntersect As Boolean = recInter.IntersectsWith(ChkPass)

        Return doesIntersect

    End Function

example..

 

Picturebox1 is player..

Picturebox2 is Mayor.

Picturebox3 is Bandit.

 

can i ask is there a better way to find out which picturebox it is that my player is intersecting so that i can run it into a function?

 

or if you have a better way to implement intersection/collision could you please share it?

Link to comment
Share on other sites

Link to post
Share on other sites

Maybe looping through the controls and checking it that way:
https://stackoverflow.com/questions/14129652/dynamically-looping-through-picture-box-controls-in-visual-basic-2010-does-not-s

 

A better solution might be to make a list of all the pictureboxes and their locations and sizes (could use the loop to automate this part), then use LINQ to check wether or not there is a intersect.

https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/linq/introduction-to-linq

 

Even better would be if you could dynamically create all the objects and positions, using e.g. a textfile (or hardcoded into the software ofc) for the data (x, y, width, height), because then you could create a list containing all the objects, and you wouldn't have to loop through the controls in order to fetch and store them.

 

It all depends on your end goal with the program thought.

Link to comment
Share on other sites

Link to post
Share on other sites

There are many ways to optimize but you do use the correct method for the quickest collision detection.

 

The optimized version would be to not create each object every time, do sequential once detection. This mean that

you never need more than 2 rectangle at once so you need 2 rectangles declared outside the method so you can reuse.

Sizes need to be declared once (probably in the player,mayor.etx class).

 

For detection logic you should have the same class for the different sprite and their properties or whatever you display. 

 

Using the list you loop while the list has elements. My vb.NET is not very good but here some C# code of the loop logic but i will assume your object right now are NOT classes but just the picturebox controls you currently have. I added as much comment as i could to explain the logic as best as i could.

 

private class CollisionDetection
        {
            // mimic the fact you have picture boxes so my code compile and see the small mistakes
            PictureBox Picturebox1;
            PictureBox Picturebox2;
            PictureBox Picturebox3;

            // container for size property to mimic if i you had a class and reference system
            Dictionary<string, Size> Sizes = new Dictionary<string, Size>()
            {
                {"player",new Size(10,10) },
                {"mayor",new Size(10,10) },
                {"bandit",new Size(10,10) }
            };

            // those rectangle are reused, the instance is a struct so it's immutable, there is not need to reassign the memory each time.
            Rectangle rect1 = new Rectangle();
            Rectangle rect2 = new Rectangle();

            public List<Tuple<string, string>> GetCollision()
            {
                // for test purpose add a tag to the picture box so we can find them easily and use them generically
                // eventually with classes this completely disapear as you can have a reference to the visual object which make it easier
                Picturebox1.Tag = "player";
                Picturebox2.Tag = "mayor";
                Picturebox3.Tag = "bandit";

                // now create a list that will contain all collisions
                var collisions = new List<Tuple<string, string>>();

                // create the 2 rectangle we will

                // create a collection for all items to test 
                // (this should enventually be a list outside this method since the number of item can vary)
                var itemsToTest = new List<PictureBox>() { Picturebox1, Picturebox2, Picturebox3 };

                // now loop while there are items in the list
                while (itemsToTest.Any())
                {
                    // get and remove the first item. Why ? because it will test against the rest of the list
                    // so we do not want to test against itself and once the list is empty it mean each items
                    // have tested against one another
                    var item = itemsToTest[0];

                    // remove the item
                    itemsToTest.RemoveAt(0);

                    // set the first rectangle, get the size from the dictionnary
                    // but this can be changed to the referenced property once you use classes
                    // remember the tag i set just so it's easier to work around. Also note i do not do any validation
                    // in order to get from the dictionary as i know in this example it cannot fail but you should do validation
                    rect1.Size = Sizes[item.Tag.ToString()];
                    rect1.Location = item.Location;

                    // loop to test each collision
                    foreach (var secondaryItem in itemsToTest)
                    {
                        // set property for the second rectangle for the check
                        rect2.Size = Sizes[secondaryItem.Tag.ToString()];
                        rect2.Location = secondaryItem.Location;

                        // do the collision detection
                        if (rect1.IntersectsWith(rect2))
                        {
                            // if there is a collision store it using the strign value set
                            collisions.Add(new Tuple<string, string>(item.Tag.ToString(), secondaryItem.Tag.ToString()));
                        }
                    }
                }

                // all collisions have been reported with each other with the most optimization i think you should be able to handle at your level.
                return collisions;
            }
        }

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×