第8回「時計 ねんね PM 9:00」
今週のあらすじ
いつまでもテレビを見て寝ないヒョードル
居眠りしていると部屋の様子がおかしいぞ
気付けば雲にのって空の上
雲の布団はきもちいな〜ふわふわ〜
と、夢の中
東京リトルロケットは四コマちょっとアニメです。
ちょっとだけアニメーションするようにiOSでプログラム。( iPhoneで動かしています。)
作:nakai & mizusima
元の四コマ
サンプルコード
@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 *livingroomImg, *bedroomImg;
UIImage *comfortersImg;
UIImage *cloud1Img, *cloud2Img;
UIImage *clockImg1, *clockImg2;
UIImage *hourhandImg, *minutehandImg, *secondhandImg;
UIImage *rabitbodyImg, *rabitheadImg;
UIImage *face1Img, *face2Img, *face3Img, *face4Img;
UIImage *starImg;
UIImage *dreamframeImg;
NSMutableArray *comments;
UIImageView *backScene;
UIImageView *comforters;
UIImageView *dreamframe;
UIImageView *clock;
UIImageView *hourhand, *minutehand, *secondhand;
UIImageView *rabitbody, *rabithead, *rabitface;
UIImageView *commentA;
UIImageView *commentB;
UIImageView *cloud1, *cloud2;
UIImageView *star;
UIImageView *dreamScreenShot;
UIView *blueBack;
NSTimer *timer;
float clockTime;
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
{
clockImg1 = [UIImage imageNamed:@”clock1″];
clockImg2 = [UIImage imageNamed:@”clock2″];
hourhandImg = [UIImage imageNamed:@”hourhand”];
minutehandImg = [UIImage imageNamed:@”minutehand”];
secondhandImg = [UIImage imageNamed:@”secondhand”];
livingroomImg = [UIImage imageNamed:@”scene1″];
bedroomImg = [UIImage imageNamed:@”bed”];
dreamframeImg = [UIImage imageNamed:@”dreamframe”];
comfortersImg = [UIImage imageNamed:@”comforters”];
cloud1Img = [UIImage imageNamed:@”cloud”];
cloud2Img = [UIImage imageNamed:@”clouds”];
rabitbodyImg = [UIImage imageNamed:@”rabitbody”];
rabitheadImg = [UIImage imageNamed:@”rabithead”];
face1Img = [UIImage imageNamed:@”facesmile”];
face2Img = [UIImage imageNamed:@”face2″];
face3Img = [UIImage imageNamed:@”face3″];
face4Img = [UIImage imageNamed:@”face4″];
starImg = [UIImage imageNamed:@”star”];
comments = [[NSMutableArray alloc] init];
for (int i=0; i<9; 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];
}];
// シーン 1
float delay = 0;
[self showScene:^{
[self scene1];
} afterDelay:delay];
// シーン 2
delay += 13;
[self showScene:^{
[self scene2];
} afterDelay:delay];
// シーン 3
delay += 5;
[self showScene:^{
[self scene3];
} afterDelay:delay];
// シーン 4
delay += 10;
[self showScene:^{
[self scene4];
} afterDelay:delay];
// end
delay += 13;
[self showScene:^{
[self createEnding];
} afterDelay:delay];
delay += 1.5;
[self showScene:^{
[self playSound:@”end”];
} afterDelay:delay];
}
– (void)scene1
{
backScene = [[UIImageView alloc] initWithImage:livingroomImg];
backScene.frame = self.view.bounds;
[self.view insertSubview:backScene belowSubview:startView];
rabitbody = [[UIImageView alloc] initWithImage:rabitbodyImg];
rabitbody.frame = self.view.bounds;
[self.view insertSubview:rabitbody belowSubview:startView];
rabithead = [[UIImageView alloc] initWithImage:rabitheadImg];
rabithead.frame = self.view.bounds;
[self.view insertSubview:rabithead belowSubview:startView];
rabitface = [[UIImageView alloc] initWithImage:face4Img];
rabitface.frame = self.view.bounds;
[rabithead addSubview:rabitface];
clock = [[UIImageView alloc] initWithImage:clockImg1];
clock.frame = self.view.bounds;
[self.view insertSubview:clock belowSubview:startView];
hourhand = [[UIImageView alloc] initWithImage:hourhandImg];
hourhand.frame = self.view.bounds;
[clock addSubview:hourhand];
minutehand = [[UIImageView alloc] initWithImage:minutehandImg];
minutehand.frame = self.view.bounds;
[clock addSubview:minutehand];
secondhand = [[UIImageView alloc] initWithImage:secondhandImg];
secondhand.frame =self.view.bounds;
[clock addSubview:secondhand];
// 頭こっくりこっくり
CABasicAnimation *kokukoku = [CABasicAnimation animationWithKeyPath:@”transform.rotation.z”];
kokukoku.repeatCount = 4;
kokukoku.autoreverses = YES;
kokukoku.toValue = [NSNumber numberWithFloat:-M_PI * 0.1];
kokukoku.duration = 2.0;
[rabithead.layer addAnimation:kokukoku forKey:@”koku”];
[self start];
// 21時59分…. ちょうど九時で終わるように調整
clockTime = 21 * 60 * 60 + 59 * 60 + 26;
float delay = 2.0;
// コメント:「はやくねなさい」
[self showScene:^{
commentB = [[UIImageView alloc] initWithImage:[comments objectAtIndex:1]];
commentB.frame = self.view.bounds;
commentB.transform = CGAffineTransformMakeTranslation(0, 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];
// コメント:「まだテレビみるの」
delay += 3.0;
[self showScene:^{
commentA = [[UIImageView alloc] initWithImage:[comments objectAtIndex:0]];
commentA.frame = self.view.frame;
commentA.transform = CGAffineTransformMakeTranslation(0, 100);
[self.view addSubview:commentA];
[UIView animateWithDuration:4.0 animations:^{
commentA.alpha = 0;
}];
} afterDelay:delay];
// コメント:「もう九時よ」
delay += 3.0;
[self showScene:^{
commentB.image = [comments objectAtIndex:2];
[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
{
// シーン転換 夢の中へ
dreamframe = [[UIImageView alloc] initWithImage:dreamframeImg];
dreamframe.frame = self.view.bounds;
dreamframe.transform = CGAffineTransformMakeScale(1.1, 1.1);
dreamframe.alpha = 0;
[self.view addSubview:dreamframe];
blueBack = [[UIView alloc] initWithFrame:self.view.bounds];
blueBack.backgroundColor = [UIColor blueColor];
[self.view insertSubview:blueBack belowSubview:backScene];
[UIView animateWithDuration:3.0 animations:^{
backScene.alpha = 0;
dreamframe.alpha = 1.0;
}];
star = [[UIImageView alloc] initWithImage:starImg];
[self.view addSubview:star];
star.alpha = 0;
// コメント「あれ?」
float delay = 1.0;
[self showScene:^{
rabitface.image = face3Img;
commentA.image = [comments objectAtIndex:4];
commentA.transform = CGAffineTransformMakeTranslation(-50, –150);
[UIView animateWithDuration:0.5 animations:^{
commentA.alpha = 1.0;
star.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:5.0 animations:^{
commentA.alpha = 0;
star.alpha = 0;
}];
}];
} afterDelay:delay];
}
– (void)scene3
{
CAGradientLayer *layer = [CAGradientLayer layer];
layer.frame = self.view.bounds;
// 144, 215, 236
UIColor *c1 = [UIColor colorWithRed:144.0/255.0 green:215.0/255.0 blue:226.0/255.0 alpha:1.0];
UIColor *c2 = [UIColor colorWithRed:144.0/255.0 green:215.0/255.0 blue:255.0/255.0 alpha:1.0];
layer.colors = [NSArray arrayWithObjects:(id)c1.CGColor, (id)c2.CGColor, nil];
layer.startPoint = CGPointMake(0.5, 0.4);
layer.endPoint = CGPointMake(0.5, 1.0);
UIView *backSky = [[UIView alloc] initWithFrame:self.view.bounds];
backSky.alpha = 0;
[backSky.layer addSublayer:layer];
[blueBack addSubview:backSky];
cloud1 = [[UIImageView alloc] initWithImage:cloud1Img];
cloud1.frame = self.view.bounds;
[self.view insertSubview:cloud1 belowSubview:backScene];
cloud1.alpha = 0;
CABasicAnimation *pukupuku = [CABasicAnimation animationWithKeyPath:@”transform.scale”];
pukupuku.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
pukupuku.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)];
pukupuku.repeatCount = 6;
pukupuku.autoreverses = YES;
pukupuku.duration = 1.0;
[cloud1.layer addAnimation:pukupuku forKey:@”puku”];
cloud2 = [[UIImageView alloc] initWithImage:cloud2Img];
cloud2.frame = self.view.bounds;
cloud2.transform = CGAffineTransformMakeScale(0.6, 0.6);
[self.view insertSubview:cloud2 belowSubview:backScene];
cloud2.alpha = 0;
CABasicAnimation *pukupuku2 = [CABasicAnimation animationWithKeyPath:@”transform.scale”];
pukupuku2.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 0.5, 1.0)];
pukupuku2.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.4, 0.4, 1.0)];
pukupuku2.repeatCount = 4;
pukupuku2.autoreverses = YES;
pukupuku2.duration = 1.5;
[cloud2.layer addAnimation:pukupuku2 forKey:@”puku”];
[UIView animateWithDuration:0.5 animations:^{
clock.alpha = 0;
backSky.alpha = 1.0;
cloud2.alpha = 1.0;
rabitbody.alpha = 0;
rabithead.alpha = 0;
} completion:^(BOOL finished) {
cloud1.alpha = 1.0;
rabitbody.transform = CGAffineTransformMakeTranslation(0, 200);
rabithead.transform = CGAffineTransformMakeTranslation(0, 200);
cloud1.transform = CGAffineTransformMakeTranslation(0, 200);
[UIView animateWithDuration:0.5 animations:^{
rabitbody.transform = CGAffineTransformIdentity;
rabithead.transform = CGAffineTransformIdentity;
cloud1.transform = CGAffineTransformIdentity;
rabitbody.alpha = 1;
rabithead.alpha = 1;
}];
}];
float delay = 1.0;
[self showScene:^{
rabitface.image = face1Img;
} afterDelay:delay];
// コメント「雲の布団だ」
delay += 1.0;
[self showScene:^{
commentA.image = [comments objectAtIndex:5];
commentA.transform = CGAffineTransformMakeTranslation(100, 60);
[UIView animateWithDuration:0.5 animations:^{
commentA.alpha = 1.0;
}];
} afterDelay:delay];
// コメント「きもちいい」
delay += 3.0;
[self showScene:^{
commentA.image = [comments objectAtIndex:6];
commentA.transform = CGAffineTransformMakeTranslation(100, 60);
[UIView animateWithDuration:3.0 animations:^{
commentA.alpha = 0.5;
} completion:^(BOOL finished) {
commentA.alpha = 0;
// capture screen
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
dreamScreenShot = [[UIImageView alloc] initWithImage:[self captureScreen]];
CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:@”mask”] CGImage];
mask.frame = CGRectMake(60, 60, dreamScreenShot.bounds.size.width – 120, dreamScreenShot.bounds.size.height – 120);
dreamScreenShot.layer.mask = mask;
dreamScreenShot.layer.masksToBounds = YES;
dreamScreenShot.layer.opacity = 0.8;
});
}];
} afterDelay:delay];
}
– (void)scene4
{
// set up real space
backScene.image = bedroomImg;
backScene.alpha = 1.0;
comforters = [[UIImageView alloc] initWithImage:comfortersImg];
comforters.frame = self.view.bounds;
[self.view addSubview:comforters];
rabitface.image = face2Img;
clock.image = clockImg2;
clock.alpha = 1;
// overlay captuer screen
[self.view addSubview:dreamScreenShot];
[blueBack removeFromSuperview];
[dreamframe removeFromSuperview];
[UIView animateWithDuration:3.0 animations:^{
CGAffineTransform transform = CGAffineTransformMakeScale(0.5, 0.5);
transform = CGAffineTransformTranslate(transform, 300, –150);
dreamScreenShot.transform = transform;
} completion:^(BOOL finished) {
CABasicAnimation *puku = [CABasicAnimation animationWithKeyPath:@”transform.scale”];
puku.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 0.5, 1.0)];
puku.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.6, 0.6, 1.0)];
puku.repeatCount = 4;
puku.autoreverses = YES;
puku.duration = 1.5;
[dreamScreenShot.layer addAnimation:puku forKey:@”puku”];
}];
float delay = 1.0;
for (int i=0; i<3; i++) {
delay += 0.4;
[self showScene:^{
UILabel *z = [self createWord:@”Z” size:50];
z.textColor = [UIColor blueColor];
z.center = CGPointMake(260 + i*50, 150);
z.transform = CGAffineTransformMakeTranslation(0, –300);
[self.view addSubview:z];
CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:@”transform.translation.y”];
move.fromValue = [NSNumber numberWithInt:0];
move.toValue = [NSNumber numberWithInt:-100];
move.duration = 3.0;
move.repeatCount = 1;
[z.layer addAnimation:move forKey:@”move”];
} afterDelay:delay];
}
// コメント「九時だよ」
delay += 6.0 – 1.2;
[self showScene:^{
commentB.image = [comments objectAtIndex:7];
[self.view addSubview:commentB];
commentB.transform = CGAffineTransformMakeTranslation(30, –150);
[UIView animateWithDuration:0.5 animations:^{
commentB.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:5.0 animations:^{
dreamScreenShot.alpha = 0;
commentB.alpha = 0;
}];
}];
} afterDelay:delay];
delay += 2.0;
for (int i=0; i<3; i++) {
delay += 0.4;
[self showScene:^{
UILabel *z = [self createWord:@”Z” size:50];
z.textColor = [UIColor blueColor];
z.center = CGPointMake(260 + i*50, 150);
z.transform = CGAffineTransformMakeTranslation(0, –300);
[self.view addSubview:z];
CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:@”transform.translation.y”];
move.fromValue = [NSNumber numberWithInt:0];
move.toValue = [NSNumber numberWithInt:-100];
move.duration = 3.0;
move.repeatCount = 1;
[z.layer addAnimation:move forKey:@”move”];
} afterDelay:delay];
}
// コメント「おやすみ」
delay += 3.0 – 2.2;
[self showScene:^{
commentB.image = [comments objectAtIndex:8];
[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];
delay += 4.0;
[self showScene:^{
[timer invalidate];
} afterDelay:delay];
}
– (UIImage*)captureScreen
{
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *captureImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return captureImage;
}
– (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
{
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(113, 57);
// second hand
// 1 seconds = 2 * PI / 60
// image origin is 50 seconds.
float secondAngle = (seconds – 10) * (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) + 9) * (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 08″ 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 08″ 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