PDA

View Full Version : Window Buffer Trouble


Stalin55
2006.08.01, 08:26 PM
I just recently began fixing up an old 2d isometric engine written in Carbon C and it uses QuickDraw for graphics (yes I know its deprecated, but I'm using it anyways).

Basically, I have a GWorld (which is larger than the window it is copied to in order to allow for scrolling)on which all of my tiles and sprites are assembled to, then I copy the correct part of the GWorld that would be visible to the player into the window(or the window's back buffer) and of course then I flush the buffer.

Now obviously there is an extra buffer in this sequence which signifigantly slows down the engine. The reason why assemble the final image to an offscreen buffer and not directly to the window's buffer is because I assemble an area larger than the area of the window(to allow fo scrolling).

I see only two possible solutions; either somehow disable the windows offscreen buffer (which would be my preference) or somehow resize the visible portion of the window without resizing it's buffer.

I read in some old apple dev doc where it said that the window will be double buffered unless specified otherwise which led me to believe that this can be done. Anyways I have searched through lots of old books and dev docs and have not been able to find how to do either, might anyone here know how?

ThemsAllTook
2006.08.01, 09:14 PM
Would it be an option to alter your drawing code to draw directly to the window's back buffer, clipped to the visible region? For scrolling, you could use CopyBits() to copy from the window's buffer to a different portion of itself, and only redraw the dirty and newly uncovered areas.

Stalin55
2006.08.01, 09:55 PM
I'm not quite sure what you meant about clipping the visible area. But here's how my graphics engine works in slightly greater detai to maybe give you a better ideal:

- Tile Sprites, enemy sprites, objects sprite, etc... are each stored in the respective GWorlds.
- I have a Tile Asseblt GWorld where I assemble all of the tiles
- once my tiles have been assembled in the Tile Assembly GWorld, I copy this image to another GWorld (I'll call is the Display Gworld), then I copy the sprites that I need to this Display GWorld.
-Then I determine the scrolling offset and I copy the appropriate part of the Display GWorld to the Window and then flush its buffer.

How scrolling works:
-There are rougly 4-6 extra rows and columns of tiles on on my tile assembly buffer and display buffer than appear in the game window
-Whenever the player moved a full tile in any direction I Copy part of the Tile Assembly Gworld to itself and the draw the new column, or rows of tiles.

OneSadCookie
2006.08.01, 10:26 PM
Just use the window's back buffer instead of your "display GWorld". It doesn't matter if it's not larger than the window, you've already got that covered by the "tile assembly GWorld".

ThemsAllTook
2006.08.01, 10:34 PM
The change that I was proposing would go something like this:

- Tile sprites, enemy sprites, object sprites, etc. would still be stored in their own GWorlds.
- Rather than having a tile assembly GWorld, you'd CopyBits them directly to the window, offset by scrolling as appropriate.
- Sprites would be copied directly to the window as well.
- When the scroll origin changes, you could use CopyBits to move the contents of the window, and add the newly uncovered regions to your dirty rect list.
- When a sprite moves, you'd make a dirty rect of the union of its old bounds and its new bounds.
- When redrawing dirty rects, you'd only need to concern yourself with the particular images (or parts of images) that intersect that dirty rect.

Hopefully that makes some sense...

OneSadCookie
2006.08.01, 10:55 PM
You can't use CopyBits when the source & dest areas might overlap, I think. I think there's a ScrollRect that does the same thing, though :)

Stalin55
2006.08.01, 11:21 PM
Just use the window's back buffer instead of your "display GWorld". It doesn't matter if it's not larger than the window, you've already got that covered by the "tile assembly GWorld".

It is important to keep in mind that this is an isometric engine...

Tiles are assembled to the Tile Assembly GWorld once at the begining of the engine and then they are copied into the Display GWorld(Both GWorlds are the same size). Every frame I copy sprites from their respective Gworlds into the Display GWorld and I do keep a list of the dirty rectangles for every sprite which I clean by copying the dirty rects from the Tile Aseembly GWorld into the Display GWorld using a single rect(so you see the Tile Assembly GWorld essential).

Every time the player moves all of the way onto an adjacent tile, I copy a large block of the Tile Assembly GWorld onto itself and then I draw in the new tile columns or rows. Then I copy the newly fixed Tile Assembly Gworld to the Display GWorld and reset the player so that his position will be in the center of the Display GWorld once again.

The Display GWorld must be the size that it is because of the extra padded rows and columns it contains, otherwise the player would not be able to scroll (keep in mind this is isometric). In fact, I actually need to add more padded rows and columns because of trouble with drawing large tiles such as wall which pop up suddenyl from the bottom of the screen(this is no problem though).

Anyways... I am 90% sure the solution to my problem lies in one of the below methods, and if anyone has any knowledge of either I would greatly appreciate it:

I see only two possible solutions; either somehow disable the windows offscreen buffer (which would be my preference) or somehow resize the visible portion of the window without resizing it's buffer.

OneSadCookie
2006.08.01, 11:48 PM
I still don't see why the display GWorld needs to be so large -- yes, if it's smaller, you have to recomposite the exposed sprites when you scroll, but that shouldn't be a big deal. Presumably you have animation that requires you to recomposite all the sprites every frame anyway.

You cannot enlarge the window's back buffer without enlarging the window. You should be able to turn off the double-buffering, but I don't see an API that allows this.

ThemsAllTook
2006.08.02, 08:36 AM
You can't use CopyBits when the source & dest areas might overlap, I think.
I remember being able to do it. That's how the level transition is done in Water Tower. It's pretty smart about it.