CALayerでダルマが転んだり起きたりするアプリ落書き

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

ポイント

タップした座標を中心に回転させる CATransform3D

Translate(回転中心に移動) -> rotate -> Translate(戻す)

という処理を行っている。

抜粋

 CATransform3D transform = target.layer.transform;

 transform = CATransform3DTranslate(transform, rx, ry, 0.0);

 transform = CATransform3DRotate(transform, M_PI * 0.02, 0, 0, 1.0);

 transform = CATransform3DTranslate(transform, -rx, -ry, 0.0);

落ちてくるダルマをタップして、転ばせて、起こしてを繰り返すアプリ

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    BOOL wait;

    int counter;

    UIView *target;

    CADisplayLink *timer;

    CGPoint centerOfRotation;

}

@property (nonatomic, strong) UILabel *label;

@end

@implementation ViewController

@synthesize label;

– (void)viewDidLoad

{

    [super viewDidLoad];

    

}

– (void)viewDidAppear:(BOOL)animated

{

    [self.view addSubview:[self createDharma]];

    

    // label 初期化

    label = [[UILabel alloc] initWithFrame:CGRectMake(150, 0, 100, 200)];

    label.textColor = [UIColor blackColor];

    label.backgroundColor = [UIColor clearColor];

    label.text = @” ころび おき;

    [label sizeToFit];

    [self.view addSubview:label];

    

    

    [self start];

}

– (UIView*)createDharma

{

    UIView *dharma = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];

    dharma.backgroundColor = [UIColor redColor];

    dharma.layer.cornerRadius = 30.0;

    

    UIView *face = [[UIView alloc] initWithFrame:CGRectMake(10, 20, 80, 60)];

    face.backgroundColor = [UIColor whiteColor];

    face.layer.cornerRadius = 20.0;

    

    UIView *eyeR = [[UIView alloc] initWithFrame:CGRectMake(70, 40, 12, 12)];

    eyeR.backgroundColor = [UIColor blackColor];

    eyeR.layer.cornerRadius = 6.0;

    

    UIView *eyeL = [[UIView alloc] initWithFrame:CGRectMake(20, 40, 12, 12)];

    eyeL.backgroundColor = [UIColor blackColor];

    eyeL.layer.cornerRadius = 6.0;

    

    UIView *mouth = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];

    mouth.backgroundColor = [UIColor blackColor];

    mouth.layer.cornerRadius = 15.0;

    UIView *mouthHide = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 15)];

    mouthHide.backgroundColor = [UIColor whiteColor];

    [mouth addSubview:mouthHide];

    

    

    

    eyeR.center = CGPointMake(80, 50);

    eyeL.center = CGPointMake(20, 50);

    mouth.center = CGPointMake(50, 45);

    

    [dharma addSubview:face];

    [dharma addSubview:eyeR];

    [dharma addSubview:eyeL];

    [dharma addSubview:mouth];

    

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

    [dharma addGestureRecognizer:tgr];

    

    return dharma;

}

– (void)start

{

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

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

}

– (void)updateDisp:(CADisplayLink*)sender

{

    if (wait && target) {

        

        // ころぶ、おきるのアップデート

        if (counter == 0) {

            [self updateLabel];

        }

        

        

        // タップされた達磨を回転する。

        

        CATransform3D transform = target.layer.transform;

        

        // タップされた場所を回転中心にする

        float rx = centerOfRotation.xtarget.center.x;

        float ry = centerOfRotation.ytarget.center.y;

        

        transform = CATransform3DTranslate(transform, rx, ry, 0.0);

        // 回転

        transform = CATransform3DRotate(transform, M_PI * 0.02, 0, 0, 1.0);

        // 平行移動を戻す

        transform = CATransform3DTranslate(transform, -rx, -ry, 0.0);

        

        // 反映

        target.layer.transform = transform;

        

        

        counter++;

        if (counter >= 50) {

            wait = FALSE;

            // viewの補正(そのうちもっとシンプルな方法を見つけよう。)

            target.layer.position = CGPointMake(50,50);

            target = nil;

            counter = 0;

        }

        

    } else {

        float x, y;

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

            x = v.center.x;

            y = v.center.y + 0.2;

            v.center = CGPointMake(x, y);

        }

    }

    

}

– (void)tap:(UITapGestureRecognizer*)tgr

{

    if (!wait) {

        // タップした達磨を回転対象としてマークする

        centerOfRotation = [tgr locationInView:tgr.view];

        target = tgr.view;

        wait = YES;

        counter = 0;

    }

}

– (void)updateLabel

{

    static int callCount = 1;

    callCount++;

    

    // 漢数字に変換してラベルを表示する

    NSArray *kanji = [[NSArray alloc] initWithObjects:@”, @”, @”, @”, @”, @”, @”, @”, @”, nil];

    NSString *korobi = [kanji objectAtIndex:callCount / 2];

    NSString *oki = [kanji objectAtIndex:((callCount – 1) / 2 + 1)];

    label.text = [NSString stringWithFormat:@”%@ ころび %@ おき,korobi, oki];

    [label sizeToFit];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end