モグラたたきを作ってみる。

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

ポイント

・UIViewを仕掛け絵本みたいに組み合わせることで

 モグラを巣穴に出したり入れたりする

・モグラの上下にはtransformを利用し、

 位置判定用に現時点のCALayer.transform translateの値を

 CALayer valueForKeyPathで取得する。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

typedef enum{

    MOGU_HOLE,

    MOGU_UP,

    MOGU_DOWN,

    MOGU_SHOW,

} StateMogu;

@interface ViewController () {

    CADisplayLink *timer;

}

@property (nonatomic, strong) NSMutableArray *mogu;

@property (nonatomic, strong) UILabel *score;

@end

@implementation ViewController

@synthesize mogu, score;

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor brownColor];

    

    // 仕掛け絵本みたいに

    // 巣穴とモグラをサンドイッチして隠れるようにする

    mogu = [[NSMutableArray alloc] init];

    [self createGround];

    [self start];

    

    // スコア

    score = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 200, 40)];

    score.backgroundColor = [UIColor blackColor];

    score.layer.cornerRadius = 5.0;

    score.font = [UIFont boldSystemFontOfSize:30];

    score.text = @”000000″;

    score.textAlignment = 1;

    score.textColor = [UIColor orangeColor];

    [self.view addSubview:score];

}

– (void)createGround

{

    

    // モグラの上にくるように、穴と芝、仕掛け絵本みたいにかぶせて隠す

    float widht = self.view.bounds.size.width * 0.9;

    float x = self.view.bounds.size.width * 0.05;

    float y = self.view.bounds.size.height * ((sqrt(2) – 1) / sqrt(2));

    

    // 一列目のモグラと芝、穴のサンドイッチ

    // 穴 モグラの裏に配置

    [self createGrass:CGRectMake(x, y, widht, 80) isFront:NO];

    // モグラ

    [self createMogura:CGRectMake(50, 150, 50, 50 * sqrt(2))];

    [self createMogura:CGRectMake(130, 150, 50, 50 * sqrt(2))];

    [self createMogura:CGRectMake(210, 150, 50, 50 * sqrt(2))];

    // モグラのかくれる芝

    [self createGrass:CGRectMake(x, y + 80, widht, 80) isFront:YES];

    

    

    [self createGrass:CGRectMake(x, y + 130, widht, 50) isFront:NO];

    [self createMogura:CGRectMake(50, 250, 50, 50 * sqrt(2))];

    [self createMogura:CGRectMake(130, 250, 50, 50 * sqrt(2))];

    [self createMogura:CGRectMake(210, 250, 50, 50 * sqrt(2))];

    [self createGrass:CGRectMake(x, y + 180, widht, 80) isFront:YES];

    

    

    [self createGrass:CGRectMake(x, y + 230, widht, 50) isFront:NO];

    [self createMogura:CGRectMake(50, 350, 50, 50 * sqrt(2))];

    [self createMogura:CGRectMake(130, 350, 50, 50 * sqrt(2))];

    [self createMogura:CGRectMake(210, 350, 50, 50 * sqrt(2))];

    [self createGrass:CGRectMake(x, y + 280, widht, 80) isFront:YES];

    

}

– (void)createMogura:(CGRect)frame

{

    // mogura body

    float width = frame.size.width * 0.8;

    float height = frame.size.height * 0.8;

    float x = frame.origin.x + frame.size.width * 0.5;

    float y = frame.origin.y + frame.size.height * 0.8;

    

    UIView *mogura = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

    mogura.center = CGPointMake(x, y);

    mogura.backgroundColor = [UIColor brownColor];

    mogura.layer.cornerRadius = width * 0.2;

    mogura.layer.borderWidth = 3.0;

    mogura.layer.borderColor = [UIColor darkGrayColor].CGColor;

    [self.view addSubview:mogura];

    

    // mogura eye

    UILabel *left = [[UILabel alloc] init];

    float lx = width * 1/sqrt(2) * (11 / sqrt(2));

    left.text = @”●”;

    left.backgroundColor = [UIColor clearColor];

    [left sizeToFit];

    left.center = CGPointMake(lx, 10);

    [mogura addSubview:left];

    

    UILabel *right = [[UILabel alloc] init];

    float rx = width – lx;

    right.text = @”●”;

    right.backgroundColor = [UIColor clearColor];

    [right sizeToFit];

    right.center = CGPointMake(rx, 10);

    [mogura addSubview:right];

    

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

    [mogura addGestureRecognizer:tap];

    

    [self.mogu addObject:mogura];

}

