ほんのページをぱらぱら~っとめくって
ぴたっと開きたいページでとめてみよう!
という感じで、子供向けiPhoneゲームのサンプルコードを書いてみた。

ポイント
本のページのanchorをViewの左端に持ってきて
そこを中心にy軸周りでCATransform3DRotateをかけてみました。
めくってるページの手前側はm34を使って少し遠近感を。
反対にいくと文字が裏返るので、90度まわしたときに、
裏面にラベルを貼付けるという感じです。

環境
今回つくったiPhoneアプリサンプルは、
XcodeのiOS6 iPhone Simulatorで動かしています。

iPhone ゲーム ページパラパラ

サンプルコード


#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    NSMutableArray *pages;

    int counter;

    BOOL back;

    

    NSTimer *timer;

    

    UILabel *question;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [self getColorAtIndex:0];

    [self createBook];

    [self createUI];

    

    [self setQuestion];

}

– (void)createBook

{

    pages = [[NSMutableArray alloc] init];

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

        UILabel *page = [[UILabel alloc] initWithFrame:CGRectMake(160, 100, 120, 200)];

        

        

        page.text = [NSString stringWithFormat:@”%d”, 2*(99 – i) + 1]; // page 1 to 200

        page.textAlignment = 1;

        page.textColor = [UIColor whiteColor];

        page.font = [UIFont fontWithName:@”Hiragino Kaku Gothic ProN” size:40];

        

        page.backgroundColor = [self getColorAtIndex:3];

        page.layer.anchorPoint = CGPointMake(0, 0.5);

        page.layer.position = CGPointMake(160, 200);

        

        page.layer.borderColor = [self getColorAtIndex:2].CGColor;

        page.layer.borderWidth = 2;

        

        CATransform3D trans = CATransform3DIdentity;

        trans.m34 = –1. /500.0;

        page.layer.transform = trans;

        [self.view addSubview:page];

        

        [pages insertObject:page atIndex:0];

    }

}

– (void)createUI

{

    UILabel *nextButton = [[UILabel alloc] initWithFrame:CGRectMake(260, 400, 40, 40)];

    nextButton.text = @”>”;

    nextButton.font = [UIFont boldSystemFontOfSize:40];

    nextButton.textAlignment = 1;

    nextButton.textColor = [UIColor whiteColor];

    nextButton.backgroundColor = [self getColorAtIndex:3];

    nextButton.layer.cornerRadius = 5;

    [self.view addSubview:nextButton];

    nextButton.userInteractionEnabled = YES;

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

    [nextButton addGestureRecognizer:tapNext];

    

    

    UILabel *backButton = [[UILabel alloc] initWithFrame:CGRectMake(20, 400, 40, 40)];

    backButton.text = @”<“;

    backButton.font = [UIFont boldSystemFontOfSize:40];

    backButton.textAlignment = 1;

    backButton.textColor = [UIColor whiteColor];

    backButton.backgroundColor = [self getColorAtIndex:3];

    backButton.layer.cornerRadius = 5;

    [self.view addSubview:backButton];

    backButton.userInteractionEnabled = YES;

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

    [backButton addGestureRecognizer:tapBack];

    

    UILabel *stopButton = [[UILabel alloc] initWithFrame:CGRectMake(120, 400, 80, 40)];

    stopButton.text = @”stop”;

    stopButton.font = [UIFont boldSystemFontOfSize:30];

    stopButton.textAlignment = 1;

    stopButton.textColor = [UIColor whiteColor];

    stopButton.backgroundColor = [self getColorAtIndex:3];

    stopButton.layer.cornerRadius = 5;

    [self.view addSubview:stopButton];

    stopButton.userInteractionEnabled = YES;

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

    [stopButton addGestureRecognizer:tapStop];

}

– (void)tapStop

