• Advertisement

Archived

This topic is now archived and is closed to further replies.

DirectDraw & C++

This topic is 6349 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Wondering if some of you nice folks might be able to help me. I''ve been reading "Tricks of the Windows Game Programming Gurus." and feel that I have all the direct draw concepts down, enough so that I''m ready to write my own sprite engine but I can''t decide whether to use C or C++. To me C++ seems the natural choice for doing things like bitmaps and sprites because I can see these as objects, but making a class for all the direct draw stuff is a little more abstract it seems. I''ve been trying to go by the recommendations of OOP methodology and make the classes self sustained and protecting their internals while providing an approved interface blah, blah, but I think I''m having a concept problem here. My bitmap and sprite classes have to ''dig'' into the direct draw class. The whole idea was to make the code more manageable, you know, abstract away the details so that when it got to the actual game programming part I wouldn''t have to deal with all the internals every time. Well, my attempts at making C++ wrapper classes for everything is even messier than straight C. I find myself having these strange thoughts like making a base class that contains the ddraw stuff and then using inheritence to derive bitmap and sprite classes from it so on and so forth. Ugh! brain hurt! Question: Since I''ve never actually written a whole game before, should I use Andre''s methods and finish a small game before trying to make my own ddraw wrapper library? The concept of "fill out structure - pass to function - use lots of globals" just gives me the screaming heebee-geebees for some reason. Ok, I admit that I may have an acceptance problem. I think it''s cool to have an object create itself and then draw itself on the screen with out any outside help, but I also realize that game programmers have been doing things similar to the way Andre does it for years. Last question, I promise Can anyone recommend some sample code to look at that shows a good way to make C++ wrappers for ddraw? Sorry so long winded. Thanks, Phillip

Share this post


Link to post
Share on other sites
Advertisement
I''ll answer your C/C++ debate. Just because the tools are there, doesn''t mean you have to use them. Coding any game using pure C++ ideology is suicide performance wise. Writing it all in C can cause you brain cramps.

I recommend you make use of classes when you think they are beneficial to you. If you don''t think it makes sense that something should be a class, make it procedural.

If you work out a nice blend between pure c and c++ you should have no problems writing a well designed and efficient game.

Share this post


Link to post
Share on other sites
I think you may be trying to stretch the class concept too far.
It can be very useful if it''s used right, but when you find
yourself doing something just to make it fit into a class, even
though it doesn''t logically fit with your program or programming
style, then it''s lost its usefullness.

It can be very useful for isolating different functionality and
providing a clean interface. e.g. - if you encapsulate all your
direct draw stuff in a class, decide what needs to be passed to
it and returned from it, then you don''t have to think about all
the internals of what''s happening there when you get ready to
render something - you just have to think about the interface.

Anyway, back to your actual question, if you haven''t done much
(or any) oo programming before, then it would probably be useful
to just go ahead and write a small program first. I think it
will be easier to go back in retrospect and see how you could
make some use of classes and object-oriented concepts, than it
would be to try to decide all of that before you write the
program. Trying to put this nicely -- if you''re finding that your BMP''s, etc. are having to ''dig down'' into your direct draw classes, you may not quite have mastered the concept yet.

information is the illusion of knowledge

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by justj

Anyway, back to your actual question, if you haven''t done much
(or any) oo programming before, then it would probably be useful
to just go ahead and write a small program first. I think it
will be easier to go back in retrospect and see how you could
make some use of classes and object-oriented concepts, than it
would be to try to decide all of that before you write the
program. Trying to put this nicely -- if you''re finding that your BMP''s, etc. are having to ''dig down'' into your direct draw classes, you may not quite have mastered the concept yet.


Yes, you''re probably right about that. I seem to be stuck in limbo between functional and object oriented programming at the moment. I think I understand the broad principle of OOP design, but I''m still having problems with implementation in C++. Thanks for the suggestions, I think I''ll just press on and try to concentrate on making a useful attempt at a game and worry about doint in the OOP way when I have more experience with it.

Phillip

Share this post


Link to post
Share on other sites
quote:

To me C++ seems the natural choice for doing things like bitmaps and sprites because I can see these as objects, but making a class for all the direct draw stuff is a little more abstract it seems.



Was that an attempt at a pun? A little more abstract than it seems. hehe

Anyway...I think you should C++. It is a superset of C and doesn''t lack anything that C has but has more than C. If you don''t want a class or it isn''t logical, you can just tuck your engine functions away in a file never to be seen again. But if you DO and you started the game with a C compiler, then it will be harder to port. Go with C++.