– (void)createGrass:(CGRect)frame isFront:(BOOL)front

{

    float width = frame.size.width * 0.2;

    UIView *grass = [[UIView alloc] initWithFrame:frame];

    grass.backgroundColor = [UIColor greenColor];

    grass.clipsToBounds = YES;

    [self.view addSubview:grass];

    

    // hole

    float point[] = {60, 140, 220};

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

        float y = front ? 0 : frame.size.height;

        float x = point[i];

        UIView *hole = [[UIView alloc] initWithFrame:CGRectMake(0,0, width, width)];

        hole.center = CGPointMake(x, y);

        hole.backgroundColor = [UIColor blackColor];

        hole.layer.cornerRadius = hole.bounds.size.width * 0.5;

        [grass addSubview:hole];

    }

}

– (void)start

{

    timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateGame:)];

    [timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

    

    UILabel *startLabel = [[UILabel alloc] init];

    startLabel.text = @”start”;

    startLabel.textColor = [UIColor darkGrayColor];

    startLabel.backgroundColor = [UIColor clearColor];

    startLabel.font = [UIFont boldSystemFontOfSize:50];

    [startLabel sizeToFit];

    startLabel.center = CGPointMake(500, 100);

    [self.view addSubview:startLabel];

    

    [UIView animateWithDuration:1.0 animations:^{

        startLabel.center = CGPointMake(160, 100);

    } completion:^(BOOL finished) {

        [UIView animateWithDuration:0.5 animations:^{

            startLabel.center = CGPointMake(-300, 100);

        } completion:^(BOOL finished) {

            [startLabel removeFromSuperview];

        }];

    }];

    

    for (UIView *m in mogu) {

        m.tag = MOGU_DOWN;

    }

}

– (void)updateGame:(CADisplayLink*)sender

{

    int rand = arc4random() % 270;

    

    // ランダムでモグラを出す

    if (rand % 30 == 0) {

        UIView *m = [mogu objectAtIndex:rand / 30];

        m.tag = MOGU_UP;

    }

    

    // モグラを動かす

    for (UIView *m in mogu) {

        if (m.tag == MOGU_DOWN)

        {

            CGAffineTransform form = m.transform;

            m.transform = CGAffineTransformTranslate(form, 0, 1);

            

            CALayer *layer = m.layer.presentationLayer;

            float currentY = [[layer valueForKeyPath:@”transform.translation.y”] floatValue];

            if (currentY >= 80.0 ) {

                m.tag = MOGU_HOLE;

            }

        }

        else if (m.tag == MOGU_UP)

        {

            CGAffineTransform form = m.transform;

            m.transform = CGAffineTransformTranslate(form, 0, –1);

            

            CALayer *layer = m.layer.presentationLayer;

            float currentY = [[layer valueForKeyPath:@”transform.translation.y”] floatValue];

            if (currentY <= 0.0) {

                m.tag = MOGU_SHOW;

            }

        }

        else if (m.tag == MOGU_SHOW)

        {

            int stay = arc4random() % 50;

            if (!stay) {

                m.tag = MOGU_DOWN;

            }

        }

    }

}

– (void)tap:(UIGestureRecognizer*)gr //(UIView*)m

{

    UIView *m = gr.view;

    float x = m.center.x;

    float y = m.center.y – m.frame.size.height * 0.5;

    

    // 叩かれて星を出す

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

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

        star.center = CGPointMake(x, y);

        star.backgroundColor = [UIColor yellowColor];

        [self.view addSubview:star];

        [UIView animateWithDuration:0.5 animations:^{

            float th = – i * M_PI / 4.0;

            star.center = CGPointMake(50 * cos(th) + x, 50 * sin(th) + y);

        } completion:^(BOOL finished) {

            [star removeFromSuperview];

        }];

    }

    

    // お目めを×

    for (UILabel *l in m.subviews) {

        l.text = @”×”;

    }

    

    [UIView animateWithDuration:0.5 delay:0.5 options:UIViewAnimationCurveLinear animations:^{

        m.transform= CGAffineTransformMakeTranslation(0, 80);

    } completion:^(BOOL finished) {

        // 目を戻す

        for (UILabel *l in m.subviews) {

            l.text = @”●”;

        }

    }];

    

    // スコアアップ

    score.text = [NSString stringWithFormat:@”%07d”, [score.text intValue] + 100];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end