MGP Question: DrawToBackBuffer()

jontolof
Unregistered
 
Post: #1
I am completely new to game programming, so I bought the book Mac Game Programming. So far I really like it.
I have been programming C++ before, but it's been a while and a few questions arise from time to time.

On page 101 Mark discusses double buffering under Mac OS X. He describe a function call;

void DrawToBackBuffer(WindowPtr theWindow, short pictureResourseID)
{...}

My question might seem trivial, but really bugs me. Where is this function supposed to be implemented? Is it meant to be a member function of the GameOffScreenBuffer, thus being implemented like:

void GameOffScreenBuffer::DrawToBackBuffer(WindowPtr theWindow, short pictureResourseID)
{...}

Or where am I supposed to put it?

Thanx

/Jont Olof
Quote this message in a reply
w_reade
Unregistered
 
Post: #2
I'm sorry, this isn't entirely a reply, it's more a related question that's been confusing me a bit, but the next sentence may be relevant. I read that windows are automatically double-buffered under OSX.

I've been carbonising a game where I write everything to a window-sized GWorld and then copy to a window. Does this mean I'm actually triple-buffering the window? And if so, how do I stop? I couldn't find detail on this anywhere, so I don't see how the machine knows when to draw from the window's back buffer to its front. You'd think there was some specific callÖ or not? Can I just write bit and pieces to the window and trust it to become visible when I want it to (psychic API?!).

sorry to hijack your thread, jontolof, but I think replies might help both of usÖ

It's just that if DrawToBackBuffer() is a member function of GameOffscreenBuffer class, it seems to me like you're potentially triple-buffering as well. As far as I can see, this function has no particular reason to be a member of this class. I don't have the book, though, so I'm probably just wrong.

ps don't let my ignorance put you off, there are many helpful people on this forum who are far more knowledgeable than me. And, first postÖ welcomeSmile
Quote this message in a reply
jontolof
Unregistered
 
Post: #3
Thank you, I'm glad to be here!

You might be right about the tripple-buffering, though like I said, I'm new to both Carbon and gameprogramming (I have been programming quite a lot Cocoa though, for what that's worth). This question still bugs me though and I have full confidence that someone around here can help me... Smile

/Jont Olof
Quote this message in a reply
Member
Posts: 111
Joined: 2002.06
Post: #4
The DrawToBackBuffer() function is not implemented in the source code on the CD-ROM. It is merely an example of drawing a picture into the back buffer of an OS X window. As w_reade said, if DrawToBackBuffer() were a member function of the GameOffscreenBuffer class, you would be drawing three times, slowing your game down.

There is a good reason why the DrawToBackBuffer() function was not implemented. In the game in the book, the back buffer contains the portion of the game world that the player will see on the screen. This portion of the game world is a bunch of tiles, which I copy from an offscreen buffer to the back buffer. There is no need to directly draw a picture in the back buffer, which is why I did not implement the DrawToBackBuffer() function.