Lucas


PS If you do not conform to every single law of Object Orientation (section 1 through 6545433.4.543) then I will find your computer and burn it. Then i''ll ring ANSI and ISO and tell them. Then i''ll ring Bjarne Stroustrup up and boy will he be angry! So make sure you abide by every single rule of encapsulation. And remember, if its not a class and its not a preprocessor directive, then it is RUBBISH and Bjarne will smite your ass.

PPS that was a joke if you hadn''t guessed

PPPS except for that stuff about Bjarne smiting you for lack of OO

PPPPS That was a joke too.

PPPPPS hehehehe







Share this post


Link to post
Share on other sites
quote:
Original post by Ataru
Coding any game using pure C++ ideology is suicide performance wise.



Only if you suck at C++ - you haven''t read my article, have you?




Give me one more medicated peaceful moment.
~ (V)^|) |<é!t|-| ~
ERROR: Your beta-version of Life1.0 has expired. Please upgrade to the full version. All important social functions will be disabled from now on.

Share this post


Link to post
Share on other sites
Go with C-style functions and globals for starters and just try to isolate the complex directx stuff away from your main game. When that works perfectly then start thinking about putting it in a class. And make small games first or else you''ll never get anything done.

If you don''t need to put it in a class, don''t.

- Daniel
VG Games

Share this post


Link to post
Share on other sites
That was your article? I had a hunch that it was, what with the reference to that operator overloading thread. Maybe you should use your nick when you submit it?

It was a great article!


To the original poster:

I've never written a DirectDraw wrapper class, because DirectX is so class-like anyway... My advice is just to learn C++, and practice with it. It takes a lot of practice to get good at modeling things with OOP.

Anytime you write a wrapper class, don't just write lots of inline functions that simply call methods with the same name. I mean stuff like this:


class direct_draw
{
public:
create(...) { DirectDrawCreateEx(...); }
release() { lpdd->Release(); }
};



That's just duplicating all the function names - it really doesn't do anything to help the user of the class, because they'd still have to worry about all that stuff anyway.

The purpose of classes is to allow you to work with things at a higher level. For example, you want might want to call:


surface.blit(mysprite);



And let the surface worry whether the sprite is in the correct color depth and how to convert it, whether or not to stretch it, etc. Or you might want a method like this:


surface.alpha_blend(RGB(255, 0, 0), 0.10f); // make it a little red



Instead of having to worry about all the details and the surface format and things like that. That's really the same reason why we have functions and structs - so you can write the code once instead of having to duplicate the code every time you need it. If when writing a class you find yourself copying and pasting large blocks of code, the code probably belongs in a class somewhere as a member function, or perhaps as a new class. Only the very simplest code should be duplicated anywhere.

How complex the member functions are depends on what you need. If you don't need to do any fancy clipping, don't bother making functions to manipulate clipping regions. If don't need to write directly to a surface, don't bother putting in functions to do that. Your classes will change quite a bit between projects. One game may need to play MP3s, while another only needs to play some wav files in the background. The DirectSound class will be different in those two projects.

Don't start off by writing a do-everything library - just make it work, and try to keep the code clean. You may want it to be limited to one resolution (maybe 640x480x16?), and maybe once you learn enough you can make your DirectDraw class and your sprite class work together, so that your main game loop can handle any resolution and color depth without any changes to its code.

