Getting MFC and DX to play nice with eachother...

Started by
5 comments, last by Yanroy 23 years, 3 months ago
Here is another question that has been asked many times, but I think I have a new twist for you. I need a map editor for my new game (it doesn''t need to be good or fast, I''ll work on that once I see my map loading function works). Currently, I just have my game set every tile to equal grass, and I know that works (because the screen looks like grass...), but I want to see if I can actually load a file. So my question is: how do I make the main window in my MFC (single document appwizard generated one...) have DirectDraw draw on it so I can see the tiles as I place them? I think that if I could just get a pointer to the window and a way to ensure that DirectX doesn''t go crazy and draw on the whole screen, I would be more or less set. --------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming

You are unique. Just like everybody else.

Yanroy@usa.com

Visit the ROAD Programming Website for more programming help.

--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Advertisement
Hi Yanroy:

Just a quick suggestion here. Writing a MFC window that supports DirectX is doable, but the performance is usually poor and you are taking an extra step without benifit from it in your case, where you are simply writing a map editor. You don''t need DirectX (this doesn''t conflict with your game app which uses DirectX), because all you need is a file format that matches the reading method you use in game App, and a method to display the map in CView.

My recommandation is simply writing the map editor in MFC, and draw the bitmaps with CDC since there is no high graphics involved here. Then have all the tiles saved in a Container class. Using basi SDK functions to save the tile informations in text or Hex format. Also it maybe helpful if you include a header block that gives out certain map info. (the Read function will be reusable in gameApp.

In your Game App. you may use the same SDK code to read the map.

The format of your MFC app would be somehow like this:
CDocument: contains the Container class for the map tiles if your map file is not too big. (otherwise you may need to dynamiclly load portion of the map).

CView: this class contains a CPoint object that records the topleft tile that is visible in the view. Then an algorithm to determine which tiles are visible.
in OnDraw funciton, draw those tiles via CDC pointer
You will then need a set of Command message handler and Mouse message handlers to add/remove tiles from the map.

See if it helps. Thanks,
Turtlenet.
You make it sound easy If I do it that way, I am going into uncharted territory. I know nothing about the bitmap handling functions for MFC. The CView idea has always confused me, and I just let the framework handle it so I don''t get a headache. Could you perhaps explain with more detail what I need to do to my CView in order to make that work? Since I posted that message I have made a console app that generates random tiles and puts them in the file... I can''t actually make a playable map, but I know now that my loading function works.

--------------------


You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming


You are unique. Just like everybody else.

Yanroy@usa.com

Visit the ROAD Programming Website for more programming help.

--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Here we go, a short sample on how to handle bitmap with MFC

void CBitmapTestView::OnDraw(CDC* pDC)
{
CBitmapTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here

//Block One
int nTileWidth = 16;
int nTileHeight = 16;
int nDisplayWidth = 100;
int nDisplayHeight = 100;

CBitmap bm;
bm.LoadBitmap(IDB_BITMAP1);
//End Block One


CDC memdc;
memdc.CreateCompatibleDC(pDC);
memdc.SelectObject(&bm);

int nTargetX, nTargetY;
int nSrcX, nSrcY;
for (int i = 0; i < 100; i++)
{
nTargetX = (i % 10)*nDisplayWidth;
nTargetY = (i /10) * nDisplayHeight;
nSrcX = rand()%2 * nTileWidth;
nSrcY = rand()%2 * nTileHeight;
pDC->StretchBlt(nTargetX, nTargetY,nDisplayWidth,nDisplayHeight,&memdc,nSrcX, nSrcY,nTileWidth,nTileHeight,SRCCOPY);
}
}

This is just a demonstration on what can be done. IDB_BITMAP is a bitmap file for the tile map. The one I used has only 4 tiles. The for loop draws a map of 10x10 tiles (the tiles are random in this demo)

the code I used inside for loop:
nSrcX = rand()%2 * nTileWidth;
nSrcY = rand()%2 * nTileHeight;
should be replaced by your code to reflect the actual tile need to be drawn on tile (i%10, i/10) so that it won''t be random anymore.


The code I commented in Block one Should go to CView::OnIntialUpdate() to reduce drawing time, and the related variables should be class members.

nTileWidth and nTileHeight are the actual tile size in the bitmap, while nDisplayWidth and nDisplayHeight reflect the size will be displayed. This is why I use StretchBlt, so that you can show the tiles larger than actual size. Otherwise, you can simply use CDC::BitBlt.


To improve performance, you should also override the Erase Background message handler to do nothing.


See if this helps,
Turtlenet
MFC reduced the framerate of the project I am working on by 0.1fps. It is barely outside of experimental error.
The events that MFC handles are so infrequent it barely impacts the performance. M$ did take care not too slow down the pump.

You don''t need to use MFC to make a SDI or MDI program though... whatever you''re more comfortable with will work just fine. You might want to just make a dialog program (use a ''picture'', really a CStatic, control to set aside an area to render to). Search for "MFC Fog" on msdn to find an example of how to do this. Unless you want to learn how to use SDI or MDI, it''s big PITA to just get some tites in a window (compared to just using a dialog & a menu).


You use the MFC function CWnd::GetSafeHWND() to retrieve a hwnd for a window that can be used with Dx. When you initialize Dx you tell it to work in windowed mode, not full screen, and you create and attach (don''t forget to attach) a clipper object. I''m pretty sure the clipper factory was in the dx7surface interface, I''m not sure where it is in Dx8.
Once all of that''s done, when you lock the surface (which appears like a secondary surface if you''re used to full screen mode) you get access to the frame buffer and can render or bit twiddle with speed.
- 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
Turtlenet, that code looks like exactly what I need. Thanks. Now just one more question about it. Is that code supposed to be in my own derivative of the CView class? I would guess that is the case because it says void CBitmapTestView::OnDraw(CDC* pDC). If that is a real MFC type, then they need to find better names. If it is a class of my own, how do I tell the appwizard that I want to use that one (doesn''t it make you choose from a list? I''m not home now so I can''t check). My experience with MFC and non-DX windows apps in general is minimal (I am, however, a demigod of dialog apps ). Which leads me to my next comment: Magmai Kai Holmlor (could you have chosen a more difficult name to spell? ), Your idea sounds great as well, but I would actually prefer to use only MFC because I have had bad experiences in the past when I tried to mix APIs (like when windows API, winsock, DX, and WGPDUMB collide... maybe that was just a fluke, but I don''t want to sort out another mess like that). I don''t use WGPDUMB anymore anyway, because it seems to conflict with just about everything and it is sooo much slower than my engine...

--------------------


You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming


You are unique. Just like everybody else.

Yanroy@usa.com

Visit the ROAD Programming Website for more programming help.

--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Yanroy: the CBitmapTestView Class is my own derived class from CView. I made a project called BitmapTest so that MFC App Wizard named my view class "CBitmapTestView". You will get a CView derived class too, and it will supply an OnDraw function. Just add the function body there will do. (OnDraw is like a beaten up WM_PAINT message handler from SDK).

A dialog can be nice too, though a dialog does not have a frame to directly support Toolbars and Menubars (Well, it is still posible to add these items to a dialog, but it''s going to be painful). That''s why I would choose SDI/MDI.

Magmai is right that you don''t have to use MFC for SDI/MDI. straight WinSDK will do, and the memory usable is usually better with WinSDK. It requires more coding than MFC though Then if you also need a docking window with all the tile buttons, MFC is much easier to use without re-route all the window messages.

Turtlenet

This topic is closed to new replies.

Advertisement