Making a hole on a CCRenderTexture - cocos2d-iphone

I am trying to make a hole on a CCRenderTexture with Cocos2D 2.0.
More specifically I have:
a CCSprite "stars" that shows some stars repeating a png image;
on top of that I have a CCRenderTexture "dark" that completely covers the "stars" sprite.
I want to be able to cut a hole on "dark" in order to show the stars below.
I am using CCRenderTexture (as suggested in some tutorials) but the hole I manage to make is never fully transparent, so the stars visible through the hole are partially obscured.
I really hope some one can show me the light, I spent over a week on this...
This is the code:
#interface MyBackgroundLayer : CCLayerGradient {
}
#end
#implementation MyBackgroundLayer
CCRenderTexture * dark;
CCSprite * stars;
-(id) init
{
if (self=[super init]) {
CGSize size = [[CCDirector sharedDirector] winSize];
// background
stars = [CCSprite spriteWithFile:#"stars.png" rect:CGRectMake(0, 0, size.width, size.height)];
stars.anchorPoint = ccp(0,0);
ccTexParams params = {GL_LINEAR,GL_LINEAR,GL_REPEAT,GL_REPEAT};
[stars.texture setTexParameters:&params];
[self addChild:stars];
// dark layer to cover the background
dark = [CCRenderTexture renderTextureWithWidth:size.width height:size.height];
[dark clear:0 g:0 b:0 a:1.0f];
[self addChild: dark];
dark.position = ccp(size.width/2,size.height/2);
[[dark sprite] setBlendFunc: (ccBlendFunc) { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }];
}
return self;
}
-(void)draw
{
[super draw];
[dark beginWithClear:0 g:0 b:0 a:1];
glColorMask(0, 0, 0, 1);
// Here I am using 0.5 as alpha value, this could seems the reason why the hole is not fully transparent.
// However if I change the alpha value to 1.0f or 0.0f the hole becomes completely opaque
ccColor4F color = ccc4f(1.f, 1.f, 1.f, 0.5f);
ccDrawSolidRect(ccp(0,0), ccp(600, 600), color);
glColorMask(1,1,1,1);
[dark end];
}
#end

I think what you're looking for is something like this ( may need some editing).
As for your code ..i thing the problem is in the blend function. Check this out to see how they work.

Related

CCSpriteBatchNode is deprecated Cocos2d 3.1

I have a problem following a tutorial for cocos2d 3.0 in cocos2d 3.1 ... when compilation finish show a warning "CCSpriteBatchNode is deprecated", how can I use the plist now? or isn't used now in cocos2d 3.1? can you write an example, would very helpful :)
#implementation GameScene
{
CCSpriteBatchNode *_batchNode; // WARNING 1 HERE
Hunter *_hunter;
Bird *_bird;
}
-(void)addBackground
{
//1
CGSize viewSize = [CCDirector sharedDirector].viewSize;
//2
CCSprite *background = [CCSprite spriteWithImageNamed:#"game_scene_bg.png"];
//3
background.position = ccp(viewSize.width * 0.5f, viewSize.height * 0.5f);
//4
[self addChild:background];
}
-(void)createBatchNode {
//1
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"Cocohunt.plist"];
//2
_batchNode = [CCSpriteBatchNode batchNodeWithFile:#"Cocohunt.png"]; // WARNING 2 HERE
//3
[self addChild:_batchNode z:1];
}
In version 3.1, the cocos2d renderer was re-made to automatically batch drawn sprites. So CCSpriteBatchNode is no longer needed, just use a CCNode.
#implementation GameScene
{
CCNode *_batchNode; // WARNING 1 HERE
Hunter *_hunter;
Bird *_bird;
}

Rotated Clipping Node in Cocos2d

I'm using the clipping node here: http://www.learn-cocos2d.com/2011/01/cocos2d-gem-clippingnode
ClippingNode.h
#import "cocos2d.h"
#interface ClippingNode : CCNode {
CGRect clippingRegionInNodeCoordinates;
CGRect clippingRegion;
}
#property (nonatomic) CGRect clippingRegion;
#end
ClippingNode.m
#import "ClippingNode.h"
#interface ClippingNode (PrivateMethods)
-(void) deviceOrientationChanged:(NSNotification*)notification;
#end
#implementation ClippingNode
-(CGRect) clippingRegion {
return clippingRegionInNodeCoordinates;
}
-(void) setClippingRegion:(CGRect)region {
// keep the original region coordinates in case the user wants them back unchanged
clippingRegionInNodeCoordinates = region;
self.position = clippingRegionInNodeCoordinates.origin;
self.contentSize = clippingRegionInNodeCoordinates.size;
// convert to retina coordinates if needed
region = CC_RECT_POINTS_TO_PIXELS(region);
// respect scaling
clippingRegion = CGRectMake(region.origin.x * scaleX_, region.origin.y * scaleY_,
region.size.width * scaleX_, region.size.height * scaleY_);
}
-(void) setScale:(float)newScale {
[super setScale:newScale];
// re-adjust the clipping region according to the current scale factor
[self setClippingRegion:clippingRegionInNodeCoordinates];
}
-(void) deviceOrientationChanged:(NSNotification*)notification {
// re-adjust the clipping region according to the current orientation
[self setClippingRegion:clippingRegionInNodeCoordinates];
}
-(void) visit {
glEnable(GL_SCISSOR_TEST);
CGPoint worldPosition = [self convertToWorldSpace:CGPointZero];
const CGFloat s = [[CCDirector sharedDirector] contentScaleFactor];
glScissor((clippingRegion.origin.x) + (worldPosition.x*s), (clippingRegion.origin.y) + (worldPosition.y*s),
(clippingRegion.size.width), (clippingRegion.size.height));
[super visit];
glDisable(GL_SCISSOR_TEST);
}
#end
However, I need to clip a rotated CCNode. Any idea on how I could accomplish such a task?
Replace the visit method in the class ClippingNode by this
-(void) visit
{
float rotationAngle = 15;
glPushMatrix();
CCRenderTexture* renderTexture = [[CCRenderTexture renderTextureWithWidth:512 height:512] retain];
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, clippingRegion.size.width, clippingRegion.size.height);
[renderTexture begin];
glPushMatrix();
glRotatef(rotationAngle, 0, 0, 1);
glTranslatef(-clippingRegion.origin.x, -clippingRegion.origin.y, 0);
[super visit];
glPopMatrix();
[renderTexture end];
glDisable(GL_SCISSOR_TEST);
renderTexture.sprite.position = CGPointMake(clippingRegion.origin.x , clippingRegion.origin.y);
renderTexture.sprite.anchorPoint = CGPointMake(0, 1);
renderTexture.sprite.rotation = rotationAngle;
[renderTexture.sprite visit];
[renderTexture release];
glPopMatrix();
}
Basically it creates a texture where to render the ClippingNode contents
Then translate the scene so that the origin in the clipping region is now at (0,0)
Rotate the entire scene by rotationAngle
Enable the scissor
Render the scene
Translate, rotate, and render the sprite containing the texture
It only needs CCRenderTexture to finish the job. Any suggestion will be greatly appreciated.
ClippingNode.h
#import "cocos2d.h"
#interface ClippingNode : CCNode
#property (nonatomic, assign) CGSize clippingSize;
#end
ClippingNode.m
#import "ClippingNode.h"
#interface ClippingNode()
#property (nonatomic, strong) CCRenderTexture * renderTexture;
#property (nonatomic, strong) CCSprite * clippedSprite;
#end
#implementation ClippingNode
#synthesize renderTexture;
#synthesize clippedSprite;
#synthesize clippingSize;
- (void) setClippingSize:(CGSize)newClippingSize {
//assignment
clippingSize = newClippingSize;
//set contentSize
self.contentSize = clippingSize;
//configure renderTexture
self.renderTexture = [CCRenderTexture renderTextureWithWidth:clippingSize.width height:clippingSize.height];
renderTexture.contentSize = CGSizeMake(clippingSize.width, clippingSize.height);
//configure the renderTexture sprite
self.clippedSprite = [CCSprite spriteWithTexture:renderTexture.sprite.texture];
clippedSprite.position = self.position;
clippedSprite.rotation = rotation_;
clippedSprite.scaleY = -1;
}
- (void)visit {
[renderTexture beginWithClear:0 g:0 b:0 a:1];
[super visit];
[renderTexture end];
[clippedSprite visit];
}
#end
Usage:
CCSprite * spriteImage = ...;
spriteImage.position = ccp(0,0);
spriteImage.anchorPoint = ccp(0.5,0.5);
//configure clipping Node
self.clippingNode = [ClippingNode node];
clippingNode.position = ccp(size.width * 0.5f, size.height * 0.5f);
clippingNode.anchorPoint = ccp(0.5f, 0.5f);
clippingNode.rotation = -10.0f;
//configure clipping region
[clippingNode setClippingSize:CGSizeMult(spriteImage.boundingBox.size, 1.5f)];
//add content to the clipping node
[clippingNode addChild:spriteImage]

