「まる、さんかく、しかく」を引っぱるとビョーンとのびます。
ゆびを離すと、飛んでいくので、同じ形の的に当ててみましょう。
というようなゲームのサンプルを作ってみました。

環境
XcodeのiOS6 iPhone Simulatorで動かしています。

ポイント
touchesMovedで引っぱった方向にあわせて、
transformで図形を回転させ、UIViewのcenterからの距離
y方向を調整することで、引っぱった感じを出してみました。



サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    UIView *selected;

    NSTimer *timer;

    NSTimer *checkTimer;

    CGPoint points[3];

    NSMutableArray *holes;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    self.view.backgroundColor = [self colors:0];

    [self createUI];

    

    [self startCheck];

}

– (UIColor*)colors:(int)i

{

    float rgb[5][3] = {

        {   9.0/255.0,  33.0/255.0,  64.0/255.0}

        ,{242.0/255.0, 199.0/255.0, 119.0/255.0}

        ,{242.0/255.0,  71.0/255.0,  56.0/255.0}

        ,{7.0/255.0,  242.0/255.0,  0.0/255.0}

        ,{  2.0/255.0,  73.0/255.0,  89.0/255.0}

    };

    return [UIColor colorWithRed:rgb[i][0] green:rgb[i][1] blue:rgb[i][2] alpha:1.0];

}

– (void)createUI

{

    

    // create holes

    holes = [[NSMutableArray alloc] init];

    for (int i=0; i<3; i++) {

        UIView *h = [self createRandomFigure];

        h.center = CGPointMake(i*100 + 60, 60);

        [self.view addSubview:h];

        h.backgroundColor = [UIColor clearColor];

        CAShapeLayer *l = [h.layer.sublayers objectAtIndex:0];

        l.fillColor = [UIColor whiteColor].CGColor;

        [holes addObject:h];

    }

    

    // create figure

    UIView *v = [self createRandomFigure];

    v.center = self.view.center;

    [self.view addSubview:v];

}

– (UIView*)createRandomFigure

{

    int rand = arc4random() % 3;

    

    UIView *figure = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

    figure.backgroundColor = [UIColor clearColor];

    

    UIBezierPath *path = [[UIBezierPath alloc] init];

    

    switch (rand) {

        case 0: // triangle

            figure.tag = 1;

            [path moveToPoint:CGPointMake(0, 40)];

            [path addLineToPoint:CGPointMake(20, 0)];

            [path addLineToPoint:CGPointMake(40, 40)];

            break;

            

        case 1: // rect

            figure.tag = 2;

            [path appendPath:[UIBezierPath bezierPathWithRect:figure.bounds]];

            break;

            

        case 2: // circle

            figure.tag = 3;

            [path appendPath:[UIBezierPath bezierPathWithOvalInRect:figure.bounds]];

            break;

            

        default:

            break;

    }

    

    CAShapeLayer *sl = [[CAShapeLayer alloc] initWithLayer:figure.layer];

    sl.path = path.CGPath;

    sl.fillColor = [self colors:figure.tag].CGColor;

    [figure.layer addSublayer:sl];

    

    return figure;

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    if (selected) {

        [self touchesCancelled:touches withEvent:event];

        return;

    }

    

    CGPoint p = [[touches anyObject] locationInView:self.view];

    

    for (UIView *v in self.view.subviews) {

        if (CGRectContainsPoint(v.frame, p)) {

            selected = v;

        }

    }

}

– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

    if (!selected) {

        return;

    }

    

    CGPoint p = [[touches anyObject] locationInView:selected];

    CGPoint center = CGPointMake(20, 20);

    

    float distance = hypot(p.x – center.x, p.y – center.y);

    points[0] = CGPointMake(center.x, center.y – distance);

    points[1] = CGPointMake(0, 40);

    points[2] = CGPointMake(40, 40);

    

    UIBezierPath *path = [[UIBezierPath alloc] init];

    switch (selected.tag) {

        case 1:

            [path moveToPoint:points[0]];

            [path addLineToPoint:points[1]];

            [path addLineToPoint:points[2]];

            break;

            

        case 2:

            [path moveToPoint:CGPointMake(points[0].x + 10, points[0].y)];

            [path addLineToPoint:CGPointMake(points[0].x10, points[0].y)];

            [path addLineToPoint:points[1]];

            [path addLineToPoint:points[2]];

            break;

            

        case 3:

            [path addArcWithCenter:points[0] radius:10 startAngle:M_PI endAngle:0 clockwise:YES];

            [path addArcWithCenter:CGPointMake(20, 20) radius:20 startAngle:0 endAngle:M_PI clockwise:YES];

            break;

        default:

            break;

    }

    

    CAShapeLayer *sl = [selected.layer.sublayers lastObject];

    sl.path = path.CGPath;

    

    

    float angle = atan2f(p.y – center.y, p.x – center.x) + M_PI/2.0;

    selected.transform = CGAffineTransformRotate(selected.transform, angle);

}

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

    if (!selected) {

        return;

    }

    

    [self start:selected];

    

    selected.userInteractionEnabled = NO;

    

    CGPoint p = [[touches anyObject] locationInView:self.view];

    CGPoint velocity = CGPointMake(selected.center.x – p.x, selected.center.y – p.y);

    

    [UIView animateWithDuration:1.0 animations:^{

        selected.center = CGPointMake(velocity.x * 5 + selected.center.x, velocity.y * 5 + selected.center.y);

    } completion:^(BOOL finished) {

        if (finished) {

            [selected removeFromSuperview];

            selected = nil;

        }

        UIView *v = [self createRandomFigure];

        v.center = self.view.center;

        [self.view addSubview:v];

    }];

}

