Results 1 to 16 of 16

Thread: Collision detection on circle outside of BoundingRect

  1. #1
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Collision detection on circle outside of BoundingRect

    I'm working on a "tower defense" style game for a class project and I can't seem to figure out how to detect collision within a radius around a tower. I cannot simply use the boundingrect function as the area to detect collision goes beyond the actual boundingrect of the object. I tried to re-implement the shape function to create a path, but that causes the program to crash when a tower is clicked.

    Can anyone give some insight on how I would create an "imaginary" circle around an object and check for collisions?

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Collision detection on circle outside of BoundingRect

    Add another item with a radius of your choice that is not visible and detect collisions for that item instead of your actual tower.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    I actually just finished doing getting something to work by creating a QPainterPath, drawing an ellipse around the tower and then calling the QGraphicsScene::items(QPainterPath) method. However, it is REALLY slowing down the program running time when several towers are placed.

    Do you predict that doing it in the manner you've suggested would be faster? I had actually looked into trying something along those lines, but I couldn't figure out how to give a new QGraphicsItem a radius. Would it be possible without creating a new sub-class of QGraphicsItem?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Collision detection on circle outside of BoundingRect

    Basically the fastest approach is to go through a list of items that can collide with your tower (which is easy to keep or calculate using a bounding rectangle of the circle) and then iterate through the list and check the euclidean distance between the tower and the item. It can even be distributed among many threads if available.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    Actually somehow I stumbled across the idea to limit all of my collision detecting to using the bounding rectangles and I created a new dummy class that I add to the scene and use it to detect the rectangular collisions for any given object. The problem that is now occurring is handling the collision detection for many objects becomes far too expensive a task to be handled in a single thread. This is my first experience trying to use QThread, or any type of threading for that matter, so I'm a little confused as to where and how I would send the collision detecting tasks to different threads.

    Currently I have all of my collision detecting taking place in the advance(step=0) function for any of the graphicsobjects. By doing so, when the advance(step=1) call is made, the graphicsobjects can simply perform the proper task based on their current situation. Thus there should be no issue with threading out the collision detection for each object into different threads, but I'm unclear where I should put the threading code.

    Should the threading be declared as its own class and then the object and scene that need to be processed for some kind of detection be passed into that class?

    Or should the thread be declared within each graphicsobject and called when that object attempts to detect any collision that is occurring.

    Also, would I still want to declare a main thread? It seems as though the answer would be no, as I would not want the main thread getting ahead of the collision processing and starting up the advance(step=1) processing while some of the collision detection processing is still occurring.

    Thanks!

  6. #6
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    So after posting my previous question, I went to my professor to see if he could also provide some insight into threading. Well after about thirty minutes of showing him that only threading would improve the performance further from where I was, he told me to lower the frame rate and not to attempt threading.

    Well, I'm not that kind of student. Shortly after I finally found an example of use that made sense and translated well into my usage, applied it to my code and everything seems to be working. Checking the processor usage on the Linux machines in our lab shows that all of the processors are taking on a shared load, where one was being over-ran before I inserted the threading.

    BUT, after a few objects get on the scene, suddenly my project closes and the Debug display reads "The program has finished unexpectedly"

    The only thing I can determine that would be causing the program to suddenly close without error, is I don't have a thread created to handle the "main" program, so the scene/view and everything suddenly are left without an active thread, which causes the entire program to finish.

    I've tried to find different manners to create a separate thread to handle the main execution of the program so it stays active continuously when the other threading occurs, but I can't seem to figure out how/where to put the view/scene into their own thread. Adding the view returns an error about trying to thread a QWidget, and the scene isn't adding properly into a thread and running within the view.

    If anyone could help me get through this last step, it would be pretty awesome to go back to my professor and say, "hey I know you said dont do this, but I did anyways, and it works, so give me an A"

    Thanks

  7. #7
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Collision detection on circle outside of BoundingRect

    I went to my professor to see if he could also provide some insight into threading. Well after about thirty minutes of showing him that only threading would improve the performance further from where I was, he told me to lower the frame rate and not to attempt threading.
    Your professor is a wise man. Threads add complexity.

    You cannot put a QGraphicsView into a thread because GUI objects must be in the GUI thread. Leave the GUI and scene in the main thread. As wysota said you can delegate the work of detailed collision checks (on candidates identified by quick checks) to threads by passing the centre and radius of each object to a processor in the other thread(s). You might like to look at QtConcurrent.

    The "The program has finished unexpectedly" message is usually the result of using a null, undefined, or no-longer-valid pointer. It could also be the result of multiple threads sharing a data structure with protection. Your debugger will tell you exactly which line the crash occurred on and allow you to inspect variables while step back through callers to identify the culprit.

  8. #8
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    Quote Originally Posted by ChrisW67 View Post
    Your professor is a wise man. Threads add complexity.

    You cannot put a QGraphicsView into a thread because GUI objects must be in the GUI thread. Leave the GUI and scene in the main thread. As wysota said you can delegate the work of detailed collision checks (on candidates identified by quick checks) to threads by passing the centre and radius of each object to a processor in the other thread(s). You might like to look at QtConcurrent.

    The "The program has finished unexpectedly" message is usually the result of using a null, undefined, or no-longer-valid pointer. It could also be the result of multiple threads sharing a data structure with protection. Your debugger will tell you exactly which line the crash occurred on and allow you to inspect variables while step back through callers to identify the culprit.
    While I completely understand the complexity of Threading (I actually did a 10 page paper on it for one of my prior classes), I dream one day of being a programming "god" like some of you, which means at some point I will need to understand and be able to implement such things. Since I've found a need to use it at this time, it became my current goal in life to generate a working threading code. I don't know why stupidity sometimes takes control and I don't run something in the debugger to check for more information.

    QObject::killTimers: timers cannot be stopped from another thread

    I Google'd this issue, and everyone else seems to be getting it from using a timer from within their Thread, which I am not, which means that somehow the destructor of the Thread must be deleting my main thread (I think)

    Qt Code:
    1. #ifndef WORKER_H
    2. #define WORKER_H
    3.  
    4. #include <QObject>
    5. #include "gamescene.h"
    6. #include "troop.h"
    7. #include "colldetect.h"
    8.  
    9. class Worker : public QObject {
    10. Q_OBJECT
    11.  
    12. public:
    13. Worker(GameScene* sc, QPoint p, int x, int y, int ut, int pnum);
    14. ~Worker();
    15.  
    16. public slots:
    17. void process();
    18.  
    19. signals:
    20. void finished(Troop* t);
    21. void completed();
    22.  
    23. private:
    24. GameScene* gs;
    25. CollDetect* cd;
    26. int UserT;
    27. int playernum;
    28. };
    29. #endif // WORKER_H
    30.  
    31.  
    32. //Worker.cpp file
    33. #include "worker.h"
    34. #include <QDebug>
    35.  
    36. Worker::Worker(GameScene* sc, QPoint p, int x, int y, int ut, int pnum)
    37. {
    38. gs = sc;
    39. cd = new CollDetect(p, x, y);
    40. UserT = ut;
    41. playernum = pnum;
    42. }
    43.  
    44. Worker::~Worker()
    45. {
    46.  
    47. }
    48.  
    49. void Worker::process()
    50. {
    51. gs->addItem(cd);
    52. QList<QGraphicsItem*> gi = cd->collidingItems(Qt::IntersectsItemBoundingRect);
    53. //qDebug() << "collisions: " << gi.size();
    54. for (int i = 0; i < gi.size(); i++)
    55. {
    56. if (gi.at(i)->type() == UserT)
    57. {
    58. if (dynamic_cast<Troop*>(gi.at(i))->playernum != playernum)
    59. {
    60. qDebug() << "troop found";
    61. emit finished(dynamic_cast<Troop*>(gi.at(i)));
    62. gs->removeItem(cd);
    63. emit completed();
    64. }
    65. }
    66. }
    67. emit finished(NULL);
    68. gs->removeItem(cd);
    69. emit completed();
    70.  
    71. }
    72.  
    73. //In the Troop class advance(step) function
    74. QImage img;
    75. img.load(image);
    76. QThread* thread = new QThread;
    77. Worker* worker = new Worker(myscene, QPoint(this->scenePos().x(),this->scenePos().y()), img.width(), img.height(), UserType+1, playernum);
    78. worker->moveToThread(thread);
    79. connect(thread, SIGNAL(started()), worker, SLOT(process()));
    80. connect(worker, SIGNAL(completed()), thread, SLOT(quit()));
    81. connect(worker, SIGNAL(completed()), worker, SLOT(deleteLater()));
    82. connect(worker, SIGNAL(finished(Troop*)), this, SLOT(settarget(Troop*)));
    83. connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    84. thread->start();
    To copy to clipboard, switch view to plain text mode 


    Added after 27 minutes:


    Okay, one of the big issues is coming from
    Qt Code:
    1. gs->addItem(cd);
    To copy to clipboard, switch view to plain text mode 

    further inspection of the cd element tells me where something is going way wrong here. The d_ptr element has a pointer to another complete graphics item, whose q_ptr has another d_ptr to another graphics item, whose q_ptr has another d_ptr to another graphics item, i think you get the point. But all the q_ptr, d_ptr, and v_ptr through the entire structure have the same values all the way down the chain. Obviously adding the collision detection item to the scene in the thread is a bad idea, it just seemed like the most straight forward approach at the time
    Last edited by squeegedog; 3rd April 2014 at 07:50.

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Collision detection on circle outside of BoundingRect

    I don't really see a need for threading here. How many objects do you have in your scene? 1k? 1M? Assuming 1k objects and an even distribution of objects in the scene checking collisions between objects in a circle covering 10% of the whole scene means checking collisions for 100 items. Even this can be easily avoided by keeping a list of objects that collide with the circle and updating that list when the object enters or leaves the circle.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    Yeh thats the crazy part, like 100 objects on the scene and it gets beyond slow, my professor thought I was doing something wrong or detecting collisions based on actual unit shape rather than rectangles. But the thing is, all 100 objects on the scene are doing a form of collision detection and it gets REALLY lagged, beyond LAGGED. And I'm not even doing circular collision detecting, its all rectangular at the moment. Calculating the circular collision from those that collide rectangularly is very simple and can be added at any point


    Added after 42 minutes:


    Just to clarify why so many things are detecting collision, I am make a tower-defense "style" game, its actually a combination of TD and RTS, where 2-4 players connect through a network into a single game, each player has a base to defend by creating towers, and troops to send, which attack other troops and path past towers. Thus the troops and the towers need to effectively do forms of collision detection all the time to see when opposing troops are in range. I could do A LOT of coding to limit the amount of collisions each troop and tower must go through, but time simply will not permit that at this point, and threading the current detection system would give enough performance increase to allow a "decent" finished product to be released by the final sprint turn in.
    Last edited by squeegedog; 3rd April 2014 at 10:46.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Collision detection on circle outside of BoundingRect

    Quote Originally Posted by squeegedog View Post
    Yeh thats the crazy part, like 100 objects on the scene and it gets beyond slow,
    You must be doing something wrong then. How are you detecting collisions between the tower range and those objects? It is enough to do the detection when the object enters the radius, there is no need to perform the detection when it is far outside the radius or when it is far inside the radius (unless the object can teleport itself far from its current location).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #12
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    Qt Code:
    1. CollDetect* cd = new CollDetect(QPoint(this->scenePos().x()-250,this->scenePos().y()-250), 500, 500);
    2. myscene->addItem(cd);
    3. QList<QGraphicsItem*> gi = cd->collidingItems(Qt::IntersectsItemBoundingRect);
    4. for (int i = 0; i < gi.size(); i++)
    To copy to clipboard, switch view to plain text mode 


    Added after 4 minutes:


    But honestly, the tower detection isn't where the lag is coming from right now, its the troop detecting other troops (doing in the same exact manner as above, except I'm only detecting for the actual bounding rect of the troop rather than an increased area around it). When I first inserted the tower collision using a QPath, it was very slow and I limited the collision detecting to once per second. I've never reverted that back as its fine. However, slowing down the rate at which the troops detect allows for clipping and sometimes complete missed detections
    Last edited by squeegedog; 3rd April 2014 at 10:58.

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Collision detection on circle outside of BoundingRect

    If you use collidingItems() then you detect collisions between each and every item in the scene. As I said before it is enough to do collision detection between items that are crossing the radius (if the "troop" is near the tower (colliding) in step A then there is no point in checking it in step A+1 since it couldn't have moved far enough to not collide with the tower).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #14
    Join Date
    Feb 2014
    Posts
    23
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Collision detection on circle outside of BoundingRect

    I understand that, and it probably wouldn't take a whole lot of work to limit the troops lists that are compared against towers with fixed positions and stop some of the detections that way.

    But, as previously stated, towers are NOT the problem. Its troops detecting other troops. Towers only check for collisions once per second on a 30fps game, so they aren't stalling up the processing by checking against each and every item. The troops, which all move around, are the ones who are causing the complete performance drop. They have to be checked every frame for collisions and creating limiting lists would take a much larger implementation, and still would only be a partial improvement.

    a.) limit lists of troops to those within certain locations of the game and only check against those
    b.) limit lists of troops to only those not on your own team

    Depending on the number of players would determine the improvement that can be seen, but your also now putting a lot of extra tracking work for each and every troop, also having to occur every step A and A+1.

    So, YES, I can make some small improvements through limitations etc, but in the end, detecting collisions amongst all my troops is still going to lag on a SINGLE processor.

  15. #15
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Collision detection on circle outside of BoundingRect

    but your also now putting a lot of extra tracking work for each and every troop
    So change your approach, use quadtree to partition your scene, it will limit the number of needed collision detection tests between troops. Here is a nice introduction with example implementation (java, but anyway) : Using quadtrees to detect collisions in 2D space

  16. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Collision detection on circle outside of BoundingRect

    Quote Originally Posted by squeegedog View Post
    I understand that, and it probably wouldn't take a whole lot of work to limit the troops lists that are compared against towers with fixed positions and stop some of the detections that way.

    But, as previously stated, towers are NOT the problem. Its troops detecting other troops. Towers only check for collisions once per second on a 30fps game, so they aren't stalling up the processing by checking against each and every item. The troops, which all move around, are the ones who are causing the complete performance drop. They have to be checked every frame for collisions and creating limiting lists would take a much larger implementation, and still would only be a partial improvement.

    a.) limit lists of troops to those within certain locations of the game and only check against those
    b.) limit lists of troops to only those not on your own team

    Depending on the number of players would determine the improvement that can be seen, but your also now putting a lot of extra tracking work for each and every troop, also having to occur every step A and A+1.

    So, YES, I can make some small improvements through limitations etc, but in the end, detecting collisions amongst all my troops is still going to lag on a SINGLE processor.
    What you say seems strange to me. Each troop would only do collision checking in this own neighbourhood which shouldn't be that complex. Have a look at the "colliding mice" example, increase the number of items and monitor the performance.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Replies: 3
    Last Post: 16th July 2012, 11:01
  2. QGraphicsPixmapItem collision detection
    By sophister in forum Qt Programming
    Replies: 7
    Last Post: 4th July 2010, 19:36
  3. collision detection...
    By Muffin in forum Newbie
    Replies: 1
    Last Post: 8th January 2010, 10:28
  4. turn off collision detection?
    By Deacon in forum Qt Programming
    Replies: 14
    Last Post: 30th December 2008, 17:37
  5. 2D Race Car collision detection
    By neonnds in forum Qt Programming
    Replies: 0
    Last Post: 6th July 2008, 08:10

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.