Fosterdn007
Fosterdn007

Reputation: 49

How to remove QGraphicsItem from QGraphicsScene when it goes out of scene window

I have a item named bullet and I want it to clear when it leaves the QGraphicsScene window.

My code is:

if(bullet->scene() != NULL)
    {
        if(bullet->x() >= 800 || bullet->y() >= 600)
        {
            scene->removeItem(bullet);
            scene->update();
            view->update();
            qDebug("Bullet went out of screen so it has been removed");
        }
    }

This works but the problem that i have is after this is done it will not let me create another bullet item.

Upvotes: 0

Views: 1674

Answers (1)

dtech
dtech

Reputation: 49289

I assume your bullet is animated (since bullets usually fly you know) so it must have an advance() method implemented.

You can put the bounds check there:

// in Bullet::advance() after you advance the bullet position
// if the scene rect doesn't contain the item rect remove from scene
if (!scene()->sceneRect()->contains(boundingRect())) scene()->removeItem(this);

Your current solution assumes a bullet will only increment its position in X and Y, and the scene will always be 800x600, which is bad design. You may enlarge the window, and that immediately breaks your logic. You may shoot right to left, meaning your bullet will never get removed from the scene if it leaves it from the left side. The solution above will work regardless of how big the scene is and what is the direction of the bullet.

the problem that i have is after this is done it will not let me create another bullet item

From the code you have posted it doesn't become clear what is the cause of your problem. You should be able to add as much items to a scene as you want, or your system can handle. It sounds though as if you are managing the bullet manually through a pointer to it, which may seem like a good idea if you have only one bullet on your scene, but in a practical scenario the scene will be fully dynamic, you might have hundreds of bullets, so you cannot track them this way.

Which is why you must make your items "intelligent" and implement their managing logic inside them, so you only keep track of the main items, such as your player item. Everything else should interact through the scene and interactions between the items. For example, when your player item shoots a bullet, you shouldn't be creating that manually, it should be implemented in your player item. So when you call player->shoot() it will scene()->addItem(new Bullet(bulletSpeed, bulletDirection) or something of that sort. In the same flow of logic, the bullet will automatically be removed if it goes out of the scene, or it hits an enemy, and also inflict damage to that enemy, which if lethal, will also remove the enemy from the scene.

Remember that when removing items from the scene, the items are not deleted, the ownership responsibility is transferred to you. If you want to delete it from memory, after you remove it from the scene you may call delete this; which should be OK if it is the last operation with that item and it will not be accessed anymore.

Upvotes: 1

Related Questions