Sign in to follow this  
draconar

Design basics: Callbacks and Listeners classes

Recommended Posts

draconar    130
Hello all,

It is weird why it took me so long to post this topic. But the problem is: I'm writing the physics manager of my game engine and I still can't see to -really- grasp the concept of callbacks and listener classes.

To be specific, I'm using Box2D as the physics solver and the user should implement callbacks and listener classes in order to apply, well, user defined behavior after the physics is solved.

It seems like one of those well concealed secrets where everyone but you knows about it!

thanks!

Share this post


Link to post
Share on other sites
jyk    2094
What language are you using?

I think it's likely your best resource might be the testbed examples that come with Box2D. There are (or at least were) some examples that showed how to respond to various events (e.g. remove a body from the simulation when it collides with another body).

Box2D has its own callbacks that you can register, and then if you want you can add an additional layer of abstraction and pass that information to clients via your own callbacks. This is how I did it in my project that uses Box2D (C++). All the Box2D stuff is wrapped up in a module, and clients register callbacks with that module. The module itself registers callbacks with Box2D, then takes the data it receives in those callbacks, processes it, and passes it to the callbacks registered with the module. The end client receives information with no Box2D-specific information attached (in my case, smart pointers pointing to the entities with which the bodies are associated, and some simple collision info such as collision point and normal).

Share this post


Link to post
Share on other sites
draconar    130
Quote:
Original post by jyk
What language are you using?

I think it's likely your best resource might be the testbed examples that come with Box2D. There are (or at least were) some examples that showed how to respond to various events (e.g. remove a body from the simulation when it collides with another body).


I'm using C++ too.
Think you're right in there! I will need to study the testbed examples some more.


Quote:

Box2D has its own callbacks that you can register, and then if you want you can add an additional layer of abstraction and pass that information to clients via your own callbacks. This is how I did it in my project that uses Box2D (C++). All the Box2D stuff is wrapped up in a module, and clients register callbacks with that module. The module itself registers callbacks with Box2D, then takes the data it receives in those callbacks, processes it, and passes it to the callbacks registered with the module. The end client receives information with no Box2D-specific information attached (in my case, smart pointers pointing to the entities with which the bodies are associated, and some simple collision info such as collision point and normal).


The problem I'm confronting is: I don't know exactly what a callback does. Generally, I mean. Not just in Box2D.

To make a concrete representational of the problem, I will to explain what I'm doing and where I'm trying to go. Please see if it makes any sense:

In the physics manager of my engine, there will be a collection of b2Bodies. Each will be initialized with information from the scene Manager. In each time step, the box2D world will step through its world and update the bodies info, which will be sent to the entities/scene manager.


Then the question is: how do I check for collisions between the bodies? I know that box2d has its routines for collision checking, but I will need to update the sprites, score and many other game chores, not only update position + velocity. Do I need a listener to tell my game engine that a collision has occurred and that it is time to update sound/sprites/points/etc.

Last but not least: what is exactly a Listener class? how does it works?

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
The problem I'm confronting is: I don't know exactly what a callback does. Generally, I mean. Not just in Box2D.
The Wikipedia article would probably be a good place to start.

In this context though, a callback is basically a way for a module that provides a service to let a client know that something has happened. Box2D is the module that provides a service, the service being to simulate rigid body dynamics in 2-d. Occasionally, things may happen in the simulation that the client might be interested in, such as collisions between objects. Assuming the API supported it, you could ask Box2D every update whether any objects had collided (this might be called the 'polling method'), but that might not be very efficient, and it's not particularly convenient. Instead though, we can ask Box2D to let us know when such an event occurs.

The mechanism by which Box2D lets us know of such events is a callback. Box2D can't know in advance who to let know about these events, because every program is different. So, it provides a mechanism for you to let it know who to let know. In other words, 'Hey Box2D, would you let me know whenever a collision occurs? Here's my email address so you can send that info directly to me.' The 'email address' is your callback.
Quote:
Do I need a listener to tell my game engine that a collision has occurred and that it is time to update sound/sprites/points/etc.
Yes, you'll probably need a listener of some sort for that.
Quote:
Last but not least: what is exactly a Listener class? how does it works?
There are different ways to handle callbacks, and Box2D handles them via polymorphism. That is, you derive a class from a base class that Box2D recognizes, and then you can submit a pointer to an instance of your class to Box2D. It then stores it and calls the callback function as necessary.

Looking at the testbed examples should clear the rest up, I think, but post back if you have further questions.

Share this post


Link to post
Share on other sites
spek    1240
Let's say you call a helpdesk with question X. Normally you would get a direct answer, but the kind lady at the other side has to do some research. She asks your phone number so she can call-back as soon as she knows the answer. Better than hanging on the phone and waiting forever!

In programming terms, "function pointers" are a common way to this. You'll pass the address of a function to some service. As soon as this server has an answer or needs to ask more details, it will call that function.

// Delphi code, but the same thing can be done in most other languages
// Define how the callback function looks like. You can define any kind of
// function, as long as it matches with what the service expects
THelpDeskCallback = procedure( requesterName : string; answer : string );

// Make an instance of this callback function, the "listener"
procedure onHelpDeskReply( requesterName : string; anwer : string );
begin
< do something with the answer. Eventually use the requester
name (or pointer) to find out for the answer was >
end;

<call the helpdesk>
helpdesk.callForHelp( myName, question, @onHelpDeskReply ); // Pass address of the function above
// code continues... unlike normal functions, it doesn't have to hang here


<code at the helpdesk lady>
procedure helpdesk.callForHelp( caller, question : string; replyFunc : THelpDeskCallback ) ;
begin
< find the answer. Do it right now, or put in a background thread or
something so that the requester doesn't have to wait >
requestStruct.caller := caller;
requestStruct.replyFunc := replyFunc;
requestStruct.answer := getAnswer( question );
// When ready, reply
sendReply( requesterStruct );
end;

procedure helpdesk.sendReply( requesterStruct : TRequesterStruct );
begin
requesterStruct.replyFunc( "Dear sir "+requesterStruct.caller,
requesterStruct.answer );
// This will actually call "onHelpDeskReply" with the specific parameters
end;


Like jyk said, it's also possible with OOP to override a certain interface class to catch the callback function there. My advice, google "function pointers" for some practical examples in C++.

Rick

Share this post


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

Sign in to follow this