棒人間 Stick Personに背泳ぎをさせるサンプルです。
今日は、東京の3月にしては暑かったのでプールものです。
最高気温は25度らしいです。
サンプルアプリは、指でタッチしたコース上を、stick person が
手足をバタバタさせながら、プールを泳いでいくように
作ってみました。

環境

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

ポイント

手のストロークには、楕円の式、x = a * cos, y = b * cos を利用、
手を下から上に上げるときは、円軌道ではなく
直線になるように、if 条件で制御を追加しています。




サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface StickPerson : UIView

{

    CGPoint head, neck, hip;

    CGPoint sholderR, sholderL, elbowR, elbowL, handR, handL;

    CGPoint kneeR, kneeL, footR, footL;

    

    NSTimer *timer;

    float lastTime;

}

– (void)swim;

@end

@implementation StickPerson

– (id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        self.backgroundColor = [UIColor clearColor];

        CGSize size = self.bounds.size;

        head = CGPointMake(size.width*0.5, size.height*0.2);

        neck = CGPointMake(size.width*0.5, size.height*0.3);

        hip = CGPointMake(size.width*0.5, size.height*0.6);

        

        sholderR = CGPointMake(size.width*0.5, size.height*0.3);

        elbowR = CGPointMake(size.width*0.4, size.height*0.45);

        handR = CGPointMake(size.width*0.3, size.height*0.6);

        kneeR = CGPointMake(size.width*0.45, size.height*0.85);

        footR = CGPointMake(size.width*0.45, size.height);

        

        sholderL = CGPointMake(size.width*0.5, size.height*0.3);

        elbowL = CGPointMake(size.width*0.6, size.height*0.45);

        handL = CGPointMake(size.width*0.7, size.height*0.6);

        kneeL = CGPointMake(size.width*0.55, size.height*0.85);

        footL = CGPointMake(size.width*0.55, size.height);

    }

    return self;

}

– (void)swim

{

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

}

– (void)turnHand:(NSTimer*)sender

{

    lastTime += 4*sender.timeInterval;

    CGSize size = self.bounds.size;

    

    {

        CGPoint c = CGPointMake(size.width*0.45, size.height*0.3);

        float x = size.width*0.2 * 0.4 * cos(-lastTime) + c.x;

        if (x > size.width*0.45) {

            x = size.width*0.45;

        }

        float y = size.height*0.2 * 0.5 * sin(-lastTime) + c.y;

        elbowR = CGPointMake(x, y);

    }

    {

        CGPoint c = CGPointMake(size.width*0.45, size.height*0.3);

        float x = size.width*0.2 * cos(-lastTime) + c.x;

        if (x > size.width*0.45) {

            x = size.width*0.45;

        }

        float y = size.height*0.25 * sin(-lastTime) + c.y;

        handR = CGPointMake(x, y);

    }

    {

        CGPoint c = CGPointMake(size.width*0.55, size.height*0.3);

        float x = size.width*0.2 * 0.4 * cos(lastTime) + c.x;

        if (x < size.width*0.55) {

            x = size.width*0.55;

        }

        float y = size.height*0.2 * 0.5 * sin(lastTime) + c.y;

        elbowL = CGPointMake(x, y);

    }

    {

        CGPoint c = CGPointMake(size.width*0.55, size.height*0.3);

        float x = size.width*0.2 * cos(lastTime) + c.x;

        if (x < size.width*0.55) {

            x = size.width*0.55;

        }

        float y = size.height*0.25 * sin(lastTime) + c.y;

        handL = CGPointMake(x, y);

    }

    {

        CGPoint c = kneeR;

        float y = size.height*0.3 * sin(4*lastTime) + c.y;

        if (y < size.height*0.75) {

            y = size.height*0.75;

        }

        footR = CGPointMake(c.x, y);

    }

    {

        CGPoint c = kneeL;

        float y = size.height*0.3 * sin(4*lastTime + M_PI) + c.y;

        if (y < size.height*0.75) {

            y = size.height*0.75;

        }

        footL = CGPointMake(c.x, y);

    }

    

    [self setNeedsDisplay];

}

– (void)drawRect:(CGRect)rect