What you would want to do in your game is check whether or not the window is double-buffered by calling the function QDIsPortBuffered(). If QDIsPortBuffered() returns true, you would do your drawing into the window (which will draw into the window's back buffer), then call QDFlushPortBuffer() to make the contents appear on the screen. Otherwise, you would do your drawing into an offscreen buffer, then copy the contents of the offscreen buffer to the screen.

Mark Szymczyk
http://www.meandmark.com
Quote this message in a reply
w_reade
Unregistered
 
Post: #5
thanks, I'll do that now.
Quote this message in a reply
w_reade
Unregistered
 
Post: #6
I'm getting something funny happening. I've done this (although, if anything, it slows things down (?)), but when I GetGWorldPixMap() for the window's CGrafPtr and draw directly into it, it draws directly onto the screen in global co-ordinates. Everything else draws fine, and in the right place, although I'm using the exact same GWorldPtr/CGrafPtr.

any suggestions?

[edit] more details - no it doesn't slow things down, I had my monitor in the wrong colours. However, the stuff I draw directly draws over (and stays over) everything on screen except the window I want it to be drawn in, where it gets drawn over immediately. (so it looks flickery)

[edit - misleading grammar]
Quote this message in a reply
Member
Posts: 111
Joined: 2002.06
Post: #7
Quote:Originally posted by w_reade
I'm getting something funny happening. I've done this (although, if anything, it slows things down (?)), but when I GetGWorldPixMap() for the window's CGrafPtr and draw directly into it, it draws directly onto the screen in global co-ordinates. Everything else draws fine, and in the right place, although I'm using the exact same GWorldPtr/CGrafPtr.

any suggestions?

[edit] more details - no it doesn't slow things down, I had my monitor in the wrong colours. However, the stuff I draw directly draws over (and stays over) everything on screen except the window I want it to be drawn in, where it gets drawn over immediately. (so it looks flickery)

[edit - misleading grammar]

The fact that your drawing ends up in portions of the screen other than your window tells me that you're not setting the port to the window before drawing into it. Make sure you call either SetPort() or SetGWorld() before drawing.

When you call QDFlushPortBuffer(), you should call it only once per frame. If you call it every time you draw something, things will slow down and you can get some flickering. I can't think of anything else to tell you at the moment.

Mark Szymczyk
http://www.meandmark.com
Quote this message in a reply
w_reade
Unregistered
 
Post: #8
The PixMap is Locked, the GWorld is Set. No joy.

As far as I can tell, the flickering is because the order goes like this:

1: draw everything to the window's back buffer

2: supposedly draw the fire to the back buffer, but actually straight onto the screen

3: QDFlushPortBuffer draws the back buffer to the window, overwriting the fire which should have been drawn to the back buffer in the first place.

I reckon I'll go back to the triple-bufferingÖ I'll miss the extra speed, but not the craziness.

Has anyone else experienced strangenesses with quickdraw in X? see "quickdraw troubles (reprise)" in General Programming for details of my other "little problem".
Quote this message in a reply
jontolof
Unregistered
 
Post: #9
Sorry w_reade! Can't help you there! Smile

Anyway, now I've finished the graphics chapter and I gladly compiled the code on the CD (with the errata I downloaded from Marks homepage).

The screen I get when I chose "Start" under the game menu is but a completely yellow one. Is this actually right, or is there something wrong with the code? I couldn't find any reference in the book telling me what the picture was supposed to look like, so I figured that maybe someone around here (perhaps szymczyk) could help me?

I really do like the book by the way. Good work...

/Jont Olof
Quote this message in a reply
kainsin
Unregistered
 
Post: #10
I do this:
Code:
// If we are in Mac OS X then draw right to the window, if not
// the draw into our back buffer.
if( inMacOSX )
{

  // Set the window as the port.
  SetPortWindowPort( gMainWindow );
        
  // Lock the window's port bits for our drawing routines.
  LockPortBits( GetWindowPort( gMainWindow ) );
}
else
{
        
  // Set the offscreen buffer as the port.
  SetPort( gBackBuffer );
        
  // Lock the bits of the offscreen buffer while
  // we draw into it.
  LockPixels( GetGWorldPixMap( gBackBuffer ) );
}

// Draw everything into the current port.
DrawEverything();

// Are we in Mac OS X?
if( inMacOSX )
{
    
  // Unlock the window's port bits.
  UnlockPortBits( GetWindowPort( gMainWindow ) );
}
else
{
        
  Rect    windowRectangle;
        
  // Switch the port to the window.
  SetPortWindowPort( gMainWindow );
        
  // Get the size of the window.
  GetWindowPortBounds( gMainWindow, &windowRectangle );
        
  // Lock the window's port when we dump in the back buffer.
  LockPortBits( GetWindowPort( gMainWindow ) );
        
  // Copy the bits from the back buffer into the window.
  CopyBits( GetPortBitMapForCopyBits( gBackBuffer ),
    GetPortBitMapForCopyBits( GetWindowPort( gMainWindow ) ),
    &windowRectangle, &windowRectangle, srcCopy, NULL );
        
  // Unlock the window.
  UnlockPortBits( GetWindowPort( gMainWindow ) );
        
  // Unlock the offscreen buffer.
  UnlockPixels( GetGWorldPixMap( gBackBuffer ) );
}

inMacOSX is a boolean that I set when the application launches. I didn't realize that there was a QDIsPortBuffered() function, which would probably work out better.
Quote this message in a reply
Member
Posts: 111
Joined: 2002.06
Post: #11
Quote:Originally posted by jontolof
Sorry w_reade! Can't help you there! Smile

The screen I get when I chose "Start" under the game menu is but a completely yellow one. Is this actually right, or is there something wrong with the code?
/Jont Olof

This is actually right. If you want to draw a different picture, just go into a resource editor (ResEdit or Resorcerer) and substitute a different PICT resource in the resource file. If you are using Project Builder, you will have to clean the project and recompile the code. If you are using CodeWarrior, just recompile the code.

Mark Szymczyk
http://www.meandmark.com
Quote this message in a reply
jontolof
Unregistered
 
Post: #12
Quote:Originally posted by szymczyk


This is actually right. If you want to draw a different picture, just go into a resource editor (ResEdit or Resorcerer) and substitute a different PICT resource in the resource file. If you are using Project Builder, you will have to clean the project and recompile the code. If you are using CodeWarrior, just recompile the code.

Thank you for bringing that up. Since this is the first time I write Carbon-Apps (or mac apps in C++) I have never actually been manipulating the resource-file. I have been programming a lot of Cocoa-apps, but so far I only created Nib-files and did a bit of localization.
In other words, how do I get a resource editor for free (I am after all a student with rather limited financial resources)? And what do I do with it!?

Forgive my ignorance, it might seem trivial to you, but though I'm seriously trying to figure this out, I do need some help.

I downloaded a Resourcerer Demo but it all seems like greek to me. Is it easily explained? Maybee it's covered in the book (somewhere after chapter 4 Smile ).

Thanx for the aid...

/Jont Olof
Quote this message in a reply
jontolof
Unregistered
 
Post: #13
Okay! I opened the resource-file in Resourcerer and I found the type named PICT. I see the game background (Yellow) and I have a PICT-file. But how do I change them?

/JO
Quote this message in a reply
Member
Posts: 111
Joined: 2002.06
Post: #14
Quote:Originally posted by jontolof
Okay! I opened the resource-file in Resourcerer and I found the type named PICT. I see the game background (Yellow) and I have a PICT-file. But how do I change them?

/JO
You need a PICT resource. The Graphic Converter program on the CD-ROM will convert your PICT file to a PICT resource. Copy your PICT resource into the resource file. Change the resource ID of the original PICT (the yellow one), and give your PICT resource the ID the original PICT had before you changed it.

Mark Szymczyk
http://www.meandmark.com
Quote this message in a reply
jontolof
Unregistered
 
Post: #15
I finally figured it out! Thank you for the help Mark.

/JO
Quote this message in a reply
Post Reply