Why does my view draw so slowly?

Member
Posts: 43
Joined: 2009.10
Post: #1
Okay, so I'm pretty new to graphics programming - I've only done a little bit with the standard NS drawing tools. Since I'm trying to make a simple game I've been trying to learn how to use Quartz.

Basically all I'm trying to do right now is a have a game world background that scrolls across the screen. This background is created by using repeate image textures (of type jpg) that are first draw onto a CGLayer. When I scroll the background I simply draw the layer at a different position in my custom view each time. When I get a keydown event I create a NSTimer (only one timer is ever activated so continuous keydowns will not create unecessary copies) and the firing function simply updates the position at which the background should be displayed. Despite the fact that my timer is set to fire every .01 seconds its scrolls much slower. Making a smaller firing interval makes no difference as well. While my computer is slow, this should not be a demanding task on the computer at all. So my question is what's causing this to run so badly? I've included my code below for this custom view (excluding the non essentials) and thanks for any help.

Code:
- (id)initWithFrame:(NSRect)frame {

    ifstream wldFile;

    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    
    m_playerPos.x = 337.5;
    m_playerPos.y = 337.5;
    
    
    wldFile.open("plainworld.txt");
    m_wldBg.resize(90);
    for(int i = 0; i < 90; i++){
    
        m_wldBg[i].resize(90);
        for(int j = 0; j < 90; j++){
        
            int tmp;
            wldFile >> tmp;
            m_wldBg[i][j] = tmp;
        
        }
    
    
    }
    
    wldFile.close();
    
    
    return self;
}


- (void) awakeFromNib{

    CGPoint tempPos;
    CGRect myContextRect;
    CGRect iBound;
    grass = [self getCGImageFromFile:"grass.jpg"];
    stone = [self getCGImageFromFile:"stone.jpg"];
    
    CGContextRef myContext = (CGContextRef)[[NSGraphicsContext // 1
                                currentContext] graphicsPort];
                                
    CGContextRef layerContext1;
    
    iBound = CGRectMake(0, 0, 675, 675); //size of my view
    
    background = CGLayerCreateWithContext(myContext, iBound.size, NULL);
    layerContext1 = CGLayerGetContext(background);

      //m_wldBg is a vector matrix with specifies what image tile to draw

    for(int i = 0; i < m_wldBg.size(); i++){     
        for(int j = 0; j < m_wldBg[i].size(); j++){
        
            tempPos.x = i*15 - (m_playerPos.x - 337.5);
            tempPos.y = j*15 - (m_playerPos.y - 337.5);
            
            myContextRect = CGRectMake(tempPos.x, tempPos.y, 15, 15);
        
            if(m_wldBg[i][j] == 0)
                CGContextDrawImage (layerContext1, myContextRect, grass);
            else if(m_wldBg[i][j] == 1)
                CGContextDrawImage (layerContext1, myContextRect, stone);
                
        }
        
    }

}

- (void)drawRect:(NSRect)rect {
    
    
    CGContextRef myContext = (CGContextRef)[[NSGraphicsContext // 1
                                currentContext] graphicsPort];
                                

                                
    CGPoint tempPos;
    
    
    tempPos.x = 337.5 - m_playerPos.x;
    tempPos.y = 337.5 - m_playerPos.y;
    
        
    CGContextDrawLayerAtPoint(myContext, tempPos, background);
}

- (void) keyDown:(NSEvent *)event{

    unsigned short keyCode;
       m_keyCode = [event keyCode];

       if(m_keyDownTimer != nil){
    
        if(![m_keyDownTimer isValid]){
        
            m_keyDownTimer = [[NSTimer scheduledTimerWithTimeInterval:0.0001 target:self selector:@selector(keyTimer:) userInfo:nil repeats:YES] retain];
        }
    }
    else{
    
        m_keyDownTimer = [[NSTimer scheduledTimerWithTimeInterval:0.0001 target:self selector:@selector(keyTimer:) userInfo:nil repeats:YES] retain];
    
    }

}


- (void) keyUp:(NSEvent *)event{

    //NSLog(@"Killing Timer");
    [m_keyDownTimer invalidate];

}


- (void) keyTimer:(NSTimer *)aTimer{

    //NSLog(@"In Timer");
    double inc = 1;
    if(m_keyCode == 126){
    
        m_playerPos.y += inc;
    
    }
    else if(m_keyCode == 125){
    
        m_playerPos.y -= inc;
    
    }
    else if(m_keyCode == 123){
    
        m_playerPos.x -= inc;
    
    }
    else if(m_keyCode == 124){
    
        m_playerPos.x += inc;
    
    }
    
    [self setNeedsDisplay:YES];

}
Quote this message in a reply
Moderator
Posts: 508
Joined: 2002.09
Post: #2
Probably not the reason why it's slow, but since you are retaining the timer, you must also release it after invalidating it!

"When you dream, there are no rules..."
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
You may be able to turn down some quality options to get better speed, but ultimately, making a game with a lot of animation in Quartz is probably futile. OpenGL is the way to go if you need speed.
Quote this message in a reply
Member
Posts: 43
Joined: 2009.10
Post: #4
I guess I thought for something as simple as moving a background it would be decently fast enough at this point. Instead though its getting like 15FPS... Perhaps I'll have to crack open an OpenGL book.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  When to create custom OpenGL view instead of subclass NSOpenGL view Coyote 37 22,676 Oct 20, 2009 08:16 PM
Last Post: Coyote
  Slowly moving objects McSebi 2 1,970 Jul 3, 2006 02:01 PM
Last Post: McSebi