Archived

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

The Windowed Clipper

This topic is 5889 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

I need a bit of clarification on the clipper in windowed mode, as well as translating between world, screen, and view area. This is all DirectDraw7 (no D3D). I have a window, it is 320x240. The world has been made 11x7 tiles, but only the center 9x5 are to be visible. There is a one-tile border for the smooth clipping of sprites into the view area. Each tile is 32x32. So: View area: 288x160 World area: 352x224 The view anchor (offset for windowed view) of the upper left corner is 12x12 (also bizarre, since fullscreen is 16x40). This leaves a black border of 32 (12 left/right) x 80 (40 top/bottom). I don't ever want to draw anything in this area. Sprites may enter and leave any of the four edges, but they are to begin clipping at the start of the black border, and never entirely be removed all at once...hence, the use of a clipper in the first place. What I am finding that is odd is: 1) the clipper's region must be set to very odd values. For my exe, the winning coordinates end up being: anchorx+3,anchory+51,windowwidth-17,windowheight-17 (15,63,303,223) I cannot, for the life of me, figure out what combination of GetClientRect, GetWindowRect, the view area, the screen area, or any other value that comes to the above four values to create that clipper. 2) A 16x20 sprite clips out fine. A 32x32 sprite begins to clip, and at about the halfway mark, jumps out entirely. Any attempt at increasing the clipper by any dimension causes overdraw into the black border; copies of the bitmap that are never erased into black again (I have seen this similar effect in a few emulators out there that have game areas smaller than the window). It doesn't make sense, because again, we are dealing with a world of 11x7, of which each tile is 32 wide. So if a 32 wide sprite is clipping out the left side of the screen, at the half way point, only 16 pixels are out of the view area...there is still another 16 in the world view to accompany the rest of the sprite. Any tips or ideas on what I need to be looking for, checking on, etc, would be appreciated. I can include code here where requested. Also, feel free to point out that I have completely goofed and am a moron. I may speak like I understand this stuff, but in actuality, I'm quite the idiot. - Hanzo Edited by - Hanzo on October 23, 2001 1:55:35 AM

Share this post


Link to post
Share on other sites
Clippers are relative only to the surface they''re attached to.
It''s the Blt (or Flip) that draws the surface in the right place on the desktop.

So for the clipper, something like:

LPRGNDATA regionData; // Needs to be malloced and memset(0)
regionData->rdh.dwSize = sizeof(RGNDATAHEADER);
regionData->rdh.iType = RDH_RECTANGLES;
regionData->rdh.nCount = 1;
regionData->rdh.nRgnSize = sizeof(RECT);
regionData->rdh.rcBound.left = 0;
regionData->rdh.rcBound.top = 0;
regionData->rdh.rcBound.right = surfaceWidth;
regionData->rdh.rcBound.bottom= surfaceHeight;

lpDD->CreateClipper(0,&lpDDClipper,NULL);
lpDDClipper->SetClipList(regionData,0);
lpDDSBack->SetClipper(lpDDClipper);


Should work.

Then to draw to the window


HRESULT hRes;
RECT srcRect,destRect;
POINT pt = {0,0};

ClientToScreen(ghDDWnd,&pt);
GetClientRect(ghDDWnd,&destRect);
OffsetRect(&destRect,pt.x,pt.y);
SetRect(&srcRect,0,0,surfaceWidth,surfaceHeight);

lpDDSFront->Blt(&destRect,lpDDSBack,&srcRect,DDBLT_WAIT,NULL);

Share this post


Link to post
Share on other sites
I have noticed (after the fact) that in order to properly clip a view area that is less than the window area while in windowed mode, you need multiple clippers. Or at least, I have seen the best success with this.

There are a **lot** of forum posts on windowed clippers, but so far, all of them seem to come from the direction of one big clipper that handles a view area equal to the entire view area of your DDraw window. Unfortunately, this does not apply in my case. My big confusion is to which surface must the clipper be attached? Primary? Back(Secondary)? Turns out you may need both.

I notice that, if you are building DDraw for windowed mode, you will always need one clipper to handle the actual window, since the surface will take up the entire desktop. Almost every single forum post covering this topic has suggested this:


//lpdd is the LPDIRECTDRAW7
//lpddclip is a LPDIRECTDRAWCLIPPER
//lpddMain is the primary surface
lpdd->CreateClipper(0,&lpddclip,NULL);
lpddclip->SetHWnd(0,hWndMain);
lpddsMain->SetClipper(lpddclip);


This absolutely seems to be the way to go. Having this clipper allows the window to be partially moved offscreen and still animate (blit). However, if the view area is less than the window itself (as is in my case) you will notice "overdraw" when sprites enter or leave the edge. They''re clipped off the edges of the window fine, but when they leave the view area, and into the border where you wish *nothing* to be drawn...they just leave a sprite-residue that is never cleared away. This is where the second view-area clipper must be placed:

Currently, my view-area clipper looks like this:


//viewanchor (start of view area) is 12,12, windowwidth is 320,
// windowheight is 240
HRGN hrgn=CreateRectRgn(VIEWANCHORX,
VIEWANCHORY,
WINDOWWIDTH-VIEWANCHORX-8,
WINDOWHEIGHT-VIEWANCHORY-56);
lpdd->CreateClipper(0,&lpddclip,NULL);
DWORD dwBufSize=GetRegionData(hrgn,0,NULL);
LPRGNDATA lprd=(LPRGNDATA)malloc(dwBufSize);
GetRegionData(hrgn,dwBufSize,lprd);
lpddclip->SetClipList(lprd,0);
free(lprd);
DeleteObject(hrgn);
lpddsBack->SetClipper(lpddclip);


With this added clipper, sure enough, all the "residue" left by sprites being clipped away from the view area is gone. Note that if only this clipper is set and not the previous one, all blitting stops if the window moves partially off the desktop. Therefore, it would seem both clippers are needed.

The -8 and -56 adjustments boggle my mind.

Now, my final problem is to determine why it is sprites leaving the right or bottom side of the view area are fine, but sprites leaving the left or top part of the view area "jump" out before they can be clipped properly. More suggestions welcome.

- Hanzo

Share this post


Link to post
Share on other sites
Well, managed to solve one thing, kind of a "smack yourself it''s dumb" error.

HRGN hrgn=CreateRectRgn(VIEWANCHORX,VIEWANCHORY, WINDOWWIDTH-VIEWANCHORX-8,WINDOWHEIGHT-VIEWANCHORY-56);


The -8,-56 adjustments are bogus. The clipper to the view area should be:

HRGN hrgn=CreateRectRgn(VIEWANCHORX,VIEWANCHORY, MAPPANELWIDTH+VIEWANCHORX,MAPPANELHEIGHT+VIEWANCHORY);


...as MAPPANELWIDTH = 9x32 or 288 pixels, MAPPANELHEIGHT is 5x32 or 160 pixels. Add on the 12,12 adjustment and you have 12,12,300,172 as your clipping view area. Duh.

I''ve since gone back and reduced my world space to be the same as game: 9x5. There''s no need for a world larger, since clipping should potentially still work with a game area the same size as the screen.

Still working on solving the top and left clipping problem, however...

Share this post


Link to post
Share on other sites