I'm trying to add frosted glass effect for nodes in my game. For example http://bit.ly/1vNMvAG
What is the right way to do that?
I must be missing something, as I would just stay with SpriteKit, as suggested in original comments, but maybe I'll get schooled and learn something new. :-) EDIT, simplified everything, and now you can just move the crop mask by setting it as a property and then changing its position dynamically as you go. Obviously you could jazz it up with various sprite layers.
SKSpriteNode *bgImage = [SKSpriteNode spriteNodeWithImageNamed:#"bgImage.png"];
bgImage.anchorPoint = CGPointZero;
[self addChild:bgImage];
cropMaskNode = [SKSpriteNode spriteNodeWithImageNamed:#"clippingImage.png"];
SKCropNode *cropNode = [SKCropNode node];
SKSpriteNode *bgInsideOfCrop = [SKSpriteNode spriteNodeWithImageNamed:#"bgImage.png"];
bgInsideOfCrop.anchorPoint = CGPointZero;
SKEffectNode *effectNode = [SKEffectNode node];
effectNode.filter = [self blurFilter];
effectNode.shouldEnableEffects = YES;
effectNode.shouldCenterFilter = YES;
effectNode.shouldRasterize = YES;
[self addChild: cropNode];
[effectNode addChild:bgInsideOfCrop];
[cropNode addChild:effectNode];
cropNode.maskNode = cropMaskNode;
this effect is only available in ios 7 to my knowlwdge. Engin Kurutepe has posted it on Github
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
if (newSuperview == nil) {
return;
}
UIGraphicsBeginImageContextWithOptions(newSuperview.bounds.size, YES, 0.0);
[newSuperview drawViewHierarchyInRect:newSuperview.bounds afterScreenUpdates:YES];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIImage *croppedImage = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(img.CGImage, self.frame)];
UIGraphicsEndImageContext();
self.backgroundImage = [croppedImage applyBlurWithRadius:11
tintColor:[UIColor colorWithWhite:1 alpha:0.3]
saturationDeltaFactor:1.8
maskImage:nil];
}
Code Sample Ref
Related
I need to make UIImageView in circle radius, I am using this block of code for this taks.
-(void)viewWillAppear:(BOOL)animated {
[self performSelector:#selector(setStyleCircleForImage:) withObject:_imageview afterDelay:0];
[super viewWillAppear:YES];
}
-(void) setStyleCircleForImage:(UIImageView *)imgView {
imgView.layer.cornerRadius = _imageview.frame.size.height / 2.0;
imgView.clipsToBounds = YES;
}
Its working perfect in iOS 5 but when test in other device it shape is change I don't know why it happens. Please make some help.
Better to use mask to make circle like this function
- (void)viewDidLoad {
[super viewDidLoad];
[self makeCircleImage: _imageview];
}
-(void)makeCircleImage:(UIImageView *)img{
CGFloat img_width = img.bounds.size.width;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(img_width,img_width), NO, 0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(c, [UIColor blackColor].CGColor);
CGContextFillEllipseInRect(c, CGRectMake(0,0,img_width,img_width));
UIImage* maskim = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CALayer* mask = [CALayer new];
mask.frame = CGRectMake(0,0,img_width,img_width);
mask.contents = (id)maskim.CGImage;
img.layer.mask = mask;
}
Try This
yourImageView.layer.cornerRadius = yourImageView.frame.size.width/2;
yourImageView.layer.masksToBounds = YES;
First give equal width and equal height for UIImageView, then make use it
imgView.layer.cornerRadius = imgView.frame.size.height / 2.0;
imgView.layer.masksToBounds = YES;
Ive added a SpriteKit particle to my app - The skView has been added to an existing image view (myImageView). All works well but the skScenne cannot be set to clear colour to show myImage behind the emitter. You can change the colour but not to clear colour ?? `
SKView *skView = [[SKView alloc] initWithFrame:CGRectMake(0.0, 0.0, 768, 1024)];
[myImageView addSubview:skView];
SKScene *skScene = [SKScene sceneWithSize:skView.frame.size];
skScene.scaleMode = SKSceneScaleModeAspectFill;
skScene.backgroundColor = [UIColor clearColor];
SKEmitterNode *emitter = [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:#"MyParticle" ofType:#"sks"]];
emitter.position = CGPointMake(400,0);
[skScene addChild:emitter];
[skView presentScene:skScene];
[self.view addSubview:myImageView];
Unfortunately you can't make an SKView transparent in iOS 7. In iOS 8 it works by using:
skView.allowsTransparency = YES;
skScene.backgroundColor = [UIColor clearColor];
In iOS 7 you can add a large spriteView that is as big as your skView as background and set your myImage as texture.
I suggest you avoid setting the color of your SKScene to [UIColor clearColor] for performance reasons (use opaque views whenever possible). Instead, you can create an SKSpriteNode and add it to your scene as the background...
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:#"image"];
background.size = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
// Bottom/left of your image
background.anchorPoint = CGPointZero;
background.position = CGPointZero;
// Make sure the background is behind other nodes in the scene
background.zPosition = -100;
[self addChild:background];
Since the background is added to the SKScene, it is automatically removed/released when you transition to a new scene.
When trying to add a SKSpriteNode at position 0,0 in my scenes initWithSize method, it is offset on the x axis. This is due to the positions still holding values for "portrait" orientation.
I've followed the advice in the following article by adding my scene in the "viewWillLayoutSubviews" method of the view controller, but I'm still experiencing an offset issue.
Here is the initWithSize method:
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.userInteractionEnabled = YES;
self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.physicsWorld.gravity = CGVectorMake(0.0f, -1.0f);
self.physicsWorld.contactDelegate = self;
SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(size.width,20)];
n1.position = CGPointMake(0, 0);
n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:n1.size];
n1.physicsBody.contactTestBitMask = catCategory;
n1.physicsBody.dynamic = NO;
n1.physicsBody.categoryBitMask = floorCategory;
[self addChild:n1];
}
return self;
}
Following Ray Wanderlich's article I was able to achieve success by using an offset, and applying it to the position when adding the sprite, but there HAS to be a better way, right?
-(id)initWithSize:(CGSize)size {
float center = 240.0;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && IS_WIDESCREEN) {
center = 284.0;
}
if (self = [super initWithSize:size]) {
self.userInteractionEnabled = YES;
self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.physicsWorld.gravity = CGVectorMake(0.0f, -1.0f);
self.physicsWorld.contactDelegate = self;
SKSpriteNode *n1 = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(size.width,20)];
n1.position = CGPointMake(center, 0);
n1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:n1.size];
n1.physicsBody.contactTestBitMask = catCategory;
n1.physicsBody.dynamic = NO;
n1.physicsBody.categoryBitMask = floorCategory;
[self addChild:n1];
}
return self;
}
I'd like to find a comprehensive solution that doesn't rely on a hard-coded offset, and will work with landscape orientation regardless of if its an iPad or iPhone.
Thanks.
Is there an efficient way to do this? currently i use
[renderTexture begin];
[self.view visit];
[renderTexture end];
but app jitters because of it.
I read I can copy contents of frame buffer for this. Is that true? Can someone guide me how to do that.
I used a method that worked for me. It does a screenshot, and then selects a frame of it. You can change it, so it takes a screenshot from the whole screen.
Here's the code.
-(UIImage*) takeScreenShot
{
[CCDirector sharedDirector].nextDeltaTimeZero = YES;
CGSize winSize = [CCDirector sharedDirector].winSize;
//aux layer to make screenshot
CCLayerColor* blankLayer = [CCLayerColor layerWithColor:ccc4(255, 255, 255, 0) width:winSize.width height:winSize.height];
blankLayer.position = ccp(winSize.width/2, winSize.height/2);
CCRenderTexture* rtx = [CCRenderTexture renderTextureWithWidth:winSize.width height:winSize.height];
//this part is the same as yours
[rtx begin];
[blankLayer visit];
[[[CCDirector sharedDirector] runningScene] visit];
[rtx end];
//this part makes a rectangle from the screenshot with size.width and 200 height. Change it
UIImage *tempImage =[rtx getUIImage];
CGRect imageBoundary = CGRectMake(0, 0, winSize.width, 200);
UIGraphicsBeginImageContext(imageBoundary.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// translated rectangle for drawing sub image
CGRect drawRect = CGRectMake(-imageBoundary.origin.x, -imageBoundary.origin.y, tempImage.size.width, tempImage.size.height);
// clip to the bounds of the image context
CGContextClipToRect(context, CGRectMake(0, 0, imageBoundary.size.width, imageBoundary.size.height));
// draw image
[tempImage drawInRect:drawRect];
UIImage* subImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return subImage;
//and there you have an UIImage
}
This code works well when making screenshots of a part of the screen. Maybe you can try deleting the code part where it makes a temp image with a CGRect. But I recommend you to change the values like this:
CGRect imageBoundary = CGRectMake(0, 0, winSize.width, winSize.height);
So it will make a full screenshot.
You can use "Kamcord" framework, with this framework you can take screenshots as well as you can also record video of your game play and you can replay them..
I use it. This is for Cocos2d v3. Weak needs for memory returning. Because there're some problems with it. If you'll remove weak, you memory usage will increase every time you call this method. I think it's best way to do.
+(UIImage *)screenshot
{
[CCDirector sharedDirector].view.alpha = 1.0;
[CCDirector sharedDirector].nextDeltaTimeZero = YES;
CGSize winSize = [[CCDirector sharedDirector] viewSize];
CCRenderTexture* renTxture = [CCRenderTexture renderTextureWithWidth:winSize.width
height:winSize.height
pixelFormat:CCTexturePixelFormat_RGB565];
[renTxture begin];
MainScene* tempScene = (MainScene *)[[CCDirector sharedDirector] runningScene];
MainScene* __weak scene = tempScene;
[scene visit];
[renTxture end];
UIImage *tempImage = [renTxture getUIImage];
UIImage * __weak image = tempImage;
return image;
}
I have an Objective-C project. In the project, I want to use some CCAction on the image(UIImage). So, I think I need to change all UIImage into CCSprite.
I have a function which add image to view for all images in the project:
UIImage* firstImage = [imageArray objectAtIndex:0];
UIImageView* imageView = [[UIImageView alloc] initWithImage:firstImage];
[targetView addSubview:imageView];
[imageView release];
return imageView;
At this point, I don't know how to do addSubview on CCSprite. As I know, in cocos2d, only one CCGLView is using.
Is there any hints? thank you.
Some useful Notes for you:
« You can add one CCSprite to other CCSprite by using addChild method.
« Creating CCSprite from UIImage:
CCTexture2D *tex = [[[CCTexture2D alloc] initWithImage:uiImage] autorelease];
CCSprite *sprite = [CCSprite spriteWithTexture:tex];
« Creating UIImage from CCSprite:
- (UIImage *) imageFromSprite :(CCSprite *)sprite
{
int tx = sprite.contentSize.width;
int ty = sprite.contentSize.height;
CCRenderTexture *renderer = [CCRenderTexture renderTextureWithWidth:tx height:ty];
sprite.anchorPoint = CGPointZero;
[renderer begin];
[sprite visit];
[renderer end];
return [renderer getUIImage];
}
//call syntax
CCSprite *sprite = (CCSprite *)node;
UIImage *p = [self imageFromSprite:sprite]