To write good classes, you _have_ to know how those classes need to be used, and how the programming task (in this case, drawing stuff on the screen) really works. If you only know a little about those things, then start off by making a very simple interface. Make a game (even if it's a Tetris clone) with it to measure your progress. As you learn more, you might want to add a feature or two to your classes. But keep testing your knowledge, and when you fail read everything you can get your hands on to find out why.

Once you get a pretty spiffy library going and some games under your belt, start reading some articles on performance, like MadKeithV's article. Eventually, when you start writing stuff that needs to be high-performance (like a 3D engine), you'll need the very fastest classes. LaMothe's books often provide a bit on optimization, which really makes you think. Most of optimization is just knowing how the computer works, and using common sense.



- null_pointer
Sabre Multimedia


Edited by - null_pointer on August 31, 2000 9:17:58 AM

Share this post


Link to post
Share on other sites
Since we''re talking about classes, I''ve got a class question I''ve always wondered about. If I have class A delcared as:

class A
{
private:
int myint;

public:
int GetMyInt();
int SetMyInt(int);
};


and I want to derive a class B from it, should I keep the myint variable as private, and use the Get/Set functions to access it, or should I declare it as protected: and access it directly, so I don''t have to make that extra function call?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by null_pointer


To the original poster:



null_pointer,
Thanks! You have given me some things to think about.

Phillip

Share this post


Link to post
Share on other sites
Houdini:

If your set/get functions are just setting and getting the variable''s value, why have them? If you aren''t doing any sort of validation like this:


void something::set_x(int x)
{
if( x < 5 && x > 10 ) // check it first
throw "x is not in the right range!";

else this->x = x; // set it
}



Then why bother with the functions? Either add the validation (if you need it), or just make the int protected instead of private.



- null_pointer
Sabre Multimedia

Share this post


Link to post
Share on other sites
DISCLAIMER! Let me flaunt my ignorance: I have never used DirectX (or any other graphics API other than windows GDI for that matter). It''s on my rather long list of "things to do", but there''s a bit of a resource allocation problem there, if you know what I mean.

My question: I thought DX uses COM, so you get interface classes. Wouldn''t it already be class-based then?

If not (i.e. if the COM interfaces don''t lend to objects well), I can''t believe there''s not a commercial C++ wrapper package out there. EVERYBODY uses DirectX (well, it seems lik eit anyway). Shouldn''t there be an OO package?

Share this post


Link to post
Share on other sites
Nope, COM doesn''t support classes (at least not that can be directly accessed from outside the DLL). They do this for portability (it can be used in C, C++, VB, VB Script, etc). COM interfaces can basically (and I mean very basically) be thought of as seperate DLLs or modules inside one DLL. One interface has NOTHING to do with the others, they don''t even know about each other.

Share this post


Link to post
Share on other sites
Stoffel: yea DX is class based... and yes its also COM... its an absolute mess... DX is designed to work for both games and application(like say Bryce or something)... wich means theres alot of crap in there that there doesn''t need to be... its a realy sloppy way of doing things if you ask me... so OO wrappers are written to help clean it up by us.... infact thats what I''m doing now =) rewrapping the whole DX API and packing alot of other stuff in there too =)

ROSS128:ummm go to my webpage... Got Milenko?
under my library section theres a few diffrent DX wrappers... both C and C++... ummmm heh like most of the site isn''t up yet but thats there =)....

Laterz

Great Milenko

Words Of Wisdom:
"Never Stick A Pretzel In Your Butt It Might Break Off In There."


http://www.crosswinds.net/~milenko
http://www.crosswinds.net/~pirotech

Share this post


Link to post
Share on other sites
Yeah, internally it''s probably all class-based (maybe even C++?), but (like everyone else said) to remain compatible with C and other languages they just make structs of function pointers (lpvtbl). I think they have an #ifdef __cplusplus in there to use classes if C++ is defined. Really, there are three major headaches with COM that could be handled quite easily with a wrapper library:

1. COM doesn''t use constructors/destructors per se, it has to be done manually.

2. You can''t create a COM object on the stack (which makes sense because of the linking).

3. COM objects use massive amounts of switch statements/return values instead of C++ exceptions. (ugh...)

So, I think a good start for a wrapper library would be:


class direct_draw
{
public:
direct_draw(/* parameters */) { DirectDrawCreateEx(/* parameters */); }
virtual ~direct_draw() { safe_release(lpdd); }

operator LPDIRECTDRAW7 () { return( lpdd ); }

private:
LPDIRECTDRAW7 lpdd;
};



Because you don''t have to rewrite all of the methods, and people can use the existing API docs (because every call is still made through the LPDIRECTDRAW7 object). It also solves problems #1 and #2 in that it handles destruction automatically. Of course, it doesn''t solve problem #3. The only unsafe call is using the conversion operator to call Release(), which there is never a need to do anyway - if you want control over which objects are released in what order, allocate the wrapper classes on the heap and call delete on them yourself.

(BTW, because you are using the same format for the member and operator for all of the DirectX objects, you might as well create a template class (com_wrapper) which you can just derive from with protected access. Saves typing, and the user knows that any class derived from that template will allow him to cast to his pointer type, etc.)

To write a really nice wrapper library, you''d have to check the return value after every call and decide whether or not to throw an exception (preferrably with your own com_exception class). Of course, this might set performance back a bit... However, writing a library is kind of tricky as people are very hard to please. I tried to write a Win32 API wrapper lib and didn''t like the result too well, so I scrapped it. It''s also very time-consuming!

