クレーンゲームの落書きをしてみました。

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

ポイント

・touchBegin, Move, Endで該当するUIViewの長押しを検知

・CALayerをのばしたり、パーツ化したけど、描画タイミングに難あり。

(※きっと設定があるはず。)

・掴むと言うより、磁石で吸い寄せ的なものになってしまった。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

// クレーンの状態

typedef enum {

    ClawStop,

    ClawLeft,

    ClawRight,

    ClawDown,

    ClawMiss,

    ClawCatch,

} ClawStatus;

@interface ViewController () {

    ClawStatus status;

    CADisplayLink *timer;

}

@property (nonatomic, strong) NSArray *prizes;

@property (nonatomic, strong) UIView *claw;

@property (nonatomic, strong) UILabel *left;

@property (nonatomic, strong) UIView *center;

@property (nonatomic, strong) UILabel *right;

@end

@implementation ViewController

@synthesize prizes, claw, left, center, right;

– (void)viewDidAppear:(BOOL)animated

{

    [super viewDidAppear:animated];

    

    // 入れ物を作る

    [self createBox];

    

    // 景品を作る

    [self createPrizes];

    

    // クローを作る

    [self createClaw];

    

    // ボタンを3つ

    [self createControlPanel];

    

    // スタート

    [self start];

}

– (void)viewDidDisappear:(BOOL)animated

{

    [super viewDidDisappear:animated];

    

    [timer invalidate];

    timer = nil;

    

    prizes = nil;

    left = nil;

    right = nil;

    center = nil;

}

– (void)createBox

{

    UIView *top = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];

    top.backgroundColor = [UIColor redColor];

    [self.view addSubview:top];

    

    // ガラスっぽく

    UIView *middle = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 320, 330)];

    CAGradientLayer *layer = [CAGradientLayer layer];

    layer.frame = CGRectMake(0, 0, 320, 330);

    UIColor *color1 = [UIColor colorWithRed:0 green:0 blue:0.4 alpha:0.5];

    UIColor *color2 = [UIColor colorWithRed:0 green:0 blue:0.6 alpha:0.3];

    layer.colors = [NSArray arrayWithObjects:(id)color1.CGColor, color2.CGColor, nil];

    [middle.layer addSublayer:layer];

    [self.view addSubview:middle];

    

    UIView *bottom = [[UIView alloc] initWithFrame:CGRectMake(0, 380, 320, 100)];

    bottom.backgroundColor = [UIColor redColor];

    [self.view addSubview:bottom];

}

– (void)createPrizes

{

    // 赤、青、黄色の箱をおいておく

    UIView *red = [[UIView alloc] initWithFrame:CGRectMake(40, 350, 30, 30)];

    red.backgroundColor = [UIColor redColor];

    red.layer.borderColor = [UIColor greenColor].CGColor;

    red.layer.borderWidth = 2.0;

    [self.view addSubview:red];

    

    UIView *blue = [[UIView alloc] initWithFrame:CGRectMake(100, 350, 30, 30)];

    blue.backgroundColor = [UIColor blueColor];

    blue.layer.borderColor = [UIColor greenColor].CGColor;

    blue.layer.borderWidth = 2.0;

    [self.view addSubview:blue];

    

    UIView *yellow = [[UIView alloc] initWithFrame:CGRectMake(160, 350, 30, 30)];

    yellow.backgroundColor = [UIColor yellowColor];

    yellow.layer.borderColor = [UIColor greenColor].CGColor;

    yellow.layer.borderWidth = 2.0;

    [self.view addSubview:yellow];

    

    

    // 掴んだりするために、配列に入れておく

    self.prizes = [NSArray arrayWithObjects:red, blue, yellow, nil];

}

– (void)createClaw

{

    self.claw = [[UIView alloc] initWithFrame:CGRectMake(self.view.center.x, 50, 70, 330)];

    self.claw.backgroundColor = [UIColor clearColor];

    [self.view addSubview:self.claw];

    

    CALayer *arm = [CALayer layer];

    arm.frame = CGRectMake(30, 0, 10, 100);

    arm.backgroundColor = [UIColor blackColor].CGColor;

    [self.claw.layer addSublayer:arm];

    

    CALayer *hand = [CALayer layer];

    hand.frame = CGRectMake(0, 100, 70, 5);

    hand.backgroundColor = [UIColor blackColor].CGColor;

    [self.claw.layer addSublayer:hand];

    

    CALayer *finger1 = [CALayer layer];

    finger1.frame = CGRectMake(0, 100, 5, 40);

    finger1.backgroundColor = [UIColor blackColor].CGColor;

    [self.claw.layer addSublayer:finger1];

    

    CALayer *finger2 = [CALayer layer];

    finger2.frame = CGRectMake(65, 100, 5, 40);

    finger2.backgroundColor = [UIColor blackColor].CGColor;

    [self.claw.layer addSublayer:finger2];

}

– (void)createControlPanel