Cocos2D - remove layer opacity on region

I got a Scene with a layer with the top z-index wich one adds a dark effect to the whole scene setting its opacity. What i am trying to do now is to remove the shadow/dark effect in a concrete region (inside a cone/triangle) as the image shows (inside the red polygon). In other words, i want to have the same "luminosity" (zero opacity) inside the triangle as on the left side of the screen.
code:
-(id) init
{
if( (self=[super initWithColor:ccc4(0,0,0,128)] )) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCLayerColor* layer1 = [CCLayerColor layerWithColor: ccc4(0, 0, 0, 180) width: winSize.width height: winSize.height];
layer1.position = ccp(50,0);
[self addChild: layer1 z:2];
CCSprite *background = [CCSprite spriteWithFile:#"background.png"];
background.position = ccp(background.contentSize.width/2, background.contentSize.height/2);
[self addChild:background];
CCSprite *player = [CCSprite spriteWithFile:#"Player.png"rect:CGRectMake(0, 0, 27, 40)];
player.position = ccp(player.contentSize.width/2, winSize.height/2);
[self addChild:player];
}
return self;
}
any idea on how to do this ?? maybe i should try to do it on another whay and not use a CCLayer to add the dark effect ??
Thanks in advance
The simplest way would be to use a CCSprite with a black image the size of the background. Then cut out the whole you need in an image program and draw that sprite over the background with lowered opacity.

CCRenderTexture (alpha) beginWithClear transparent white

I don`t understand how transparency/alpa works with CCRenderTexture.
With this code i would have expected a half transparent white over the red ColorLayer (Transparency works for the CCLayerColor). What i get is complete white.
This Code is just added to the default Template at the end of the HelloWorldLayer init Method.
CCLayerColor * lc = [CCLayerColor layerWithColor:ccc4(255.0f, 0.0f, 0.0f, 125.0f)];
[self addChild:lc];
CCRenderTexture * rt = [CCRenderTexture renderTextureWithWidth:480.0f
height:320.0f];
[self addChild:rt];
rt.position = ccp(240.0f,160.0f);
[rt beginWithClear:1.0f g:1.0f b:1.0f a:0.5f];
[rt end];
if i change to black i DO get half transparent black:
[rt beginWithClear:0.0f g:0.0f b:0.0f a:0.5f];
With alpha 0.0f and green 1.0 i get green - would have expected a clear layer..
[rt beginWithClear:0.0f g:1.0f b:0.0f a:0.0f];
The real problem ist that in that RT i can`t draw transparency with white in a fragment shader:
gl_FragColor = vec4( 1.0, 1.0, 1.0, 0.5);
results in complete white..
Any idea?
Try it:
[renderTexture.sprite setBlendFunc:(ccBlendFunc){GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}];

Create CCTexture2D from a CCSprite with primitives being drawn in draw method

I have a CCSprite subclass. In the draw method, I am drawing some cocos2d primitives like lines and such. How can I create a CCTexture2D of the sprite? I can't use sprite.texture because that doesn't include the primitives I am drawing.
You can add sprite to object of CCRenderTexture2D and after this can draw sprite to texture.
look at the example
CCSprite *spr = nil;//your sprite
CCRenderTexture* renderTexture = [CCRenderTexture renderTextureWithWidth:spr.contentSize.width height:spr.contentSize.height];
spr.anchorPoint = ccp(0, 0);
spr.position = ccp(0, 0);
[renderTexture addChild:spr];
[renderTexture begin];
[spr draw]; // or [spr visit];
[renderTexture end];
CCTexture2D *result = renderTexture.sprite.texture;
Now you will have texture, that contains sprite and primitives, that it draws in draw method.
Hope, it will help you:)