{

    CGSize size = self.bounds.size;

    

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    

    CGContextSetLineWidth(ctx, size.width*0.07);

    CGContextSetLineCap(ctx, kCGLineCapRound);

    CGContextSetLineJoin(ctx, kCGLineJoinMiter);

    CGContextMoveToPoint(ctx, head.x, head.y);

    CGContextAddArc(ctx, head.x, head.y, size.width*0.1, 0, 2.0*M_PI, NO);

    CGContextFillPath(ctx);

    

    [[UIColor whiteColor] setFill];

    CGContextAddArc(ctx, head.x + size.width*0.04, head.y, size.width*0.02, 0, 2.0*M_PI, NO);

    CGContextAddArc(ctx, head.x – size.width*0.04, head.y, size.width*0.02, 0, 2.0*M_PI, NO);

    CGContextAddRect(ctx, CGRectMake(head.x – size.width*0.03, head.y + size.height*0.05, size.width*0.05, size.width*0.02));

    CGContextFillPath(ctx);

    [[UIColor blackColor] setFill];

    

    

    CGContextMoveToPoint(ctx, neck.x, neck.y);

    CGContextAddLineToPoint(ctx, sholderR.x, sholderR.y);

    CGContextAddLineToPoint(ctx, elbowR.x, elbowR.y);

    

    

    CGContextMoveToPoint(ctx, elbowR.x, elbowR.y);

    CGContextAddLineToPoint(ctx, handR.x, handR.y);

    

    CGContextMoveToPoint(ctx, neck.x, neck.y);

    CGContextAddLineToPoint(ctx, sholderL.x, sholderL.y);

    CGContextAddLineToPoint(ctx, elbowL.x, elbowL.y);

    CGContextAddLineToPoint(ctx, handL.x, handL.y);

    

    CGContextMoveToPoint(ctx, neck.x, neck.y);

    CGContextAddLineToPoint(ctx, hip.x, hip.y);

    

    CGContextAddLineToPoint(ctx, kneeR.x, kneeR.y);

    CGContextAddLineToPoint(ctx, footR.x, footR.y);

    

    CGContextMoveToPoint(ctx, hip.x, hip.y);

    CGContextAddLineToPoint(ctx, kneeL.x, kneeL.y);

    CGContextAddLineToPoint(ctx, footL.x, footL.y);

    

    CGContextStrokePath(ctx);

    

    

}

@end

@interface ViewController () {

    NSTimer *timer;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    [self createPool];

    

    [self startTimer];

}

– (void)createPool

{

    self.view.backgroundColor = [UIColor whiteColor];

    

    UIView *water = [[UIView alloc] initWithFrame:self.view.bounds];

    water.backgroundColor = [UIColor colorWithRed:0 green:0.7 blue:1 alpha:0.9];

    [self.view addSubview:water];

    

    UIView *bartop = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)];

    bartop.backgroundColor = [UIColor whiteColor];

    bartop.layer.shadowRadius = 4.0;

    bartop.layer.shadowOpacity = 1.0;

    bartop.layer.shadowOffset = CGSizeMake(2, 4);

    bartop.layer.shadowColor = [UIColor blackColor].CGColor;

    [self.view addSubview:bartop];

    

    for (int i=1; i<5; i++) {

        UILabel *num = [[UILabel alloc] initWithFrame:CGRectMake(i*7030, 10, 40, 40)];

        num.text = [NSString stringWithFormat:@”%d”, i];

        num.textAlignment = 1;

        [self.view addSubview:num];

        

        UIView *lineA = [[UIView alloc] initWithFrame:CGRectMake(i*7015, 80, 10, 400)];

        lineA.backgroundColor = [UIColor blackColor];

        [self.view insertSubview:lineA belowSubview:water];

        

        UIView *lineB = [[UIView alloc] initWithFrame:CGRectMake(i*7030, 80, 40, 10)];

        lineB.backgroundColor = [UIColor blackColor];

        [self.view insertSubview:lineB belowSubview:water];

    }

}

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

{

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

    

    StickPerson *sp = [[StickPerson alloc] initWithFrame:CGRectMake(p.x35, 480, 80, 80)];

    [self.view addSubview:sp];

    [sp swim];

    

    [UIView animateWithDuration:6.0 animations:^{

        sp.center = CGPointMake(sp.center.x, 100);

    } completion:^(BOOL finished) {

        [UIView animateWithDuration:0.2 animations:^{

            sp.alpha = 0;

        } completion:^(BOOL finished) {

            [sp removeFromSuperview];

        }];

    }];

}

– (void)startTimer

{

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

}

– (void)tick:(NSTimer*)sender

{

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

        if ([v isKindOfClass:[StickPerson class]]) {

            UIView *white = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];

            white.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.6];

            float x = arc4random() % 40 + 20;

            float y = arc4random() % 10 + 70;

            white.center = CGPointMake(x, y);

            [v addSubview:white];

            [UIView animateWithDuration:0.5 animations:^{

                white.alpha = 0;

            } completion:^(BOOL finished) {

                [white removeFromSuperview];

            }];

        }

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end