iPhoneミット打ちゲーム

ただひたすらに、ミットを構えてくれる専属トレーナーを相手に好きなだけ指パンチの練習をするiPhoneアプリの作り方を考えてみました。


動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。

ポイント
トレーナーの両手にミットを持たせて、指でパンチすると、ミットが一度倒れます。倒したミットはトレーナーが上下に動かした後、構えなおす。パンチされる -> 倒れる -> 移動 -> 構える というシンプルな動きを繰り返すようにしました。パンチしたタイミングで、ミットのUIViewに userInteractionEnable = NOを設定し、また構え直したら userInteractionEnable = YESとすることで、移動中は叩けないようにしています。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    UIView *rightMitt, *leftMitt;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    [self createTrainer];

}

– (void)createTrainer

{

    UIView *trainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 200)];

    trainer.backgroundColor = [UIColor yellowColor];

    trainer.center = CGPointMake(240, 200);

    [self.view addSubview:trainer];

    

    UILabel *rEye = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 10, 10)];

    rEye.backgroundColor = [UIColor blackColor];

    [trainer addSubview:rEye];

    

    UILabel *lEye = [[UILabel alloc] initWithFrame:CGRectMake(90, 20, 10, 10)];

    lEye.backgroundColor = [UIColor blackColor];

    [trainer addSubview:lEye];

    

    UILabel *mouth = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 20, 30)];

    mouth.backgroundColor = [UIColor blackColor];

    mouth.layer.cornerRadius = 10.0;

    [trainer addSubview:mouth];

    

    rightMitt = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];

    rightMitt.backgroundColor = [UIColor redColor];

    rightMitt.center = CGPointMake(160, 200);

    rightMitt.layer.cornerRadius = 20;

    rightMitt.layer.zPosition = 100;

    rightMitt.layer.borderWidth = 5;

    rightMitt.layer.borderColor = [UIColor brownColor].CGColor;

    [self.view addSubview:rightMitt];

    

    leftMitt = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];

    leftMitt.backgroundColor = [UIColor redColor];

    leftMitt.center = CGPointMake(320, 200);

    leftMitt.layer.cornerRadius = 20;

    leftMitt.layer.zPosition = 100;

    leftMitt.layer.borderWidth = 5;

    leftMitt.layer.borderColor = [UIColor brownColor].CGColor;

    [self.view addSubview:leftMitt];

    

    NSArray *mitts = @[leftMitt, rightMitt];

    for (UIView *m in mitts) {

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

        [m addGestureRecognizer:tap];

    }

}

– (void)punch:(UITapGestureRecognizer*)gr

{

    gr.view.userInteractionEnabled = NO;

    [self mittOff:gr.view];

}

– (void)mittOff:(UIView*)mitt

{

    [UIView animateWithDuration:0.2 animations:^{

        mitt.layer.transform = CATransform3DMakeRotation(M_PI * 0.45, 1, 0, 0);

    } completion:^(BOOL finished) {

        [self moveMitt:mitt];

    }];

    

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

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

        circle.layer.borderColor = [UIColor whiteColor].CGColor;

        circle.layer.borderWidth = 4;

        circle.layer.cornerRadius = 40;

        circle.center = CGPointMake(mitt.bounds.size.width/2.0, mitt.bounds.size.height/2.0);

        [mitt addSubview:circle];

        circle.transform = CGAffineTransformMakeScale(0.1, 0.1);

        [UIView animateWithDuration:0.15 delay:0.04 * i options:UIViewAnimationOptionCurveEaseIn animations:^{

            circle.transform = CGAffineTransformMakeScale(1.0, 1.0);

        } completion:^(BOOL finished) {

            [circle removeFromSuperview];

        }];

    }

}

– (void)moveMitt:(UIView*)mitt

{

    float duration = (arc4random() % 20) / 100.0;

    float position = (arc4random() % 150) + 80;

    [UIView animateWithDuration:duration animations:^{

        mitt.center = CGPointMake(mitt.center.x, position);

    } completion:^(BOOL finished) {

        [UIView animateWithDuration:0.2 animations:^{

            mitt.layer.transform = CATransform3DIdentity;

            mitt.userInteractionEnabled = YES;

        }];

    }];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end