Deleting NOVA objects using event handler

Aug 30, 2012 at 9:21 AM

Hi,

 

I am adding a number of objects (SphereObject) dynamically into the scene and then I am monitoring when these objects collide with anything. I want to remove any object from the scene as soon as it collides once. Until now, I did not figure out a way to do that through the event handler. Code:

if (currentMouseState.LeftButton == ButtonState.Pressed &&
                prevMouseState.LeftButton == ButtonState.Released &&
                currentState == States.AllowAddingCanonBalls)
            {
                SphereObject canonBall = ShootBox(Scene.Camera.Position, Scene.Camera.Target);
                canonBall.Physics.CollisionInformation.Events.InitialCollisionDetected += //Events_InitialCollisionDetectedObject;
                new InitialCollisionDetectedEventHandler<EntityCollidable>(Events_InitialCollisionDetected);
                numCanonBallsInScene += 1;
            }

 void Events_InitialCollisionDetected ( EntityCollidable sender ,Collidable other , CollidablePairHandler pair )
        {
            Vector3 position = new Vector3(10, 10, 10);0
            Text3D text = new Text3D ( position ,Text3D . Type .Fill , "Hit!",  Color .Red , "");
            text . LinearVelocity = Vector3 .Up;
            text . Lifetime = new TimeSpan (0, 0, 2);
            Scene .Add( text );
            numCanonBallsInScene -= 1;
            currentState = States.ObjectsCanCollide;
        }

 

thanks for your help

Coordinator
Sep 4, 2012 at 8:32 AM

Hi,

 

I assume, that you want to remove the canonBall object as soon as it collides with anything. This is only possible as long as the canonBall object is in your current scope, where you want to remove it. Since it's a local variable, it's not in the scope of your Events_InitialCollisionDetected event handler method. Changing it to a global member variable won't solve the problem, since it will be pointing to the newest canonBall. But fortunately the solution to this is very simple, since C# supports anonymous methods for event handlers, which let you define your event handler in the same scope of the object itself.

So you should change your code to something this:

if (currentMouseState.LeftButton == ButtonState.Pressed &&
                prevMouseState.LeftButton == ButtonState.Released &&
                currentState == States.AllowAddingCanonBalls)
            {
                SphereObject canonBall = ShootBox(Scene.Camera.Position, Scene.Camera.Target);
                canonBall.Physics.CollisionInformation.Events.InitialCollisionDetected +=delegate(EntityCollidable sender ,Collidable other , CollidablePairHandler pair)

             {

                   Vector3 position = new Vector3(10, 10, 10);0
                   Text3D text = new Text3D ( position ,Text3D . Type .Fill , "Hit!",  Color .Red , "");
                   text . LinearVelocity = Vector3 .Up;
                   text . Lifetime = new TimeSpan (0, 0, 2);
                   Scene .Add( text );

                   Scene.Remove(canonBall);

                   numCanonBallsInScene -= 1;
                   currentState = States.ObjectsCanCollide;};

                }


                numCanonBallsInScene += 1;
            }

 

Since the canonBall object is now in the same scope, you can remove it in the (anonymous) event handler.

 

I hope I could help you.

Sep 5, 2012 at 12:07 PM

Yes that does solve. Thanks :)

Indeed i did it in a slightly different way. I created a new class named AugmentSphereObject inherited from SphereObject. In this new class I defined a new member called bool remove_object. I then defined a new method called flag2remove inside this class. This method sets the boolean member to true when called, so:

public void flag2remove()

{

this.remove_object =true;

}

THen, I registered this method as call back when I added the sphereObject (now, the augmented sphereObject).

What I then do is to iterate through all AugmentedSphereObjects in the update() function and remove all those whose remove_object member has been set to true.

Cheers, TUMAAA

Coordinator
Sep 7, 2012 at 5:07 PM

Nice to hear, that it's working now. :)

 

Although I don' understand why you don't want to use the anonymous event handler method instead of your own implementation? Because in your implementation you have to take about every sphere instance. And you do that by assigning a flag and checking this flag for every object on every frame. And that's basically the thing that C# does for you by assigning the anonymous event handler, since every instance calls it in it's own scope.

 

Of course there are a lot of ways to code one and the same functionality in different ways and I certainly don't want to claim that my way is the best, but I would like to suggest, that there are some downsides in your way.

The first one is that the readability of your code gets decreased, since you've to trace what this flag is doing and where it's handled.

The second one (and severe one) is that your are decreasing your performance significantly. The most challenging thing in game design (or especially engineering) is not to make something work, but to make it work at at least 60 frames per second ;). So you have to thing about every line of code and if it's really necessary. That's why you should avoid as far as you can loops in your update (or draw) method which have to process every scene object. Because the performance deterioration is then proportional to the number of scene objects.

Generally speaking there are two approaches of checking an objects state: polling and event-triggered. While on polling you've to constantly check the object's state, in event-triggered you let the object itself telling you, when it changed it's state.

In Game Design the event-triggered approach is the best practice, since it's far less harming the performance due to the reasons as mentioned above.

 

So my advice to you is to use as much events as you can instead of polling-loops! If you have any questions about improving your performance, feel free to ask. :)

 

Cheers,

Izzo

Sep 19, 2012 at 8:29 AM

Hi Izoo,

Yes indeed, I guess your approach is better. I just meant that by the time you answered I had solved it the other way, but I will probably switch to your suggestion :)


Thanks again,

TUMAAA