歩いてる風の棒人間を書いてみます。

(XcodeのiOS6 iPhone Simulatorで試しています。)

ポイント

・UIViewに肩と肘、腰と膝の情報を用意して、角度をタイマーで動かす

・線を足と同じくらいの速さで動かして、歩いている感をなんとなく。

サンプルコード

StickPerson.h

@interface StickPersonWalk : UIView

– (void)walk;

@end

StickPerson.m

#import “StickPersonWalk.h”

@interface StickPersonWalk() {

    CGPoint head, shoulder, waist;

    CGPoint lhand,  rhand;

    CGPoint lelbow, relbow;

    CGPoint lfoot, rfoot;

    CGPoint lknee, rknee;

    int timeCounter;

}

@end

@implementation StickPersonWalk

– (id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        self.backgroundColor = [UIColor clearColor];

        CGSize s = self.bounds.size;

        head = CGPointMake(s.width * 0.5, s.height * 0.1);

        shoulder = CGPointMake(s.width * 0.5, s.height * 0.3);

        waist = CGPointMake(s.width * 0.5, s.height * 0.6);

        

        // hands

        lelbow = CGPointMake(s.width * 0.4, s.height * 0.4);

        lhand = CGPointMake(s.width * 0.3, s.height * 0.5);

        relbow = CGPointMake(s.width * 0.6, s.height * 0.4);

        rhand = CGPointMake(s.width * 0.7, s.height * 0.5);

        // foots

        lknee = CGPointMake(s.width * 0.4, s.height * 0.75);

        lfoot = CGPointMake(s.width * 0.3, s.height * 0.9);

        rknee = CGPointMake(s.width * 0.6, s.height * 0.75);

        rfoot = CGPointMake(s.width * 0.7, s.height * 0.9);

        

    }

    return self;

}

– (void)drawRect:(CGRect)rect

{

    [[UIColor blackColor] set];

    [self drawStick];

}

– (void)drawStick

{

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(ctx, 5.0);

    CGContextSetLineCap(ctx, kCGLineCapRound);

    CGContextSetLineJoin(ctx, kCGLineJoinRound);

    

    float size = self.bounds.size.width;

    CGContextFillEllipseInRect(ctx, CGRectMake(head.x – size*0.1, head.y, size*0.2, size*0.2));

    

    CGContextMoveToPoint(ctx, head.x, head.y + size*0.1);

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

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

    

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

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

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

    

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

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

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

    

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

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

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

    

    

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

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

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

    CGContextStrokePath(ctx);

}

– (void)walk

{

    timeCounter++;

    

    CGSize s = self.bounds.size;

    

    

    // hand

    int i = timeCounter % 50;

    if (i > 25) {

        i = 50 – i;

    }

    float angleLE = i *  M_PI / 50.0 + M_PI * 0.2;

    float lex = shoulder.x + s.width * 0.15 * cos(angleLE);

    float ley = shoulder.y + s.width * 0.15 * sin(angleLE);

    lelbow = CGPointMake(lex, ley);

    

    float angleLH = angleLE – M_PI * 0.2;

    float lhx = lelbow.x + s.width * 0.15 * cos(angleLH);

    float lhy = lelbow.y + s.width * 0.15 * sin(angleLH);

    lhand = CGPointMake(lhx, lhy);

    

    i = (timeCounter + 25) % 50;

    if (i > 25) {

        i = 50 – i;

    }

    float angleRE = i *  M_PI / 50.0 + M_PI * 0.2;

    float rex = shoulder.x + s.width * 0.15 * cos(angleRE);

    float rey = shoulder.y + s.width * 0.15 * sin(angleRE);

    relbow = CGPointMake(rex, rey);

    

    float angleRH = angleRE – M_PI * 0.2;

    float rhx = relbow.x + s.width * 0.15 * cos(angleRH);

    float rhy = relbow.y + s.width * 0.15 * sin(angleRH);

    rhand = CGPointMake(rhx, rhy);

    

    // foot

    i = timeCounter % 50;

    if (i > 25) {

        i = 50 – i;

    }

    float angleLK = i *  M_PI / 50.0 + M_PI * 0.15;

    float lkx = waist.x + s.width * 0.2 * cos(angleLK);

    float lky = waist.y + s.width * 0.2 * sin(angleLK);

    lknee = CGPointMake(lkx, lky);

    

    float angleLF = angleLK + M_PI * 0.2;

    float lfx = lknee.x + s.width * 0.2 * cos(angleLF);

    float lfy = lknee.y + s.width * 0.2 * sin(angleLF);

    lfoot = CGPointMake(lfx, lfy);

    

    

    i = (timeCounter + 25) % 50;

    if (i > 25) {

        i = 50 – i;

    }

    float angleRK = i *  M_PI / 50.0 + M_PI * 0.15;

    float rkx = waist.x + s.width * 0.2 * cos(angleRK);

    float rky = waist.y + s.width * 0.2 * sin(angleRK);

    rknee = CGPointMake(rkx, rky);

    

    float angleRF = angleRK + M_PI * 0.2;

    float rfx = rknee.x + s.width * 0.2 * cos(angleRF);

    float rfy = rknee.y + s.width * 0.2 * sin(angleRF);

    rfoot = CGPointMake(rfx, rfy);

    

    [self setNeedsDisplay];

}

@end

ViewController.m

#import “ViewController.h”

#import “StickPersonWalk.h”

@interface ViewController () {

    NSTimer *timer;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    StickPersonWalk *sw = [[StickPersonWalk alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];

    [self.view addSubview:sw];

    

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];

    [sw addGestureRecognizer:tap];

    

}

– (void)tap:(UIGestureRecognizer*)gr

{

    // 人形を歩かせる

    gr.view.tag = (gr.view.tag + 1) % 2;

    

    [self start];

}

– (void)start

{

    timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(updateDisp:) userInfo:nil repeats:YES];

}

– (void)updateDisp:(NSTimer*)sender

{

    // 人形を歩かせる

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

        if (v.tag == 1) {

            [(StickPersonWalk*)v walk];

        }

    }

    

    // 背景の線を描画する

    static int count = 0;

    if (count % 50 == 0) {

        UIView *line = [[UIView alloc] initWithFrame:CGRectMake(360, –50, 2, 200)];

        line.backgroundColor = [UIColor grayColor];

        line.transform = CGAffineTransformMakeRotation(M_PI * 0.1);

        line.tag = 2;

        [self.view insertSubview:line atIndex:0];

        

        UILabel *mark = [[UILabel alloc] initWithFrame:CGRectMake(330, 140, 40, 20)];

        mark.text = [NSString stringWithFormat:@”%d”, count];

        mark.tag = 2;

        [self.view addSubview:mark];

    }

    count++;

    

    // 線を移動させる

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

        if (v.tag == 2) {

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

            if (v.center.x < 0) {

                [v removeFromSuperview];

            }

        }

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end