2

iPad App setup: SceneA contains layerA - 1024x768. Push a button in layerA, layerB drops down over top using a CCMoveTo action. LayerB is only 800x600 so you can see layerA behind it (think of an overlayed pause screen type effect). LayerB contains an 800x600 sprite that the user can zoom in on by pressing a button. The zoom effect is simply a combination of CCScaleTo and CCMoveTo to keep it centered on the part it's zooming in on. However, when the sprite scales, so does layerB overtop of layerA. Is there a way to scale the sprite within a contained window?

BobbyScon
  • 2,537
  • 2
  • 23
  • 32

1 Answers1

1

LayerB should use the GL_SCISSOR_TEST to trim the outside of itself. You can easily google for more information about it, it basically defines a rect and then uses glScissoron it to remove the outside. I have a class I extend when I need to do this, that goes as follows:

//
//  CCNodeClip.h
//
//  Created by Ignacio Orlandoni on 7/29/11.
//

#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface CCNodeClip : CCLayer {

}

-(void)preVisit;
-(void)postVisit;

@end

-

//
//  CCNodeClip.m
//
//  Created by Ignacio Orlandoni on 7/29/11.
//

#import "CCNodeClip.h"
@implementation CCNodeClip

-(void)visit {
    [self preVisit];
    [super visit];
    [self postVisit];
}

-(void)preVisit {
    if (!self.visible)
        return;

    glEnable(GL_SCISSOR_TEST);

    CGPoint position = [self position];

    //I don't remember if this rect really serves for both orientations, so you may need to change the order of the values here.
    CGRect scissorRect = CGRectMake(position.x, position.y, [self contentSize].width, [self contentSize].height);

    //    CCLOG(@"Scrissor Rect: X: %02f, Y:%02f, W: %02f, H: %02f", scissorRect.origin.x,     scissorRect.origin.y, scissorRect.size.width, scissorRect.size.height);

    // Handle Retina
    scissorRect = CC_RECT_POINTS_TO_PIXELS(scissorRect);

    glScissor((GLint) scissorRect.origin.x, (GLint) scissorRect.origin.y,
              (GLint) scissorRect.size.width, (GLint) scissorRect.size.height);
}

-(void)postVisit {
    glDisable(GL_SCISSOR_TEST);
}


@end 

With that imported into LayerB, you can now define it as a CCNodeClip instead of CCLayer.

Some links...

glScissor << cocos2d Forum

Circle shape clipping with opengl-es in cocos2d << StackOverflow

Cocos2d iPhone - Sprite cliping/mask/frame << StackOverflow

Another Cocos2D gem: ClippingNode << Learn-Cocos2d.com

As a side note...

CCScaleTo + CCMoveTo can be avoided if the anchor point for the sprite is centered, so the image stays centered in the container as it scales. (.anchorPoint = ccp(0.5, 0.5);)

Community
  • 1
  • 1
IOrlandoni
  • 1,790
  • 13
  • 30
  • Using your code seems to work perfectly! That was dead easy to implement. My app is landscape orientation only, and I didn't have to alter anything in your code. As far as the CCScaleTo and MoveTo goes, I'm actually zooming in on different points of the layer based on where the user touches, not just the center. Good point though. Thanks so much! – BobbyScon Mar 09 '12 at 14:31
  • Even though the issue is resolved, I recommend you do look up `GlScissor` to try and fully understand how it works and what can it do. You are welcome. – IOrlandoni Mar 09 '12 at 14:41
  • Yeah, as soon as I saw your post (about 3 minutes after you posted it) I did a google search and found many of the same links you posted. My problem was really a case of not knowing what to search for. I hadn't heard of GLScissor before. Your code seems more effecient than the setup on Learn-Cocos2d.com – BobbyScon Mar 09 '12 at 14:44
  • It all depends on what you need. @LearnCocos2D 's code accounts for scaling, orientation and orientation changes. Also, the post itself gives good tips and links. – IOrlandoni Mar 09 '12 at 14:52