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.x – target.center.x;
float ry = centerOfRotation.y – target.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