{

    // コントロール用のボタンを配置

    left = [[UILabel alloc] initWithFrame:CGRectMake(60, 400, 50, 50)];

    left.text = @”<“;

    left.font = [UIFont boldSystemFontOfSize:25];

    left.textColor = [UIColor whiteColor];

    left.textAlignment = 1; // center

    left.layer.cornerRadius = 25.0;

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

    left.layer.borderWidth = 3.0;

    left.backgroundColor = [UIColor blackColor];

    [self.view addSubview:left];

    

    right = [[UILabel alloc] initWithFrame:CGRectMake(210, 400, 50, 50)];

    right.text = @”>”;

    right.font = [UIFont boldSystemFontOfSize:25];

    right.textColor = [UIColor whiteColor];

    right.textAlignment = 1; // center

    right.layer.cornerRadius = 25.0;

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

    right.layer.borderWidth = 3.0;

    right.backgroundColor = [UIColor blackColor];

    [self.view addSubview:right];

    

    center = [[UILabel alloc] initWithFrame:CGRectMake(self.view.center.x30, 400, 60, 50)];

    center.backgroundColor = [UIColor blackColor];

    [self.view addSubview:center];

    

}

– (void)start

{

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

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

}

– (void)updateDisp:(CADisplayLink*)sender

{

    switch (status) {

        case ClawDown:

        case ClawMiss:

        case ClawCatch:

            [self updateClaw];

            break;

            

        case ClawLeft:

            claw.center = CGPointMake(claw.center.x1, claw.center.y);

            break;

            

        case ClawRight:

            claw.center = CGPointMake(claw.center.x + 1, claw.center.y);

            break;

            

        default:

            break;

    }

}

– (void)updateClaw

{

    // CALayerの描画タイミングが微妙、なにか設定があれば探そう。。

    

    CALayer *arm = [claw.layer.sublayers objectAtIndex:0];

    CALayer *hand = [claw.layer.sublayers objectAtIndex:1];

    CALayer *finger1 = [claw.layer.sublayers objectAtIndex:2];

    CALayer *finger2 = [claw.layer.sublayers objectAtIndex:3];

    

    float armHeight = arm.frame.size.height;

    

    if (status == ClawDown) {

        // アームをおろす

        arm.frame = CGRectMake(arm.frame.origin.x, arm.frame.origin.y, arm.frame.size.width, armHeight + 1);

        hand.position = CGPointMake(hand.position.x, hand.position.y + 1);

        finger1.position = CGPointMake(finger1.position.x, finger1.position.y + 1);

        finger2.position = CGPointMake(finger2.position.x, finger2.position.y + 1);

        

        // 接触したら止める

        for (UIView *v in prizes) {

            CGPoint p1 = [self.view convertPoint:finger1.position fromView:claw];

            CGPoint p2 = [self.view convertPoint:finger2.position fromView:claw];

            p1.y += 20;

            p2.y += 20;

            if (CGRectContainsPoint(v.frame, p1) || CGRectContainsPoint(v.frame, p2)) {

                status = ClawMiss;

            }

        }

        

        if (armHeight > 260) {

            // 下まで来たら止める

            for (UIView *prize in prizes) {

                

                if (abs(prize.center.xclaw.center.x) < 20) {

                    // 景品がある場合

                    status = ClawCatch;

                    return;

                }

            }

                

            // 景品が掴めない

            status = ClawMiss;

        }

    }

    else if (status == ClawMiss) {

        // アームを上げる

        arm.frame = CGRectMake(arm.frame.origin.x, arm.frame.origin.y, arm.frame.size.width, armHeight – 1);

        hand.position = CGPointMake(hand.position.x, hand.position.y1);

        finger1.position = CGPointMake(finger1.position.x, finger1.position.y1);

        finger2.position = CGPointMake(finger2.position.x, finger2.position.y1);

        

        if (armHeight < 100) {

            // 上まで来たら止める

            status = ClawStop;

        }

    }

    else if (status == ClawCatch) {

        // アームを景品ごと上げる

        arm.frame = CGRectMake(arm.frame.origin.x, arm.frame.origin.y, arm.frame.size.width, armHeight – 1);

        hand.position = CGPointMake(hand.position.x, hand.position.y1);

        finger1.position = CGPointMake(finger1.position.x, finger1.position.y1);

        finger2.position = CGPointMake(finger2.position.x, finger2.position.y1);

        for (UIView *prize in prizes) {

            if (abs(prize.center.xclaw.center.x) < 20) {

                prize.layer.position = CGPointMake(prize.layer.position.x, prize.layer.position.y1);

            }

        }

        

        

        if (armHeight < 100) {

            // 上まで来たら止める

            status = ClawStop;

        }

        

    }

    

    [claw setNeedsDisplay];

    

}

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

{

    UITouch *t = [touches anyObject];

    CGPoint tPoint = [t locationInView:self.view];

    [self buttonControl:tPoint];

}

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

{

    UITouch *t = [touches anyObject];

    CGPoint tPoint = [t locationInView:self.view];

    [self buttonControl:tPoint];

}

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

{

    // タッチした位置でクレーンの状態を変更

    if (status != ClawDown && status != ClawMiss && status != ClawCatch) {

        status = ClawStop;

    }

}

– (void)buttonControl:(CGPoint)p

{

    

    // タッチした位置でクレーンの状態を変更

    if (status != ClawDown && status != ClawMiss && status != ClawCatch) {

        

        if(CGRectContainsPoint(left.frame, p)) {

            status = ClawLeft;

            return;

        }

        

        if(CGRectContainsPoint(center.frame, p)) {

            status = ClawDown;

            return;

        }

        

        if(CGRectContainsPoint(right.frame, p)) {

            status = ClawRight;

            return;

        }

        

        // それ以外の場合

        status = ClawStop;

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end