NSTimer and recursive drawing

jamil5454
Unregistered
 
Post: #1
After spending hours of reading tutorials and trying understand Cocoa 2d drawing on my own, I've finally given up and decided to see if anyone here can solve my problem.

The point of this small app is to recursively draw rectangles inside rectangles, with each successive rectangle smaller than the one before it. More specifically, each smaller rectangle is either 1/3 the width of its predecessor, or 1/3 the height (depending on a random 0 or 1 value). Each rectangle has a random color assigned to it. The recursive loop runs until the rectangles become smaller than a predetermined size (in this case, it's 5 pixels across and 5 pixels high). So, in effect, you should see the screen being split into smaller and smaller rectangles, until the whole screen is covered with tiny colored rectangles. It's actually really cool, if it'll work.

I've managed to code this using Java, which I'm much more familiar with (2 KB):

http://homepage.mac.com/jboukheir/.Publi...g.java.zip

For some reason, this doesn't work unless you're using the 1.5 version of the java runtime. With 1.4, it just shows a blank screen. Also, to exit the program, just click the mouse. Otherwise it repeats itself forever.


Now, the Cocoa version is a standard Cocoa Application built using XCode 2.2 on Tiger 10.4.3 using my Rev. C DP 2.0 G5. I'm using an NSTimer to try to slow it down to a rate of 24 fps (or 24 rectangles drawn per second). The problem is that the rectangles are being drawn to the view all at once, and then the view is displayed when it's done. I've tried using '[self setNeedsDisplay:YES]' and '[self display]' after each rectangle I draw, but to no avail. So here's the XCode project (1.7 MB):

http://homepage.mac.com/jboukheir/.Publi...csProg.zip

I hate for this to be my first post, but I've been yearning to learn Cocoa so I could port a few games I wrote in Java to run natively on my Mac. Much thanks, and replies are appreciated.

P.S. - you can do whatever you want with the source
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #2
I looked over your project, and if I understand what you're aiming for, I think I know what you need to do.

First, my understanding is that you want the recursive descent to be animated. What you've got is the recursion executing all at once. Since Cocoa doesn't support exit or re-entry into recursive descent, you are going to have to view this problem differently.

Here's what I'd do -- I'd make a vector of the rects which need to be drawn in the next pass. With each iteration, I'd draw the rects generated in the last pass, and store the rects needed for the next pass. You're no longer recursive -- but as any good CS book will tell you, clean and manageable recursive algorithms can always be turned into hard-to-read and hard-to-maintain non-recursive stack-based algorithms.

Code:
- (void) display: (NSRect) r
{
    if ( firstFrame )
    {
        firstFrame = false;
        
        NSRect r = bounds();
        drawRectangles( r );
    }
    else if ( !_pass.empty() )
    {
        std::vector< NSRect > pass = _pass;
        _pass.clear();
    
        std::vector< NSRect >::iterator it( pass.begin() ), end( pass.end() );
        for ( ; it != end; ++it )
        {
            drawRectangles( *it );
        }
    }
        else
        {
            [_timer invalidate];
            [_timer release];
            _timer = NULL;
        }
}

- (void) displayRectangles: (NSRect) rect
{
    // display the rectangle in 'rect', and calculate the child rects, and add them to _pass
}

You don't have to se STL, but STL would make it easy to store a stack of NSRects.

ANyway, the idea is that with each tick of the timer, you'd execute the rects caculated by the previous pass, and generate new ones for the next pass. Obviously, you'd need an exit case when rects get too small, e.g., when height or width < 1 pixel. If that happens, don't add to the _pass vector. When the pass vector is empty, stop the timer.
Quote this message in a reply
jamil5454
Unregistered
 
Post: #3
Thanks for the suggestion. I was thinking that I'd probably have to approach this in a different way, and it seems I was right. I'll try it later tonight after class.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #4
Lemme know if it works Rasp
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  CVDisplayLink instead of NSTimer OptimisticMonkey 6 7,323 Nov 18, 2009 02:49 PM
Last Post: SethWillits