Capability Queries

Started by
3 comments, last by Clash 20 years, 1 month ago
I''m currently toying with some ideas for my next game engine. One in particular is using Capability Queries. Here is the sceneario: If each subsystem (rendering, networking, physics, serializer, etc.) defines an interface which has the methods needed for the subsystem to act upon an object, and each of those objects is derived from a base interface, then some sort of Capability Query system could be setup. The idea is similar to what COM does, except more lightweight and much less general. A single list of active objects could be maintained by the engine. Whenever a subsystem needs to act upon objects, it can go through that list and query each object for an interface. If it implements the interface, it would perform operations on it and move to the next one. The game code could also define interfaces for the various things in the game world and use the Capibility Queries to determine how to act. So, my question is this: is this overkill or elegance? An alternate solution to the Capability Queries that may not be obvious is Autolists. Each of those interfaces could be attached to an Autolist. The subsystems could then barrel through the correct autolist and accomplish the same thing. Using the CQs, a virtual function must be invoked on each object in the engine for each subsystem in the engine *in addition* to whatever the subsystem does. Granted, the autolists would have more memory overhead due to having the same object in a bunch of lists. Another alternate solution, which may be more obvious, is to use a custom, lightweight RTTI system to replace the CQs. Each object would contain a static instance of an RTTI object and a pointer to the RTTI object of its parent. You could ask an object if it is derived from a class or interface and then manually typecast it. So which of these three techniques would work best? Thoughts, comments, and opinions wanted. Thanks, - Jason Citron - Team nine:14, System Architect - www.fatesforgiven.com ------------------------- Check out screenshots of the Fates Forgiven Alpha at www.fatesforgiven.com/screenshots
- Jason Citron- Programmer, Stormfront Studios- www.stormfront.com
Advertisement
If you try the query method, let us know how it works out. That''s what I kinda wanted to do, but the redudant querying rubbed me the wrong way. I have each sub-system maintain it''s own deque of ''active'' objects, and the objects implement the interfaces each sub-system requires to talk to them (like the auto-list approach).

With the autolist, the majority of the overhead is taken care of when the object is ''plugged in'', whereas the other approaches have overhead whenever an object is accessed.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
I''ve implemnted a similair system for my current project. It greatly reduces the static code overhead of managing interfaces, in exhange for the cost of runtime binding.

Don''t fret too much about performance, interfaces are usually bound once during an objects lifetime. Im my case to a templated interface binding object. I use built in RTTI, however you could use a light weight custom RTTI, but I timmed it, I can bind over a million interfaces a sec with my simple built in RTTI implementation.

Though the use of a homogenous base class is useful, I''m not sure why you would want to group disparate objects such as those in the rendering, physics, network, and seralize into a unified set. It doesnt gain you much to have them in one place. There will still be a unique architure for handing each subsection. Though a single object can be shared between those components if it implemtnes the correct interfaces. However i would avoid implmenting such a tightly coupled architecture.

I seperate out the various object sets into their own model/view/controller. I''m trying to reduce all of my game engine components down into template constructs so in the future I can build an entire game by doing :

Game my_game;

my_game.run();



Good Luck

-ddn
Interesting comments. My intention for the common base class was three fold:
1. Provide a means for aggregating all objects in the engine in one place so operations could be performed across all objects.
2. Provide a base object which the Caps Queries can be invoked against.
3. Enable reference counting for all objects.

Now my comments about each of those points:
1. ddn3, you made a good point, however. In all cases each subsystem will only be operating on objects of the type it uses. Granted, serialization may occur on all objects, but that appears to be an exception. So perhaps reason #1 is no longer substantial.

2. The caps queries are sounding less attractive. Auto-lists seem to be a better choice because they do reduce dependency on a global engine-provided list of objects.

3. The reference counting is something that I absolutely want to implement.

So, with all that in mind, I think that it may come down to having all objects derive from some base class which only implements a reference counting scheme, and then using autolists for aggregating objects of the various subsystems.

I havn''t put much thought into using CapsQueries for the game-code types, but I''m curious if anyone has used them in that capacity. For example, whether an AI object can interact with another object or whether an object can be damaged. That sort of thing.

Also, ddn3, could you elaborate on what you mean by a "binding object?"

Thanks as always,

- Jason Citron
- Team nine:14, System Architect
- www.fatesforgiven.com

-------------------------
Check out screenshots of the Fates Forgiven Alpha at www.fatesforgiven.com/screenshots
- Jason Citron- Programmer, Stormfront Studios- www.stormfront.com
Yo-k! (thats Yeah, Ok!

I have components which query a generic base object ( in my case its called an Entity ) for an interface which it needs. When it does this it binds ( querires & retrives a desired interface ) it to a permanent interface holder(templated interface helper class), for the lifetime of the component ( which usually also corresponds to the lifetime of the Entity for most cases ). This binding just iteratres through the set of generic interfaces which the Entity posses and finds the matching type and return the first instance of it, using RTTI.

So this allows me to create Entites composes of componetnts which bind to eachother when the entity is created to perform their functions. I use this principle to bind in various properites such as movement, collision, AI, light properites, sound properties, etc..

So if i didn''t have this generic binding code, I would have had to write a unique interface for each property and inherit it, or expose a set of accessor functions to ptrs objects within the entity, but if i want to add a totally new interface object, the entity class would change, thus the code overhead for managing interfaces.

This pattern has reduced my code by proably 10%. I think its a proper design pattern, perhaps the Composite pattern.

The way I''ve structured my Entites :

Model : World (contains all playable Entites)
View : Scene (contains the viewable set of Entites)
Sound : Sound_Manager ( contains the soundable set of Entites)
Comm : Server ( contains all network proxy Entites)

So the world contains the complete set of Entites, and all the others are subsets ( depending upon their properites ).

Look into boost smart pointer implementation, it will solve your refrence counting problems.

Good Luck!

-ddn

This topic is closed to new replies.

Advertisement