I'm trying to draw squiggle in Set Card Game. The output is not even close to what I want. How should I improve the drawing?
..
#define SQUIGGLE_CURVE_FACTOR 0.5
- (UIBezierPath *)drawSquiggleAtPoint:(CGPoint)point
{
CGFloat dx = self.bounds.size.width * SYMBOL_WIDTH_RATIO / 2;
CGFloat dy = self.bounds.size.height * SYMBOL_HEIGHT_RATIO / 2;
UIBezierPath *path = [[UIBezierPath alloc] init];
CGFloat dsqx = dx * SQUIGGLE_CURVE_FACTOR;
CGFloat dsqy = dy * SQUIGGLE_CURVE_FACTOR;
[path moveToPoint:CGPointMake(point.x - dx, point.y)];
[path addQuadCurveToPoint:CGPointMake(point.x - dsqx, point.y + dsqy) controlPoint:CGPointMake(point.x - dx, point.y + dy + dsqy)];
[path addCurveToPoint:CGPointMake(point.x + dx, point.y) controlPoint1:point controlPoint2:CGPointMake(point.x + dx, point.y + dy * 2)];
[path addQuadCurveToPoint:CGPointMake(point.x + dsqx, point.y - dsqy) controlPoint:CGPointMake(point.x + dx, point.y - dy - dsqy)];
[path addCurveToPoint:CGPointMake(point.x - dx, point.y) controlPoint1:point controlPoint2:CGPointMake(point.x - dx, point.y - dy * 2)];
return path;
}
- (UIBezierPath *)drawSquiggleAtPoint:(CGPoint)point
{
CGSize size = CGSizeMake(self.bounds.size.width * SYMBOL_WIDTH_RATIO, self.bounds.size.height * SYMBOL_HEIGHT_RATIO);
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(104, 15)];
[path addCurveToPoint:CGPointMake(63, 54) controlPoint1:CGPointMake(112.4, 36.9) controlPoint2:CGPointMake(89.7, 60.8)];
[path addCurveToPoint:CGPointMake(27, 53) controlPoint1:CGPointMake(52.3, 51.3) controlPoint2:CGPointMake(42.2, 42)];
[path addCurveToPoint:CGPointMake(5, 40) controlPoint1:CGPointMake(9.6, 65.6) controlPoint2:CGPointMake(5.4, 58.3)];
[path addCurveToPoint:CGPointMake(36, 12) controlPoint1:CGPointMake(4.6, 22) controlPoint2:CGPointMake(19.1, 9.7)];
[path addCurveToPoint:CGPointMake(89, 14) controlPoint1:CGPointMake(59.2, 15.2) controlPoint2:CGPointMake(61.9, 31.5)];
[path addCurveToPoint:CGPointMake(104, 15) controlPoint1:CGPointMake(95.3, 10) controlPoint2:CGPointMake(100.9, 6.9)];
[path applyTransform:CGAffineTransformMakeScale(0.9524*size.width/100, 0.9524*size.height/50)];
[path applyTransform:CGAffineTransformMakeTranslation(point.x - size.width/2 - 3 * size.width /100, point.y - size.height/2 - 8 * size.height/50)];
return path;
}
Here's some code that generates a fairly decent rendition of a squiggle
- (void)drawSquiggle
{
CGContextRef context = UIGraphicsGetCurrentContext();
// translate and scale the squiggle
CGContextSaveGState( context );
CGContextTranslateCTM( context, 0, 100 );
CGContextScaleCTM( context, 2.0, 2.0 );
// create the squiggle path
CGContextMoveToPoint( context, 104.0, 15.0 );
CGContextAddCurveToPoint( context, 112.4 , 36.9, 89.7, 60.8, 63.0, 54.0 );
CGContextAddCurveToPoint( context, 52.3 , 51.3, 42.2, 42.0, 27.0, 53.0 );
CGContextAddCurveToPoint( context, 9.6 , 65.6, 5.4, 58.3, 5.0, 40.0 );
CGContextAddCurveToPoint( context, 4.6 , 22.0, 19.1, 9.7, 36.0, 12.0 );
CGContextAddCurveToPoint( context, 59.2 , 15.2, 61.9, 31.5, 89.0, 14.0 );
CGContextAddCurveToPoint( context, 95.3 , 10.0, 100.9, 6.9, 104.0, 15.0 );
// draw the squiggle
CGContextSetLineCap( context, kCGLineCapRound );
CGContextSetLineWidth( context, 2.0 );
CGContextStrokePath( context );
// restore the graphics state
CGContextRestoreGState( context );
}
This is what it produces
Scaling and Translating the Squiggle
There are two ways to change the size and position of the squiggle.
One way is to change all the number that are passed to the CGContextAddCurveToPoint
function. For example, if you adjust the x
values with x = (x-3) * 0.9524
and adjust all the y
values with y = (y-8) * 0.9524
, then the squiggle fits nicely into a 100x50 rectangle.
The other way is to change the affine transform of your drawing context before drawing the squiggle. You can apply translation and scale transformations to place/size the squiggle wherever you want it. Note that the order in which the transformations are applied is important. Also, you can save and restore the graphics state so that the transformations are only applied to the squiggle, and not other items that you are drawing. The code above moves the squiggle 100 pixels down, and makes it twice as big.
My squiggle looks like this. Unfortunately I can't insert image directly
This is my method for this. And squiggle scale with bounds of CGrect
typedef enum : NSUInteger
{
solidShading=1,
stripedShading=2,
openShading=3,
numShading=4,
} cardShading;
-(void)drawSquiggleInBounds:(CGRect)bounds withColor:(UIColor *)color withShading:(cardShading)shading
{
if (shading > 3) {return;}
UIBezierPath *path = [[UIBezierPath alloc] init];
[color setStroke];
path.lineWidth = 2;
[path moveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.05, bounds.origin.y + bounds.size.height*0.40)];
[path addCurveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.35, bounds.origin.y + bounds.size.height*0.25)
controlPoint1:CGPointMake(bounds.origin.x + bounds.size.width*0.09, bounds.origin.y + bounds.size.height*0.15)
controlPoint2:CGPointMake(bounds.origin.x + bounds.size.width*0.18, bounds.origin.y + bounds.size.height*0.10)];
[path addCurveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.75, bounds.origin.y + bounds.size.height*0.30)
controlPoint1:CGPointMake(bounds.origin.x + bounds.size.width*0.40, bounds.origin.y + bounds.size.height*0.30)
controlPoint2:CGPointMake(bounds.origin.x + bounds.size.width*0.60, bounds.origin.y + bounds.size.height*0.45)];
[path addCurveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.97, bounds.origin.y + bounds.size.height*0.35)
controlPoint1:CGPointMake(bounds.origin.x + bounds.size.width*0.87, bounds.origin.y + bounds.size.height*0.15)
controlPoint2:CGPointMake(bounds.origin.x + bounds.size.width*0.98, bounds.origin.y + bounds.size.height*0.00)];
[path addCurveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.45, bounds.origin.y + bounds.size.height*0.85)
controlPoint1:CGPointMake(bounds.origin.x + bounds.size.width*0.95, bounds.origin.y + bounds.size.height*1.10)
controlPoint2:CGPointMake(bounds.origin.x + bounds.size.width*0.50, bounds.origin.y + bounds.size.height*0.95)];
[path addCurveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.25, bounds.origin.y + bounds.size.height*0.85)
controlPoint1:CGPointMake(bounds.origin.x + bounds.size.width*0.40, bounds.origin.y + bounds.size.height*0.80)
controlPoint2:CGPointMake(bounds.origin.x + bounds.size.width*0.35, bounds.origin.y + bounds.size.height*0.75)];
[path addCurveToPoint:CGPointMake(bounds.origin.x + bounds.size.width*0.05, bounds.origin.y + bounds.size.height*0.40)
controlPoint1:CGPointMake(bounds.origin.x + bounds.size.width*0.00, bounds.origin.y + bounds.size.height*1.10)
controlPoint2:CGPointMake(bounds.origin.x + bounds.size.width*0.005, bounds.origin.y + bounds.size.height*0.60)];
[path closePath];
[self drawShading:shading withColor:color inPath:path];
[path stroke];
}
Also my methods for shading:
#define DISTANCE_BETWEEN_STRIPES 4
-(void)drawShading:(cardShading)shading withColor:(UIColor *)color inPath:(UIBezierPath *)beziePath
{
switch (shading)
{
case 1:
[color setFill];
[beziePath fill];
break;
case 2:
[self drawStripedShadingForPath:beziePath];
break;
default:
break;
}
}
-(void)drawStripedShadingForPath:(UIBezierPath *)pathOfSymbol
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGRect bounds = [pathOfSymbol bounds];
UIBezierPath *path = [[UIBezierPath alloc] init];
for (int i = 0; i < bounds.size.width; i += DISTANCE_BETWEEN_STRIPES)
{
[path moveToPoint:CGPointMake(bounds.origin.x + i, bounds.origin.y)];
[path addLineToPoint:CGPointMake(bounds.origin.x + i, bounds.origin.y + bounds.size.height)];
}
[pathOfSymbol addClip];
[path stroke];
CGContextRestoreGState(UIGraphicsGetCurrentContext());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With