Here are the problems I ran into:

1. My library didn''t do enough for programmers to justify its use!

2. It used tons of inline functions, friend classes, etc.

3. It took tons of time to write and maintain, and it was just different enough that I would have to write my own copy of the Win32 API documentation ().

The major problem was my lack of design. The library was good, didn''t leave any room for bugs (2- or 3-line functions!), and it was fast too, being mostly inline functions. The Win32 API is a real challenge for which to write wrapper classes. Here was my methodology for doing this:

1. Nearly every resource in Windows uses a handle, so for every handle type there should be a class. The handle is made private, with inline functions calling API functions with the handle. The user is not allowed access to the handle.

2. Instead of massive amounts of #defines and C-style struct definitions, I would use typedefs and enums, which meant renaming all flags (to get rid of WM_, WS_, etc.) to my own style.

3. I would derive my own classes and use overloaded arithmetic operators to them, from geometric classes included with the Win32 APIs.

4. Instead of return values, I''d make an exception class and throw exceptions.

etc.

As you can see, the project simply became too big for me to handle (well, not really... just that I have lots to do these days), and it was really irritating just making tons of inline functions with basically the same names...

On the upside, I learned a lot of the API... YMMV

(BTW, if anyone wants the source (to continue it or just use it for ideas), just email me and I''ll send it, but it''s not really too spectacular...)



- null_pointer
Sabre Multimedia

Share this post


Link to post
Share on other sites
First ... for what it does I like COM a lot. In fact I think it is about the only good general coding thing MS has ever created. There are some weaknesses, which all have to do with limitations so that COM could be language independent (although its ugly in certain languages), the PRIMARY one being it''s lack of C++/Java style exceptions.

The error reporting mechanism in DirectX is the ONLY reason anyone would want to write a general purpose wrapper (there are plenty of benifits of wrappers for using SUBsets and specific areas of DirectX in specific ways, but the only thing a general purpose C++ library could improve (IMHO) is the error handling / reporting system.

Using COM interfaces (which are usually implemeted in C++ as structs containing pure abstract functions, and inheirits from the IUnknown interface) is all COMPLETELY object oriented. The only aspect of COM which uses stand alone (non member) functions, are the component creation and interface access methods, and these areas are their own Meta programming system which owe many of their ideas to the GOF documented factory methods (if you do not own the book "Design Patterns" you are missing out on many tried and true OO methodologies).

I''d post a more on this topic ... but the ever popular Chinease cuisine has suddenly found itself on my desk, eagerly awaiting my consumption.

I would like to simply say that I do have classes written embodying 2D images (sprites or bitmaps) but they primarily serve the purpose of encapsulating reloading of lost surfaces, and allowing images to animate transparently to the client program. I also use other classes which provide memory management and back-to-front rendering benifits. But I do NOT have any class which acts as a wrapper for a DirectX interface, except where it hides all but 1 or 2 functions.

Share this post


Link to post
Share on other sites
Well, the COM doesn''t fit my my criteria for OO and encapsulation - it can''t handle it''s own cleanup, which makes it as bad as procedural code in my book. In order to use exceptions with any benefit, you have to wrap the allocation/cleanup of COM interfaces in a class. When I throw an exception in my code, I need to know that all of my resources will be cleaned up, and the program will exit normally.

Besides, the COM isn''t a replacement for C++ - it''s a specification, not a new language. You can''t make all the little classes like this in the COM:

class point;
class rectangle;
class polygon;
// etc.

Internally, yes. However you could not use your own classes like this as part of interface of the COM object because they would not be visible outside the COM object. You could probably use C-style structs, but that''s leagues behind what C++ classes can do, even for small types.

The COM doesn''t support operator overloading (even D3D has to use a header file with C++ code for that!), and it''s just too much overhead for little classes. Do I need three function calls to create and destroy a 4-byte point class? I''m not bashing the COM - like I said, it''s not a new language but a specification of how to use existing languages. It''s designed for larger, more complex interfaces.

So, what benefits does the COM provide for larger, more complex interfaces? Language independence, and also its different execution models (if that''s the right term - you know, in-process, etc.). I think that the latter could have been done in C++ with better results. Language independence with C++ code is tricky, though, so COM gets my respect for that.



- null_pointer
Sabre Multimedia

Share this post


Link to post
Share on other sites

  • Advertisement