タイトル
第7回「時計 おやつ PM 3:00」

今週のあらすじ
今日の主役は時計の針たちです。
チビは駆け足、ノッポはお散歩、太っちょはマイペース。
ウサギのヒョードルはおやつが待ちきれません。
ずーっと時計とにらめっこです。

東京リトルロケット
Tokyo Little Rocket は4コマ漫画をプログラムでショートアニメにするという企画です

四コマの絵


サンプルコード

@interface OutLineLabel : UILabel

@end

@implementation OutLineLabel

– (void)drawTextInRect:(CGRect)rect

{

    CGSize shadowOffset = self.shadowOffset;

    UIColor *textColor = self.textColor;

    

    CGContextRef c = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(c, 10);

    CGContextSetLineJoin(c, kCGLineJoinRound);

    

    CGContextSetTextDrawingMode(c, kCGTextStroke);

    self.textColor = [UIColor whiteColor];

    [super drawTextInRect:rect];

    

    CGContextSetTextDrawingMode(c, kCGTextFill);

    self.textColor = textColor;

    self.shadowOffset = CGSizeMake(0, 0);

    [super drawTextInRect:rect];

    

    self.shadowOffset = shadowOffset;

}

@end

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

#import <AVFoundation/AVFoundation.h>

@interface ViewController () {

    UIView *startView;

    

    UIImage *clockImg;

    UIImage *hourhandImg, *minutehandImg, *secondhandImg;

    NSMutableArray *comments;

    

    UIImageView *backScene;

    UIImageView *clock;

    UIImageView *hourhand, *minutehand, *secondhand;

    UIImageView *commentA;

    UIImageView *commentB;

    

    NSTimer *timer;

    float clockTime;

    float nextStartTime;

    BOOL clockup;

    float clockupRate;

    

    AVAudioPlayer *player;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    [self prepareSound];

    

    self.view.backgroundColor = [UIColor blackColor];

    [self loadResource];

    [self createOpening];

}

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

{

    static int lock;

    if(lock == 0) {

        lock++;

        [self showProgram];

    }

    

//    CGPoint p = [[touches anyObject] locationInView:clock];

//    NSLog(@”%f %f”, p.x, p.y);

}

– (void)loadResource

{

    clockImg = [UIImage imageNamed:@”clock”];

    hourhandImg = [UIImage imageNamed:@”hourhand”];

    minutehandImg = [UIImage imageNamed:@”minutehand”];

    secondhandImg = [UIImage imageNamed:@”secondhand”];

    

    comments = [[NSMutableArray alloc] init];

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

        [comments addObject:[UIImage imageNamed:[NSString stringWithFormat:@”comment%d”, i+1]]];

    }

}

– (void)showProgram

{

    // 幕を上げる

    [UIView animateWithDuration:1.0 animations:^{

        startView.center = CGPointMake(250, –300);

    } completion:^(BOOL finished) {

        [startView removeFromSuperview];

    }];

    

    

    // clock

    clockupRate = 1200.0;

    

    // シーン 1

    float delay = 0;

    [self showScene:^{

        [self scene1];

    } afterDelay:delay];

    

    // シーン 2

    delay += 16;

    [self showScene:^{

        [self scene2];

    } afterDelay:delay];

    

    // シーン 3

    delay += 16;

    [self showScene:^{

        [self scene3];

    } afterDelay:delay];

    

    // シーン 4

    delay += 20;

    [self showScene:^{

        [self scene4];

    } afterDelay:delay];

    

    // end

    delay += 22;

    [self showScene:^{

        [self createEnding];

        [self playSound:@”end”];

    } afterDelay:delay];

    

}

– (void)scene1

