Archived

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

Odoacer

help with rects

Recommended Posts

Odoacer    140
I'm having a hard time grasping rects. Forgive me but spatial visualization has never really been my strong suit. I'm blitting to an offscreen back buffer, then blitting the back buffer to the primary surface in a windowed DirectDraw app. I think my problem is in me trying to translate my backbuffer cords to screen coords.
	RECT rect, srcrect;
	POINT p1, p2;

	p1.x = 0;
	p1.y = 0;
	p2.x = 800;
	p2.y = 600;

	ClientToScreen(ddhWnd, &p1);
	ClientToScreen(ddhWnd, &p2);

       srcrect.left   = p1.x;
       srcrect.top    = p1.y;
       srcrect.right  = p2.x;
       srcrect.bottom = p2.y;

       GetWindowRect(ddhWnd, &rect);	//fills the rectangle with the window dimensions


	if(FAILED(ddBackBuffer->BltFast(0, 0, image[1], NULL, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT)))
			MessageBox(NULL, "Back buffer blit failed.", "Error", MB_OK);


	if(FAILED(ddSurface->Blt(&rect, ddBackBuffer, &srcrect, DDBLT_KEYSRC | DDBLT_WAIT, &ddbltfx)))
		MessageBox(NULL, "Primary surface blit failed.", "Error", MB_OK);
