iPhone川わたり問題

川わたりパズルっぽい動きをするiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@interface ViewController ()

@property (nonatomic, weak) UIView *boat;

@property (nonatomic, strong) NSMutableArray *people;

@end

#define MyColor [UIColor colorWithRed:107.0/255.0 green:186.0/255.0 blue:255.0/255.0 alpha:1.0]

@implementation ViewController

– (void)viewDidAppear:(BOOL)animated

{

    self.view.backgroundColor = MyColor;

    

    [self createRiver];

    [self createBank];

    [self createPeople];

    [self createBoat];

    [self createMoveButton];

}

– (void)createRiver

{

    UIBezierPath *wave = [UIBezierPath bezierPath];

    float r = 10;

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

        CGPoint o = CGPointMake(i * r * 2, 270);

        [wave appendPath:[UIBezierPath bezierPathWithArcCenter:o radius:r startAngle:0 endAngle:M_PI clockwise:i%2]];

    }

    CAShapeLayer *waveLayer = [CAShapeLayer layer];

    waveLayer.path = wave.CGPath;

    waveLayer.fillColor = [UIColor clearColor].CGColor;

    waveLayer.strokeColor = [UIColor whiteColor].CGColor;

    waveLayer.lineWidth = 2;

    [self.view.layer addSublayer:waveLayer];

}

– (void)createBank

{

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

        UIView *bank = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 80)];

        bank.backgroundColor = [UIColor whiteColor];

        bank.center = CGPointMake(i == 0 ? 30 : i * CGRectGetMaxX(self.view.bounds) – 30, CGRectGetMaxY(self.view.bounds) – 30);

        bank.layer.cornerRadius = 10;

        [self.view addSubview:bank];

    }

}

– (void)createPeople

{

    self.people = [NSMutableArray array];

    

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

        float w = (i==0) ? 20 : 10;

        UIView *p = [[UIView alloc] initWithFrame:CGRectMake(0, 0, w, w * 2.0)];

        p.tag = (i==0) ? 2 : 1;

        p.backgroundColor = [UIColor whiteColor];

        p.center = CGPointMake(i * 30 + CGRectGetMaxX(self.view.bounds) – 80, 220);

        [self.view addSubview:p];

        

        UIView *h = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1.7 * w, 1.7 * w)];

        h.layer.cornerRadius = 1.7 * w / 2.0;

        h.center = CGPointMake(w/2.0, -w * 0.9);

        h.backgroundColor = [UIColor whiteColor];

        [p addSubview:h];

        

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

        [p addGestureRecognizer:tap];

        

        [self.people addObject:p];

    }

}

– (void)createBoat

{

    UIView *boat = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 10)];

    boat.center = CGPointMake(350, 250);

    boat.backgroundColor = [UIColor whiteColor];

    boat.layer.cornerRadius = 5;

    [self.view addSubview:boat];

    

    self.boat = boat;

}

– (void)createMoveButton

{

    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];

    [btn setTitle:@”move” forState:UIControlStateNormal];

    [btn sizeToFit];

    btn.center = CGPointMake(CGRectGetMidX(self.view.bounds), 290);

    [self.view addSubview:btn];

    

    [btn addTarget:self action:@selector(move) forControlEvents:UIControlEventTouchUpInside];

}

– (void)tap:(UITapGestureRecognizer *)gr

{

    // check

    int onBoat = 0;

    NSMutableArray *arr = [NSMutableArray array];

    for (UIView *p in self.people) {

        if (CGRectContainsPoint(self.boat.frame, CGPointMake(p.center.x, self.boat.center.y))) {

            onBoat += p.tag;

            [arr addObject:p];

        }

    }

    onBoat += gr.view.tag;

    [arr addObject:gr.view];

    

    CGPoint origin = gr.view.center;

    

    [UIView animateWithDuration:0.5 animations:^{

        gr.view.center = CGPointMake(self.boat.center.x, 200);

    } completion:^(BOOL finished) {

        [UIView animateWithDuration:0.5 animations:^{

            if (onBoat < 3) {

                gr.view.center = CGPointMake(self.boat.center.x + (arr.count1) * 20, 230);

            } else {

                gr.view.center = origin;

            }

        }];

    }];

}

– (void)move

{

    NSMutableArray *arr = [NSMutableArray array];

    for (UIView *p in self.people) {

        if (CGRectContainsPoint(self.boat.frame, CGPointMake(p.center.x, self.boat.center.y))) {

            [arr addObject:p];

        }

    }

    

    if (arr.count == 0) {

        return;

    }

    

    BOOL right = self.boat.center.x > 250;

    

    [UIView animateWithDuration:2.0 animations:^{

        self.boat.center = CGPointMake(right ? 120 : 350, self.boat.center.y);

        [arr enumerateObjectsUsingBlock:^(UIView *p, NSUInteger idx, BOOL *stop) {

            p.center = CGPointMake(p.center.x + (right ? – 230 : 230), p.center.y);

        }];

    } completion:^(BOOL finished) {

        [arr enumerateObjectsUsingBlock:^(UIView *p, NSUInteger idx, BOOL *stop) {

            float d = [self.people indexOfObject:p] * 20 + 50;

            p.center = CGPointMake(self.boat.center.x + (right ? – d : d), p.center.y);

        }];

    }];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end