– (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

{

    [selected removeFromSuperview];

    selected = nil;

    [super touchesCancelled:touches withEvent:event];

}

– (void)start:(UIView*)v

{

    timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:v repeats:YES];

}

– (void)tick:(NSTimer*)sender

{    

    float newY = points[0].y – (points[0].y20) * 0.1;

    points[0] = CGPointMake(20, newY);

    

    UIBezierPath *path = [[UIBezierPath alloc] init];

    float w;

    switch (selected.tag) {

        case 1:

            [path moveToPoint:points[0]];

            [path addLineToPoint:points[1]];

            [path addLineToPoint:points[2]];

            break;

            

        case 2:

            w = 10 + 10 * (300 + points[0].y) / 300.0;

            [path moveToPoint:CGPointMake(points[0].x + w, points[0].y)];

            [path addLineToPoint:CGPointMake(points[0].x – w, points[0].y)];

            [path addLineToPoint:points[1]];

            [path addLineToPoint:points[2]];

            break;

            

        case 3:

            w = 10 + 10 * (100 + points[0].y) / 100.0;

            [path addArcWithCenter:CGPointMake(points[0].x, points[0].y + 20) radius:w startAngle:M_PI endAngle:0 clockwise:YES];

            [path addArcWithCenter:CGPointMake(20, 20) radius:20 startAngle:0 endAngle:M_PI clockwise:YES];

            break;

            

        default:

            break;

    }

    

    CAShapeLayer *sl = [selected.layer.sublayers lastObject];

    sl.path = path.CGPath;

    

    if (points[0].y >= 0.1) {

        [timer invalidate];

    }

}

– (void)startCheck

{

    checkTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(check) userInfo:nil repeats:YES];

}

– (void)check

{

    // goal check

    [self performSelectorOnMainThread:@selector(next) withObject:nil waitUntilDone:NO];

    

    static BOOL checking;

    if(selected && !checking) {

        for (UIView *v in holes) {

            CGRect r =  [selected.layer.presentationLayer frame];

            

            if (CGRectIntersectsRect(v.frame, r)) {

                checking = TRUE;

                

                [selected.layer removeAllAnimations];

                selected.frame = r;

                

                if (v.tag == selected.tag) {

                    // collect figure

                    [UIView animateWithDuration:0.5 animations:^{

                        selected.transform = CGAffineTransformIdentity;

                    } completion:^(BOOL finished) {

                        [UIView animateWithDuration:0.2 animations:^{

                            selected.frame = v.frame;

                            selected = nil;

                            [holes removeObject:v];

                        }];

                        checking = FALSE;

                    }];

                } else {

                    // different figure

                    [UIView animateWithDuration:0.5 animations:^{

                        selected.center = CGPointMake(500, 300);

                    } completion:^(BOOL finished) {

                        [selected removeFromSuperview];

                        selected = nil;

                        checking = FALSE;

                    }];

                }

            }

        }

    }

}

– (void)next

{

    if ([holes count] == 0) {

        // next

        for (UIView *v in self.view.subviews) {

            v.tag = 10;

            [UIView animateWithDuration:0.5 animations:^{

                v.alpha = 0.3;

            } completion:^(BOOL finished) {

                [v removeFromSuperview];

            }];

        }

        

        [self createUI];

        for (UIView *v in self.view.subviews) {

            if (v.tag != 10) {

                v.center = CGPointMake(v.center.x + 320, v.center.y);

                [UIView animateWithDuration:0.5 animations:^{

                    v.center = CGPointMake(v.center.x320, v.center.y);

                }];

            }

        }

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end