{

    [timer invalidate];

    if (2 * counter == [question.text intValue]

        || 2 * counter + 1 == [question.text intValue]) {

        

        UILabel *clear = [[UILabel alloc] initWithFrame:CGRectMake(60, 350, 200, 100)];

        clear.text = @”clear”;

        clear.font = [UIFont boldSystemFontOfSize:30];

        clear.textAlignment = 1;

        clear.textColor = [UIColor whiteColor];

        clear.backgroundColor = [self getColorAtIndex:2];

        clear.transform = CGAffineTransformMakeTranslation(0, 500);

        [self.view addSubview:clear];

        [UIView animateWithDuration:0.6 animations:^{

            clear.transform = CGAffineTransformIdentity;

        } completion:^(BOOL finished) {

            

            [self.view addSubview:clear];

            

            [self setQuestion];

            [UIView animateWithDuration:1.6 animations:^{

                clear.transform = CGAffineTransformMakeTranslation(0, –600);

            }];

        }];

    }

}

– (void)tapNext

{

    [timer invalidate];

    timer = [NSTimer scheduledTimerWithTimeInterval:5.0/60.0 target:self selector:@selector(leafthroughForward) userInfo:nil repeats:YES];

}

– (void)tapBack

{

    [timer invalidate];

    timer = [NSTimer scheduledTimerWithTimeInterval:5.0/60.0 target:self selector:@selector(leafthroughBack) userInfo:nil repeats:YES];

}

– (void)leafthroughForward

{

    if (counter >= 100) {

        [timer invalidate];

        return;

    }

    

    UILabel *page = [pages objectAtIndex:counter];

    

    [UIView animateWithDuration:10.0/60.0 animations:^{

        page.layer.transform = CATransform3DRotate(page.layer.transform, –M_PI/2.0, 0, 1, 0);

    } completion:^(BOOL finished) {

        

        [self.view addSubview:page]; // top view

        

        UILabel *overleaf = [[UILabel alloc] initWithFrame:page.bounds];

        overleaf.text = [NSString stringWithFormat:@”%d”, [page.text intValue] + 1];

        overleaf.font = page.font;

        overleaf.textAlignment = page.textAlignment;

        overleaf.textColor = page.textColor;

        overleaf.backgroundColor = page.backgroundColor;

        

        overleaf.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);

        [page addSubview:overleaf];

        

        [UIView animateWithDuration:10.0/60.0 animations:^{

            page.layer.transform = CATransform3DRotate(page.layer.transform, –M_PI/2.0, 0, 1, 0);

        }];

    }];

    counter++;

}

– (void)leafthroughBack

{

    if (counter == 0) {

        return;

    }

    

    counter–;

    

    UILabel *page = [pages objectAtIndex:counter];

    

    [UIView animateWithDuration:10.0/60.0 animations:^{

        page.layer.transform = CATransform3DRotate(page.layer.transform, M_PI/2.0, 0, 1, 0);

    } completion:^(BOOL finished) {

        [[page.subviews objectAtIndex:0] removeFromSuperview]; // remove overleaf

        [self.view addSubview:page]; // top view

        [UIView animateWithDuration:10.0/60.0 animations:^{

            page.layer.transform = CATransform3DRotate(page.layer.transform, M_PI/2.0, 0, 1, 0);

        }];

    }];

    

    if (counter <= 0) {

        [timer invalidate];

    }

}

#define UIColorHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

– (UIColor*)getColorAtIndex:(int)i

{

    switch (i) {

        case 0:

            return UIColorHex(0x4DC47C);

            break;

        case 1:

            return UIColorHex(0x348554);

            break;

        case 2:

            return UIColorHex(0x163823);

            break;

        case 3:

            return UIColorHex(0x1B452B);

            break;

        case 4:

            return UIColorHex(0x143320);

            break;

        default:

            break;

    }

    return nil;

}

– (void)setQuestion

{

    if (!question) {

        question = [[UILabel alloc] initWithFrame:CGRectMake(110, 30, 100, 40)];

        question.backgroundColor = [self getColorAtIndex:1];

        question.font = [UIFont boldSystemFontOfSize:30];

        question.textAlignment = 1;

        question.layer.cornerRadius = 15;

        question.textColor = [UIColor whiteColor];

        [self.view addSubview:question];

    }

    

    question.text = [NSString stringWithFormat:@”%d”, arc4random() % 180 + 10];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end