quote: Original post by null_pointer
Anyway, I should think that it might be good to use the address instead of the ID, but you would have to dynamic_cast it each time (and in the debug version, you could check for NULL pointers). That might be comparable to the abstract base class method, but I''m not sure. To use this method, you only need the following class:
class Graphics {};
Right now, I have nothing of importance in my Graphic class, so it is like that. Later I might implement a GetName() function and other trivialities.
quote:
Why do you even need a hierarchy for the drawmanager and graphics classes? I just think that you are not thinking of the best solution here. IMO, you shouldn''t need either dynamic_cast-ing or IDs in a good system.
IDs are good as they can provide an extra level of abstraction. If you always use pointers then you make it difficult to move things around. Usually objects are stored within a collection within another object. For the ''outside world'' to hold a reference to an object, it would need a pointer or an ID. What if the container I was using happened to be a vector, and I deleted an object from the middle? Some of the pointers would be invalidated, even though the objects they refer to haven''t really changed. They just happened to be moved around through some implementation detail.
In fact, that sort of reason makes me think even more that I should be passing around some sort of GraphicID. Remove the casting and improve the encapsulation in one go.
As for no good system using dynamic_cast... well, I don''t really want to get into that Suffice it to say that (a) many well-respected authors and programmers have well-documented reasons for using it, (b) not all well-respected programmers are good programmers, and (c) I''ve never needed to use one before anyway.
The reason I ''need'' a hierarchy for the DrawManager stuff is because the rest of the game logic should be able to say:
"Please draw this Creature at X,Y on the screen"
And this should work regardless of the implementation of the graphical subsystem. Therefore, to enforce a common interface to such drawing functions, I made an abstract base class DrawManager, so that implementations of the different graphical APIs would inherit that common interface.
Ok, to sum up...
I am not sure that I need a hierarchy for Graphic*. But that was one thing I had considered, along with templates, and now IDs, to try and link a specific Graphic type to a specific DrawManager type. The ''Graphic'' class doesn''t do anything, it is just an object that holds a pretty picture with whatever API-specific information is needed to for that API to render it. I thought it might be possible to provide an abstract interface to Graphic so that a DrawManager could just take a Graphic and draw it using the interface. But since the interface, from the base class, can never return specifics such as LPDIRECTDRAWSURFACE, that approach doesn''t work -for my purposes-.
Either way, I don''t quite have the same goals as you here: I don''t have to have a perfectly elegant solution which is going to be evaluated and tested by millions (a bit of helpful optimism for you there ). Rather, I want to get it working and quickly so I can write my game! Elegance tweaks can happen later. I expect lots and lots of amateur projects by fairly experienced programmers fail because they spend too much time trying to make it perfect and not enough time trying to make it work.
quote:
(Personally, every time I call any class X manager I''ve got a bad design -- usually a vague task I don''t know enough about (which, for me, means everything). For me, it usually takes about 2-3 tries (meaning semi-working implementations) until I get the right design. Sometimes my friends give me ideas, etc.)
I wouldn''t agree with this: having some sort of Manager class shows that you are able to encapsulate an entire subsystem behind one simple interface, which is usually a sign of good modularity and has good potential for code re-use. It''s also an example of the Facade pattern. (Note that I am starting to religiously quote Design Patterns in my newly-acquired Saint-hood. Largely cos, although lots of people disagree with my ideas as -I- express them, no-one seems to disagree with that book )
quote:
So here''s (yet another) solution:
Create a blitter class and a surface class, which basically just move memory and provide some kind of access to it, whatever form in which it is stored. Create custom engines (2D, 3D, etc.) which build on those two generic classes. ("build" here does not mean a hierarchy -- just use the existing classes)
DirectDraw, for all of its quirks, provides a very good system for both 2D and 3D. 3D really just uses the 2D methods (and adds some custom exceptions of its own), and this is basically how all video cards work. That''s why I''ve chosen it for vos, ok?
I''m not sure you are appreciating what I am trying to do. I''m not trying to achieve 2D and 3D functionality through one simple interface. I''m trying to achieve the same 2D functionality through various APIs. If you just pretend that I want to replace Blt() with DrawPrimitive() but to show exactly the same thing on-screen, you''re on the right track. But this requires that surf
quote:
About vos. I said that the surfaces can be created in system memory. The only way they can be created in video memory is by the video* interface. Each person who writes an implementation for the video* interface writes the implementations for the video::surfaces, video::surface::clippers, etc. and they are all in hardware (where possible).
Someone using your system could decide to derive a single implementation from your interfaces, and make them platform dependent to take full advantage of hardware, etc. Because they will probably just derive 1 implementation, they can be cross-dependent. Whereas I need all these APIs to be able to coexist within the same program at the same time, so that you can choose your API from the start up menu or something. The only thing that needs to stay standard is that I need to be able to ask the DrawManager, whichever type it is, to do certain basic things, given the appropriate graphic.