Separating Directx from your game application

Started by
8 comments, last by Grul 20 years, 10 months ago
I have been toying around with a little engine project for some time, and I''ve sort of run into problems. My idea was that I was going to write a game, with all API-specific components left out of the actual game code so that I could just as easily plug in OpenGL as Directx. To solve this I implemented a Directx wrapper in a separate DLL and made the wrapper class inherit from a certain "interface" which would the be the API''s face outward to the game application. This worked nice, but then I realized that I needed do the same thing with fonts, sprites, vectors and all other components. It was starting to look like the COM model where a central construct hands out interfaces but no actual data to use. Comments on this? Does anyone know a better way to solve this problem?
"Archangel, dark angellend me thy lightthrough death''s fail until we have heaven in sight"
Advertisement
I have tried this before as well..

DirectX is a little more "hands-on" when it comes to maintaining your rendering objects...

I found that I WAS able to abstract out the DX calls from my apps, but ended up with all kinds of function overhead, and worsely, hacks for some specific functionality which I did not plan for.

Ultimately, when I was working on a simple game, I ended up with this abstracted engine that turned into a hack monster. I ended up scrapping the project.

My problem was that I tried to completely isolate the DX, even though I should have probably taken a different approach. Granted though, this was in my DX learning days..

I have yet to make a game in DX, but we''ll see eventually.

www.cppnow.com
I must admit to attempting this in my current project.

To brief you on it: A block based board game, with an x by x grid of blocks. Certain combos of colour remove blocks. Anyway, the detail is irrelevant.

The process I am working at, is to implement as much of the actual game as possible using debugging and console apps. So for now I have my pieces (and groups - which are 3 pieces) as classes that can be (pseudo) randomly generated and passed into the game board class.

I will eventually have a renderer abstract class with methods such as the following:

UpdateScore(newscore) //updates score graphic. Could be a bar graph, could be numbers.
AddPiece(colour, shape, Coords) //Displays a piece at the coords that is colour and shape. Will prob maintain lists of each type to optimise rendering
DestroyPiece(Coords, methodOfDestruction) //Removes pieces from said lists and thus display
FadeOut() //For end of level

Etc.

Anyway, each time a group(three pieces) is placed, I check whether it is valid in my game classes. Then the renderer''s derived AddPiece is called for all three pieces, no error check req''d there as it is assumed done. I may at my discretion for those who are pedantic though .

As yet game logic is getting close to half complete, and as such I will be better able to define the renderer abstracts necessary capabilities. I believe that I will have to calol render() once per frame after processing game logic, and any state updates are done during (or as a result of ) the game logic.

I have no doubts there are flaws, but I hope I''ve given something to think about.

Keep us posted on your progress...
TheHermit
Actually, I don''t think it can work well unless you keep your code just barely floating above the actual video hardware. This means no D3DX functionality, for example; you would need to write all vector and matrix math code yourself. You would more or less have to write your own texture loading code as well. This is no doubt interesting, but I''d say that it would take forever for a single hobby programmer like me.

It would probably make more sense to toy around on the higher levels and just let D3D do the boring stuff for you More results with less code.

"Archangel, dark angel
lend me thy light
through death''''s fail until we have heaven in sight"
"Archangel, dark angellend me thy lightthrough death''s fail until we have heaven in sight"
I myself have always been trying to seperate the DX code from the game code.. I''ve attempted this on several projects. Some Defunct, some I''m still working on.

The conclusion that I have come to is that you really can''t wrap all the DX functionality behind an interface unless you really don''t need much functionality.

For instance. If you have a game that basically just draws images on the screen. Then you can hide the dx stuff in a wrapper. But if you want to blend a second texture with that image and change the blend states, you end up with function calls that are almost the same as the DX ones.

The conclusion I came to was that yes, you can wrap away alot of dx stuff, but you still need to have DX stuff in other places in the code. What I try to do is isolate those instances.

For example: I have a class CDIsplay. This handles init, texture loading and management, and provides a few other utils. It doesn''t do any actual renering (other than text). I have another class CWorldMap. This class has a member Render. Insode render I have DX code, but no where else in that class. The same goes for my CEntity class. It has a render func that does rendering.

So far this has worked fairly well for me.

-Zims
Yes, that seems to be more realistic. You probably want to separate your D3D code totally on a commercial project where you plan support for both D3D and OpenGL, but for a small project it''s ok.
"Archangel, dark angellend me thy lightthrough death''s fail until we have heaven in sight"
When I attempted this It worked with no problem -

A CWindow3D class was the main class - which my CWindowGL and CWindowD3D inherited from. This had several (abstract) Create* methods (CreateMesh, CreateFont, etc) which each took an abstract class (ie CMesh) to create. The inherited Window class created a new instance of the class based on whether it was D3D or OGL (ie new CMeshD3D or CMeshOGL). The host application just had to make sure it created objects this way and everything worked hunky dory.

My big problems were with Matrices.....

Neil

WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
as you say the OO approach to this is to use interface programming - ie abstract classes in C++. You do end up writing a lot of code. It''s a good exercise if you have the time (and skills).

I''ve gone along this route with the stuff I''m writing, but I''m taking it one step at a time - as there are bits to the APIs that I''ll never use - so I just add sections of functionality as I want it. Makes it less of an elephant task.

Have you looked at the OGRE engine? I''ve never used it but it claims to achieve this. (although I think only one gfx api is actually implemented).
actually at least three rendering apis are implemented in OGRE.

EDIT: the == three

[edited by - null_vector on June 4, 2003 12:21:53 PM]
find / -name "your base" -exec chown -R us:us {} ;
quote:Original post by stubble
as you say the OO approach to this is to use interface programming - ie abstract classes in C++. You do end up writing a lot of code. It''s a good exercise if you have the time (and skills).


Yes, this was exactly what I was using, just pure abstract interfaces. This was partly because I was writing the D3D code in a separate DLL. The common interfaces were inherited by the implemented Direct3D classes. This made what was D3D-specific and not very clear, but it feels kind of cumbersome. As you say, a lot of code to write.

And you basically have to write everything that D3DX does for you in a pure D3D app.
"Archangel, dark angellend me thy lightthrough death''s fail until we have heaven in sight"

This topic is closed to new replies.

Advertisement