{

    clock = [[UIImageView alloc] initWithImage:clockImg];

    clock.frame = self.view.bounds;

    [self.view insertSubview:clock belowSubview:startView];

    

    hourhand = [[UIImageView alloc] initWithImage:hourhandImg];

    hourhand.frame = self.view.bounds;

    [self.view insertSubview:hourhand belowSubview:startView];

    

    minutehand = [[UIImageView alloc] initWithImage:minutehandImg];

    minutehand.frame = self.view.bounds;

    [self.view insertSubview:minutehand belowSubview:startView];

    

    secondhand = [[UIImageView alloc] initWithImage:secondhandImg];

    secondhand.frame =self.view.bounds;

    [self.view insertSubview:secondhand belowSubview:startView];

    

    

    [self start];

    

    // 122650

    clockTime = 12 * 60 * 60 + 26 * 60 + 50;

    

    

    // コメント:「まま、おやつまだ?」

    float delay = 4.0;

    

    [self showScene:^{

        commentA = [[UIImageView alloc] initWithImage:[comments objectAtIndex:0]];

        commentA.frame = self.view.bounds;

        [self.view addSubview:commentA];

        [UIView animateWithDuration:4.0 animations:^{

            commentA.alpha = 0;

        }];

    } afterDelay:delay];

    // コメント:「たべたばかりでしょ」

    delay += 4.0;

    [self showScene:^{

        commentB = [[UIImageView alloc] initWithImage:[comments objectAtIndex:1]];

        commentB.frame = self.view.bounds;

        commentB.transform = CGAffineTransformMakeTranslation(-250, 150);

        [self.view addSubview:commentB];

        [UIView animateWithDuration:0.5 animations:^{

            commentB.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentB.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

    // コメント:「おやつは3時になってからよ」

    delay += 4.0;

    [self showScene:^{

        commentB.image = [comments objectAtIndex:2];

        commentB.transform = CGAffineTransformMakeTranslation(-250, 120);

        [self.view addSubview:commentB];

        [UIView animateWithDuration:0.5 animations:^{

            commentB.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentB.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

}

– (void)scene2

{

    clock.alpha = 0.2;

    clockup = YES;

    [self playSound:@”forward”];

    

    // 1303

    nextStartTime = 13 * 60 * 60 + 3 * 60;

    

    float delay = (nextStartTimeclockTime) / clockupRate;

    [self showScene:^{

        clock.alpha = 1.0;

    } afterDelay:delay];

    

    

    // コメント:「まま、三時になった?」

    delay += 1.0;

    [self showScene:^{

        commentA.image = [comments objectAtIndex:3];

        

        commentA.transform = CGAffineTransformMakeTranslation(0, –150);

        [UIView animateWithDuration:0.5 animations:^{

            commentA.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentA.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

    

    // コメント:「まだ、一時間も経ってないわよ」

    delay += 5.0;

    [self showScene:^{

        commentB.image = [comments objectAtIndex:4];

        commentB.transform = CGAffineTransformMakeTranslation(-250, 0);

        [UIView animateWithDuration:0.5 animations:^{

            commentB.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentB.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

}

– (void)scene3

{

    clock.alpha = 0.2;

    clockup = YES;

    [self playSound:@”forward”];

    

    // 1430

    nextStartTime = 14 * 60 * 60 + 30 * 60;

    

    float delay = (nextStartTimeclockTime) / clockupRate;

    [self showScene:^{

        clock.alpha = 1.0;

    } afterDelay:delay];

    

    // コメント:「まま、もう三時?」

    delay += 1.0;

    [self showScene:^{

        commentA.image = [comments objectAtIndex:5];

        commentA.transform = CGAffineTransformMakeTranslation(250, 0);

        [UIView animateWithDuration:0.5 animations:^{

            commentA.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentA.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

    

    // コメント:「もう少しかな」

    delay += 5.0;

    [self showScene:^{

        commentB.image = [comments objectAtIndex:6];

        commentB.transform = CGAffineTransformMakeTranslation(0, 150);

        [UIView animateWithDuration:0.5 animations:^{

            commentB.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentB.alpha = 0;

            }];

        }];

    } afterDelay:delay];

}

– (void)scene4

{

    clock.alpha = 0.2;

    clockup = YES;

    [self playSound:@”forward”];

    

    // 145955

    nextStartTime = 14 * 60 * 60 + 59 * 60 + 55;

    

    float delay = (nextStartTimeclockTime) / clockupRate;

    [self showScene:^{

        clock.alpha = 1.0;

    } afterDelay:delay];

    

    

    delay += 5.0;

    [self showScene:^{

        commentA.image = [comments objectAtIndex:9];

        commentA.transform = CGAffineTransformMakeTranslation(0, 0);

        [UIView animateWithDuration:0.5 animations:^{

            commentA.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentA.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

    

    // コメント:「3時になったわよ。」

    delay += 5.0;

    [self showScene:^{

        commentB.image = [comments objectAtIndex:7];

        commentB.transform = CGAffineTransformIdentity;

        [UIView animateWithDuration:0.5 animations:^{

            commentB.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentB.alpha = 0;

            }];

        }];

        

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

            UILabel *zzz = [self createWord:@”z” size:60];

            zzz.center = CGPointMake(500, 320);

            zzz.backgroundColor = [UIColor clearColor];

            zzz.textColor = [UIColor blueColor];

            [self.view addSubview:zzz];

            [UIView animateWithDuration:4.0 delay:0.2*i options:UIViewAnimationOptionAutoreverse animations:^{

                zzz.center = CGPointMake(-60, –60);

            } completion:^(BOOL finished) {

                [zzz removeFromSuperview];

            }];

        }

        

    } afterDelay:delay];

    

    delay += 5.0;

    [self showScene:^{

        commentA.image = [comments objectAtIndex:8];

        commentA.transform = CGAffineTransformMakeTranslation(0, –100);

        [UIView animateWithDuration:0.5 animations:^{

            commentA.alpha = 1.0;

        } completion:^(BOOL finished) {

            [UIView animateWithDuration:5.0 animations:^{

                commentA.alpha = 0;

            }];

        }];

    } afterDelay:delay];

    

    delay += 1.0;

    [self showScene:^{

        [timer invalidate];

        timer = nil;

    } afterDelay:delay];

}

– (void)turnView:(UIView*)v atPoint:(CGPoint)p angle:(float)angle

{

    CGAffineTransform t = CGAffineTransformIdentity;

    t = CGAffineTransformTranslate(t, -(v.center.x – p.x), -(v.center.y – p.y));

    t = CGAffineTransformRotate(t, angle);

    t = CGAffineTransformTranslate(t, v.center.x – p.x, v.center.y – p.y);

    v.transform = t;

}

– (void)start

{

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

}

– (void)tick

{

    if (clockup) {

        clockTime += clockupRate / 60.0;

        

        if (clockTime > nextStartTime) {

            clockup = NO;

            clockTime = nextStartTime;

        }

        

    } else {

        clockTime += 1.0 / 60.0;

    }

    

    int hours = clockTime / pow(60.0, 2);

    int minutes = (clockTime – hours * pow(60.0, 2)) / 60.0;

    int seconds = clockTime – hours * pow(60.0, 2) – minutes * 60.0;

    

    CGPoint handCenter = CGPointMake(214, 150);

    

    // second hand

    // 1 seconds = 2 * PI / 60

    // image origin is 50 seconds.

    float secondAngle = (seconds – 50) * (2 * M_PI / 60.0);

    [self turnView:secondhand atPoint:handCenter angle:secondAngle];

    

    // minutehand

    float minuteAngle = minutes * (2 * M_PI / 60.0);

    [self turnView:minutehand atPoint:handCenter angle:minuteAngle];

    

    // hourhand

    float hourAngle = (5 * (hours + minutes / 60.0) – 14) * (2 * M_PI / 60.0);

    [self turnView:hourhand atPoint:handCenter angle:hourAngle];

    

    

    // sound clock

    if (clockTime – (hours * 60 * 60 + minutes * 60 + seconds) == 0) {

        [self playSound:@”second”];

    }

    

}

– (void)prepareSound

{

    NSString *path = [[NSBundle mainBundle] pathForResource:@”second” ofType:@”mp3″];

    player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];

    [player prepareToPlay];

}

#pragma – mark TLR Create Helper

– (void)showScene:(void (^)(void))block afterDelay:(NSTimeInterval)delay

{

    [self performSelector:@selector(executeBlock:) withObject:block afterDelay:delay];

}

– (void)executeBlock:(void (^)(void))block

{

    block();

}

– (UILabel*)createWord:(NSString*)word size:(int)size

{

    OutLineLabel *label = [[OutLineLabel alloc] init];

    label.font = [UIFont fontWithName:@”Chalkduster” size:size];

    label.text = word;

    label.backgroundColor = [UIColor clearColor];

    [label sizeToFit];

    return label;

}

– (void)createOpening

{

    UIImage *rocket = [UIImage imageNamed:@”rocket_back.jpg”];

    startView = [[UIImageView alloc] initWithImage:rocket];

    [self.view addSubview:startView];

    

    UILabel *l = [self createWord:@” Start \n\n Tokyo Little Rocket\n 07″ size:30];

    l.numberOfLines = 0;

    l.textColor = [UIColor blueColor];

    l.frame = CGRectMake(0, 0, 500, 320);

    l.center = startView.center;

    [startView addSubview:l];

}

– (void)createEnding

{

    UIImage *rocket = [UIImage imageNamed:@”rocket_back.jpg”];

    UIImageView *endView = [[UIImageView alloc] initWithImage:rocket];

    endView.frame = CGRectMake(0, –340, 500, 320);

    [self.view addSubview:endView];

    

    UILabel *l = [self createWord:@” End \n\n Tokyo Little Rocket\n 07″ size:30];

    l.numberOfLines = 0;

    l.textColor = [UIColor redColor];

    l.frame = CGRectMake(0, 0, 500, 320);

    [endView addSubview:l];

    [UIView animateWithDuration:1 animations:^{

        endView.center = CGPointMake(250, 160);

    }];

}

– (void)playSound:(NSString*)name

{

    if ([player isPlaying]) {

        [player stop];

    }

    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@”mp3″];

    player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];

    [player prepareToPlay];

    [player play];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end