I'm using a draw function to highlight the score inserted into a table of highscores but i find that it makes my app lag when i try to leave the highscore layer. I'm still relatively new to cocos2d so I was wondering if there is a better way so it doesn't cause any lag. I find if i comment out this function that the isn't any lag. Heres my code:
- (void)draw {
[super draw];
if(currentScorePosition < 0 || currentScore==0) return;
float w = 320.0f;
float h = 20.0f;
float x = (320.0f - w) / 2.0f;
float y = 230.0f - currentScorePosition * h;
CGPoint vertices[4];
vertices[0] = ccp(x, y);
vertices[1] = ccp(x+w, y);
vertices[2] = ccp(x+w, y+h);
vertices[3] = ccp(x, y+h);
CCDrawNode *draw = [[[CCDrawNode alloc] init] autorelease];
[draw drawPolyWithVerts:vertices count:4 fillColor:ccc4f(0.5, 0.5, 0.8, 0.5) borderWidth:2.0 borderColor:ccc4f(0.0, 0.0, 0.0, 0.0)];
[self addChild:draw z:0 ];
}
You're creating a new CCDrawNode every frame. Over time this will slow down the game as it has to draw more and more draw nodes.
Solution: create one draw node up front and add it as child. Keep a reference to it in an ivar. Perform drawing with just this single draw node.
Note that the draw methods of CCDrawNode are still additive. If you want to draw just this one polygon and update it over time, then you'll have to call clear before drawing:
[theDrawNode clear];
[theDrawNode drawPolyWithVerts:vertices
count:4
fillColor:ccc4f(0.5, 0.5, 0.8, 0.5)
borderWidth:2.0
borderColor:ccc4f(0.0, 0.0, 0.0, 0.0)];
Another note: you can use the draw node outside the draw method. In fact if you run the code like you did, the draw node won't be drawn until the next frame and thus it'll always lag 1 frame behind. Use a scheduled update method to update the draw node.
Hi I`m working with CATransform3D.
Every time that I call the following method with the variable radian the UIImageView is rotated “radian * M_PI” from the previous angle.
I trying to go back to the original state. There is any way to do that?
I mind I want to sent a radian value i.e. 10 and that the view maintain these angle if is called more than once.
METHOD:
CATransform3D rotatedTransform = self.needleB.layer.transform;
rotatedTransform = CATransform3DRotate(rotatedTransform, radian * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
self.needleB.layer.transform = rotatedTransform;
self.needleB.layer.anchorPoint = CGPointMake(0.5, 0.9);
self.needleB.center = CGPointMake(160, 250);
Thanks !!
To undo all transforms, assign the transform property of your layer to CATransform3DIdentity.
I am trying to apply a texture for my brush but i'm really having a hard time figuring how it is done.
Here's the image of my output.
I used an UIImage that just follows the touch on the screen but when i swipe it faster the result is on the right side "W", and on the left side that's the result when i swipe it slow.
i tried using the CGContextMoveToPoint and CGContextAddLineToPoint i don't know how apply the texture.
Is it possible to use UIImage for the stroke texture?
Here's my code
UIImage * brushImageTexture = [UIImage imageNamed:#"brushImage.png"];
[brushImagetexture drawAtPoint:CGPointMake(touchCurrentPosition.x, touchVurrentPosition.y) blendMode:blendMode alpha:1.0f];
You need to manually draw the image at each point along the line from the previous point to the current point.
CGPoint vector = CGPointMake(currentPosition.x - lastPosition.x, currentPosition.y - lastPosition.y);
CGFloat distance = hypotf(vector.x, vector.y);
vector.x /= distance;
vector.y /= distance;
for (CGFloat i = 0; i < distance; i += 1.0f) {
CGPoint p = CGPointMake(lastPosition.x + i * vector.x, lastPosition.y + i * vector.y);
[brushImageTexture drawAtPoint:p blendMode:blendMode alpha:1.0f];
}
I'm animating a shrinking object. At any point the user can hit a button to get the current scale factor of the object. (I start by scaling the object up using a CGAffineTransformMakeScale, so the scale factor should be 1 when it reaches its original size). I'm just not sure how to retrieve the current scale factor from the animation UIImageView... Here's my code:
- (void)startShrink {
CGAffineTransform scaleFactor = CGAffineTransformMakeScale(kScaleX, kScaleY);
imageOutline.transform = scaleFactor;
CABasicAnimation *shrink = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
shrink.toValue = [NSNumber numberWithDouble:0.5];
shrink.duration = 2.0;
shrink.fillMode=kCAFillModeForwards;
shrink.removedOnCompletion=NO;
shrink.delegate = self;
[imageOutline.layer addAnimation:shrink forKey:#"shrink"];
}
I tried the following, but I'm not sure m12 is the value I should be retrieving from the transform. Or if in fact this is the right approach:
- (float)calculateScale {
CATransform3D scaleTransform = [(CALayer *)[imageOutline.layer presentationLayer] transform];
float scale = scaleTransform.m12;
NSLog(#"Scale: %g", scale);
return scale;
}
Any advice most appreciated :)
Thanks, Michael.
If you just scale your view uniformly on all axes then scale value should equal to m11 (and m22 as well).
I just ran a sample with your code copy-pasted - it seems that the following 2 lines are redundant:
CGAffineTransform scaleFactor = CGAffineTransformMakeScale(kScaleX, kScaleY);
imageOutline.transform = scaleFactor;
View immediately shrinks by half (I used 0.5 for scale values) and then shrinks twice more with animation
As the background for one of the views in my app, I'd like to draw a fairly simple rectangular border just inside its frame. This would essentially be a rectangular gradient: a black line around the frame, fading to white about 10-20 pixels in. Unfortunately, as far as I can tell, Core Graphics doesn't provide rectangular gradients (either with CGGradient or CGShading). So I'm wondering what the best approach would be.
Two that occur to me:
Draw a series of concentric rectangles, each subsequent one lighter in color, and inset by 1px on each side. I can't think of a simpler approach, but I have to do all of the gradient calculations myself, and it might be a lot of graphics operations.
Use CGGradient in linear mode, once for each side. But for this to work, I think I'd need to set up a trapezoidal clipping area for each side first, so that the gradients would be mitered at the corners.
Seems like there should be a way to use path stroking to do this, but it doesn't seem like there's a way to define a pattern that's oriented differently on each side.
I would go with option #2:
Use CGGradient in linear mode, once for each side. But for this to work, I think I'd need to set up a trapezoidal clipping area for each side first, so that the gradients would be mitered at the corners.
Using NSBezierPath to create the trapezoidal regions would be fairly straightforward, and you would only have to perform four drawing operations.
Here's the basic code for creating the left side trapezoidal region:
NSRect outer = [self bounds];
NSPoint outerPoint[4];
outerPoint[0] = NSMakePoint(0, 0);
outerPoint[1] = NSMakePoint(0, outer.size.height);
outerPoint[2] = NSMakePoint(outer.size.width, outer.size.height);
outerPoint[3] = NSMakePoint(outer.size.width, 0);
NSRect inner = NSInsetRect([self bounds], borderSize, borderSize);
NSPoint innerPoint[4];
innerPoint[0] = inner.origin;
innerPoint[1] = NSMakePoint(inner.origin.x,
inner.origin.y + inner.size.height);
innerPoint[2] = NSMakePoint(inner.origin.x + inner.size.width,
inner.origin.y + inner.size.height);
innerPoint[3] = NSMakePoint(inner.origin.x + inner.size.width,
inner.origin.y);
NSBezierPath leftSidePath = [[NSBezierPath bezierPath] retain];
[leftSidePath moveToPoint:outerPoint[0]];
[leftSidePath lineToPoint:outerPoint[1]];
[leftSidePath lineToPoint:innerPoint[1]];
[leftSidePath lineToPoint:innerPoint[0]];
[leftSidePath lineToPoint:outerPoint[0]];
// ... etc.
[leftSidePath release];
something like this could also work.
basically: instead of using clipping paths, simply use blendmode.
and in this example the gradient is cached in a CGLayer.
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx,self.bounds);
CGFloat w = self.bounds.size.width;
CGFloat h = self.bounds.size.height;
CGFloat dh = (w-h)/2;
CGLayerRef l = CGLayerCreateWithContext(ctx,CGSizeMake(h,48.0f),NULL);
CGContextRef lctx = CGLayerGetContext(l);
float comp[] = { .2,.5,1.0,1.0,1.0,1.0,1.0,1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(cspace, comp, NULL, 2);
CGContextDrawLinearGradient(lctx, gradient,CGPointMake(0,0),CGPointMake(0,48), 0);
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx,kCGBlendModeDarken);
for(int n=1;n<5;n++)
{
CGContextTranslateCTM(ctx,w/2.0,h/2.0);
CGContextRotateCTM(ctx, M_PI_2);
CGContextTranslateCTM(ctx,-w/2.0,-h/2.0);
CGContextDrawLayerAtPoint(ctx,CGPointMake((n%2)*dh,(n%2)*-dh),l);
}
CGContextRestoreGState(ctx);