I'm pretty sure it blits to the backbuffer correctly but it won't blit to the primary buffer, which leads me to believe its got something to do with my coordinates (i'm using DDraw in windowed mode). [edited by - Odoacer on January 24, 2004 11:22:41 PM]

Share this post


Link to post
Share on other sites
Supernat02    604
Your source rect is going to have the same x and y values for start and end, since both come from ClientToScreen(...). I really don''t think you even want to use ClientToScreen(...). It depends on how you filled your backbuffer.

Did you create a backbuffer the size of the screen resolution and then write to it at the position where the window would be? That''s probably not a good idea. All you should have for the backbuffer is just enough for what you are going to put in it, which is probably the size of your window.

Say your window is 300x200. So you create a backbuffer as such. You draw into the backbuffer starting at 0,0. Then you set your source rect to (0,0,300,200) and then you do what you did to find the location of your window on the screen and set the dest rect to that (I think, I don''t remember if you even have to do that, it may be client zero based).

Hope this helps!
Good luck,
Chris

Share this post


Link to post
Share on other sites
Odoacer    140
quote:
Original post by downgraded
quote:
Original post by Odoacer
I''m having a hard time grasping rects.


*adolesent snickering*



[edited by - downgraded on January 25, 2004 2:51:02 AM]

Hey dude, no dis.

Back on topic...
My window is 800x600, and my backbuffer is 800x600 also. (I''m running at 1024x768). I''m using BltFast to draw a background image onto the backbbuffer. It''s all in the code above. (Maybe that''s the problem?)

I got rid of the ClientToScreen function and now I can display my background directly (ie, blitting to the primary surface, not using the backbuffer). So now maybe I''m thinking there''s something wrong with the way I''m filling my backbuffer... (but it''s not raising any errors though) I would continue just blitting multiple surfaces to the primary surface but it flickers terribly if I do that, which is why I need the backbuffer.



Share this post


Link to post
Share on other sites
SelethD    456
Why are you blitting from the BackBuffer, to the Surface?
Your supposed to use the Flip function

After your blit your image onto the back buffer, then execute this command.

ddSurface->Flip(0,DDFLIP_WAIT);

It will flip the contents of the back and front buffers, thus displaying what you just blitted on the back buffer.

then Blit to back buffer again with next frame, and flip again, and over and over and over, do this about 30 times per second, and call me in the morning.

Share this post


Link to post
Share on other sites
Supernat02    604
Okay now that I know a little more:

You don't need ClientToScreen at all. As long as p1 = 0,0 and p2 = 800, 600, you should be fine...I think. Honestly, it's been a long time since I've done directdraw, so I'm not sure if you need to pass the window's location in as the dest or just the zero offset (i.e. 0,0 to 800,600)...something is telling me you don't need to know the window's location at all...that 0,0 is the top left corner OF the window. I'm pretty sure this is how I did things with DD. My memory isn't that fresh though, so try two things. Try blitting with the same source and dest rects, both set at 0,0,800,600. Or try this if that doesn't work:


RECT rect, srcrect;
POINT p1, p2;
p1.x = 0;
p1.y = 0;
p2.x = 800;
p2.y = 600;
srcrect.left = p1.x;
srcrect.top = p1.y;
srcrect.right = p2.x;
srcrect.bottom = p2.y;

GetWindowRect(ddhWnd, &rect); //fills the rectangle with the window dimensions


if(FAILED(ddBackBuffer->BltFast(0, 0, image[1], NULL, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT)))
MessageBox(NULL, "Back buffer blit failed.", "Error", MB_OK);

if(FAILED(ddSurface->Blt(&rect, ddBackBuffer, &srcrect, DDBLT_KEYSRC | DDBLT_WAIT, &ddbltfx)))
MessageBox(NULL, "Primary surface blit failed.", "Error", MB_OK);


What is image[1]? Do you have the code for loading that texture?

Chris

[edited by - Supernat02 on January 25, 2004 12:14:21 AM]

Share this post


Link to post
Share on other sites
Odoacer    140
Oh I just have an array of LPDIRECTDRAWSURFACE7s called image[]and I'm using image[1] (my main background) for testing. I'm initializing them using the ddutil library, so it's not much more than image[1] = DDLoadBitmap(), then I set a colorkey. Pretty standard stuff.

ddSurface->Blt(&rect, image[1], &srcrect, DDBLT_KEYSRC | DDBLT_WAIT, &ddbltfx);
works perfectly. Problem is, I can't blit to the primary surface twice(or more) because then it flickers terribly which is why I need the backbuffer to blit multiple images on. Then I can blit the backbuffer onto the primary surface.

I have a nagging feeling now that the problem may be with the way I'm drawing things to my backbuffer, but I don't see what's wrong... any ideas?

Edit: I've also come to the thought that if I'm using BltFast for my backbuffer, then I won't need the srcrect rect at all, because I can just designate the offset in BltFast's first two parameters. Since my backbuffer is 800x600, the same size as my window, the Blt function should take care of translation to screen coordinates.

That being said though, I'm still really not any closer.

[edited by - Odoacer on January 25, 2004 12:35:51 AM]

Share this post


Link to post
Share on other sites
Supernat02    604
You''re setting the rect parameter to NULL when you draw to the backbuffer, but I''m pretty sure that is okay. At least it used to be, because I did that too...but it wasn''t with the LPDIRECTDRAWSURFACE7 surface.

You said "ddSurface->Blt(&rect, image[1], &srcrect, DDBLT_KEYSRC | DDBLT_WAIT, &ddbltfx); " works perfectly. What are rect and srcrect in this case? Sorry, just trying to get an idea of what''s working and what''s not. Have you tried the suggestions in my previous post? How about trying it without the color keys and make sure it draws something...it could be an issue with those. Just some more ideas to try!

Chris

Share this post


Link to post
Share on other sites
Supernat02    604
In regards to your EDIT, yes I think you are correct. I am pretty sure that the surfaces, when using rects to specify the part to copy and paste, are just a place in video memory and the start and end of the rects are just zero based. DirectDraw knows that 0,0 begins at the beginning of your client window...I think.

Chris

Share this post


Link to post
Share on other sites
Odoacer    140
rect will be the whatever the function GetWindowRect() sets it to - I think the window location on the screen. srcrect is the dimensions of my source surface, but I've realized something(more on that below).

The reason I'm leaving the fourth parameter on the BltFast to NULL is because I want it to copy the whole surface (which is my background). If I wanted to copy just a small part of it, I'd use rects, I guess.

I'm finally starting to understand how they're used. (to specify parts to copy and paste, just like you said supernat02)

now I think the right thing to do would be just to leave the source rect (3rd) parameter to NULL in my ddPrimary->Blt function, because I want to copy the entire backbuffer, not just a part of it. So it's sayanora for all my POINT code - it now looks like this:


RECT rect;
GetWindowRect(ddhWnd, &rect); //fills the rectangle with the window dimensions

if(FAILED(ddBackBuffer->BltFast(0, 0, image[1], NULL, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT)))
MessageBox(NULL, "Back buffer blit failed.", "Error", MB_OK);
if(FAILED(ddSurface->Blt(&rect, ddBackBuffer, NULL, DDBLT_KEYSRC | DDBLT_WAIT, &ddbltfx)))
MessageBox(NULL, "Primary surface blit failed.", "Error", MB_OK);


What's eating at me is now that I understand the theory better and I'm pretty sure this should work but it's not. I suspect it might have something to do with how it's drawing to my backbuffer, but I don't have the foggiest as to what it is.

I really do appreciate the help though, and yes I did try all of your suggestions - in fact they helped to lead me to my current conclusions.

[edited by - Odoacer on January 26, 2004 1:12:51 AM]

Share this post


Link to post
Share on other sites
Supernat02    604
Hmm...I''m thinking the source and dest rect could be NULL. Try that. You''re calling GetWindowRect(ddhWnd, &rect); for the destination, but in fact, GetWindowRect returns screen coordinates. You want window coords...i.e. (0,0,800,600)

One way to test this out is to just move your window to the top left corner of the desktop and run the game. OR, try setting the dest rect to NULL too.

Good luck,
Chris

Share this post


Link to post
Share on other sites
Odoacer    140
Changing the dest rect to NULL didnt work either. As a matter of fact, my window flickered for a minute (but the image was terribly distorted), then my computer crashed (and I mean CRASHED). I couldn''t turn it back on, so I had to swap my power cable. No worries though, I think it''s my powersupply going bad.

In short, nope, setting it to NULL didn''t work. How would you usually draw to a backbuffer in windowed mode?

Share this post


Link to post
Share on other sites
Supernat02    604
In my code, I did the following:

RECT Rect;
Rect.left = 0;
Rect.top = 0;
Rect.right = FGrid->Width;
Rect.bottom = FGrid->Height;

FGrid is the width and height of each tile in a grid.

Frame->Surface->BltFast(0, 0, (fpSourceSprite->Frames[z]->Surface), &Rect, NULL);

This would blit a source sprite to a destination sprite.

Then,

FSecondarySurface->BltFast(ptStartPoint.x, ptStartPoint.y, Sprite->CurrentFrame->Surface, NULL, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);

which blits to the secondary surface the sprite.

Then,

FPrimarySurface->BltFast(ptStartPoint.x, ptStartPoint.y, FSecondarySurface, NULL, DDBLTFAST_WAIT | DDBLTFAST_NOCOLORKEY);

which just blits the secondary to primary. It should be that simple. So I don't know what's going on with yours.

Chris

[edited by - Supernat02 on January 29, 2004 10:06:20 PM]

Share this post


Link to post
Share on other sites