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;
}
Related
I am beginner in cocos2d, I need init scene frame to it be less than device screen size as shown on the pinned picture, in center. In addition, scene must scale as shown on the picture. I've tried to do it as below, but unsuccessfully.
- (void)drawBackground
{
NSArray *assetPathParts = [self.dataProvider.backgroundValue componentsSeparatedByString:#"/"];
self.background = [CCSprite spriteWithImageNamed:assetPathParts.lastObject];
self.background.anchorPoint = ccp(0,0);
self.background.scale = 2;
self.background.scaleType = CCScaleTypeScaled;
[self addChild:self.background];
}
How can I fix it?
2 ways you can fit screen.
Method 1:
CGSize wSize = [[CCDirector sharedDirector] winSize];
CCSprite *background = [CCSprite spriteWithFile:#"Kundapura.png"];
background.position = ccp(wSize.width*0.5f, wSize.height*0.5f);
[self addChild:background];
background.scaleX = wSize.width/background.contentSize.width ;
background.scaleY = wSize.height/background.contentSize.height ;
Method 2:
CGSize wSize = [[CCDirector sharedDirector] winSize];
CCSprite *image = [CCSprite spriteWithFile:#"Kundapura.png"];
CCSprite *background = [CCSprite spriteWithTexture: image.texture rect:CGRectMake(0, 0, wSize.width, wSize.height)];
background.position = ccp(wSize.width*0.5f, wSize.height*0.5f);
[self addChild:background];
This fits your background to iPhone device size. Use runAction to scale on your needs.
I have managed to get drawing on top of a recently captured UIImage working, but it only works when the UIImageView covers the entire screen. It begins to lose accuracy the moment I start drawing away from the horizontal center. Any idea how I can get it to only work on the ImageView itself and have it remain accurate?
- (void)viewDidLoad
{
[super viewDidLoad];
float height = (self.view.frame.size.width * self.chosenImage.size.height)/self.chosenImage.size.width;
self.imageView.frame = CGRectMake(0, self.navigationController.navigationBar.frame.size.height, self.view.frame.size.width, height);
self.imageView.center = self.imageView.superview.center;
self.imageView.image = self.chosenImage;
}
- (UIImage *)drawLineFromPoint:(CGPoint)from_Point toPoint:(CGPoint)to_Point image:(UIImage *)image
{
CGSize sizeOf_Screen = self.imageView.frame.size;
UIGraphicsBeginImageContext(sizeOf_Screen);
CGContextRef current_Context = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0, 0, sizeOf_Screen.width, sizeOf_Screen.height)];
CGContextSetLineCap(current_Context, kCGLineCapRound);
CGContextSetLineWidth(current_Context, 1.0);
CGContextSetRGBStrokeColor(current_Context, 1, 0, 0, 1);
CGContextBeginPath(current_Context);
CGContextMoveToPoint(current_Context, from_Point.x, from_Point.y);
CGContextAddLineToPoint(current_Context, to_Point.x, to_Point.y);
CGContextStrokePath(current_Context);
UIImage *rect = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return rect;
}
- (void)touchesBegan:(NSSet *)_touches withEvent:(UIEvent *)_event
{
// retrieve the touch point
UITouch *_touch = [_touches anyObject];
CGPoint current_Point = [_touch locationInView:self.imageView];
// Its record the touch points to use as input to our line smoothing algorithm
self.drawnPoints = [NSMutableArray arrayWithObject:[NSValue valueWithCGPoint:current_Point]];
self.previousPoint = current_Point;
// we need to save the unmodified image to replace the jagged polylines with the smooth polylines
self.cleanImage = self.imageView.image;
}
- (void)touchesMoved:(NSSet *)_touches withEvent:(UIEvent *)_event
{
UITouch *_touch = [_touches anyObject];
CGPoint current_Point = [_touch locationInView:self.imageView];
[self.drawnPoints addObject:[NSValue valueWithCGPoint:current_Point]];
self.imageView.image = [self drawLineFromPoint:self.previousPoint toPoint:current_Point image:self.imageView.image];
self.previousPoint = current_Point;
}
EDIT: With these settings I have accuracy in the UIImageView, but the image blurs inwards as I am drawing.
When I edit [image drawInRect:CGRectMake(0, 0, sizeOf_Screen.width, sizeOf_Screen.height)]; to be [image drawInRect:CGRectMake(0, self.imageView.frame.origin.y, sizeOf_Screen.width, sizeOf_Screen.height)]; and try to draw, the image flies off out of the view when I try to draw.
I've tried tweaking the sizeOf_screen value and CGRectMake of image in the drawLineFromPoint method. I've also attempted to set the locationInView in both instances to self.imageView, but to no avail. It's very strange. Any ideas or code samples that might accomplish what I'm looking for? I can't seem to find anything.
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
I create background layer. For example, it has width x height 900 x 900. And view start location is 0,0:
background = [CCSprite spriteWithFile:#"back2.png"];
background.anchorPoint = ccp(0,0);
[self addChild:background];
I also have function to move view to point. It's work. But if i add start view not in 0;0 it cut background or jump to 0,0.
How can i do start view in center of background?
Hope the code below will help you. Also, I will strongly recommend you to learn and understand about anchorPoint in cocos2d. It will be handy, I guarantee that.
CGSize winSize = [CCDirector sharedDirector] winSize];
background = [CCSprite spriteWithFile:#"back2.png"];
background.anchorPoint = ccp(0.5,0.5);
background.position = ccp(winSize.width * 0.5, winSize.height * 0.5);
[self addChild:background];
how about set anchorPoint to ccp(0.5,0.5) and calculate your desired destination?
Hope this will help you....
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *background = [CCSprite spriteWithFile:#"bg.png"];
background.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:background z:-1];
I want that, when I roll the iPad, the image blinds up/down. Effect should be like
http://madrobby.github.com/scriptaculous/combination-effects-demo/ Blind Down demo.
How can I do that?
I tried Reflection example of Apple but I had performance issues since I should redraw image in every gyroscope action.
Here is the Code:
- (void)viewDidLoad
{
[super viewDidLoad];
tmp = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"galata2.jpg"]];
// Do any additional setup after loading the view, typically from a nib.
NSUInteger reflectionHeight = imageView1.bounds.size.height * 1;
imageView1 = [[UIImageView alloc] init];
imageView1.image = [UIImage imageNamed:#"galata1.jpg"];
[imageView1 sizeToFit];
[self.view addSubview:imageView1];
imageView2 = [[UIImageView alloc] init];
//UIImageView *tmp = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"galata2.jpg"]];
imageView2.image = [UIImage imageNamed:#"galata2.jpg"];
[imageView2 sizeToFit];
[self.view addSubview:imageView2];
motionManager = [[CMMotionManager alloc] init];
motionManager.gyroUpdateInterval = 1.0/10.0;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMDeviceMotion *motion, NSError *error){
[self performSelectorOnMainThread:#selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
}];
}
////
- (void)handleDeviceMotion:(CMDeviceMotion*)motion{
CMAttitude *attitude = motion.attitude;
int rotateAngle = abs((int)degrees(attitude.roll));
//CMRotationRate rotationRate = motion.rotationRate;
NSLog(#"rotation rate = [Pitch: %f, Roll: %d, Yaw: %f]", degrees(attitude.pitch), abs((int)degrees(attitude.roll)), degrees(attitude.yaw));
int section = (int)(rotateAngle / 30);
int x = rotateAngle % 30;
NSUInteger reflectionHeight = (1024/30)*x;
NSLog(#"[x = %d]", reflectionHeight);
imageView2.image = [self reflectedImage:tmp withHeight:reflectionHeight];
}
////
- (UIImage *)reflectedImage:(UIImageView *)fromImage withHeight:(NSUInteger)height
{
if(height == 0)
return nil;
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.bounds.size.width, fromImage.bounds.size.height);
// create a 2 bit CGImage containing a gradient that will be used for masking the
// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
CGImageRef gradientMaskImage = CreateGradientImage(1, kImageHeight);
// create an image by masking the bitmap of the mainView content with the gradient view
// then release the pre-masked content bitmap and the gradient bitmap
CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.bounds.size.width,height), gradientMaskImage);
CGImageRelease(gradientMaskImage);
// In order to grab the part of the image that we want to render, we move the context origin to the
// height of the image that we want to capture, then we flip the context so that the image draws upside down.
//CGContextTranslateCTM(mainViewContentContext, 0.0,0.0);
//CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);
// draw the image into the bitmap context
CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.bounds.size.width, fromImage.bounds.size.height), fromImage.image.CGImage);
// create CGImageRef of the main view bitmap content, and then release that bitmap context
CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
// convert the finished reflection image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:reflectionImage];
// image is retained by the property setting above, so we can release the original
CGImageRelease(reflectionImage);
return theImage;
}
One way to do this is to use another covering view that gradually changes height by animation;
If you have a view called theView that you want to cover, try something like this to reveal theView underneath a cover view:
UIView *coverView = [UIView alloc] initWithFrame:theView.frame];
coverView.backgroundcolor = [UIColor whiteColor];
[theView.superView addSubView:coverView]; // this covers theView, adding it to the same view that the view is contained in;
CGRect newFrame = theView.frame;
newFrame.size.height = 0;
newFrame.origin.y = theView.origin.y + theView.size.height;
[UIView animateWithDuration:1.5
delay: 0.0
options: UIViewAnimationOptionRepeat
animations:^{
coverView.frame = newFrame;
}
completion:nil
];
This should cover the view and then reveal it by changing the frame ov the cover, moving it down while changing the height.
I haven't tried the code, but this is one direction you can take to create the blind effect. I have used similar code often, and it is very easy to work with. Also, it doesn't require knowing core animation.