ios 动画系列之七------吃豆人动画的实现

本文参考自:http://blog.csdn.net/totogo2010/article/details/8606089,尊重原创!又做了点自己的加工,最终实现了一个小人追这个豆子跑的动画,可随时暂停、继续。

效果如下:                

实现该动画的思路很简单:pacman的开口,闭口,以及pacman的行走路径。至于开口、闭口之间的效果并不需要我么实现,插值计算会自动补全动画的。而动画的暂停、继续我们在ios动画系列三这篇文章中已经讲过了,苹果给的有例子。

直接附上代码:

 1 //
 2 //  PacmanViewController.h
 3 //  AnimationDemo
 4 //
 5 //  Created by yuqiu on 13-7-23.
 6 //  Copyright (c) 2013年 rongfzh. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 #import <QuartzCore/QuartzCore.h>
11 @interface PacmanViewController : UIViewController
12 {
13     UIBezierPath *_pacmanOpenPath;
14     UIBezierPath *_pacmanClosedPath;
15     CAShapeLayer *_shapeLayer;
16     CAShapeLayer *_ballLayer;
17     UIBezierPath *_ballPath;
18 }
19 @end
PacmanViewController.h
  1 //
  2 //  PacmanViewController.m
  3 //  AnimationDemo
  4 //
  5 //  Created by yuqiu on 13-7-23.
  6 //  Copyright (c) 2013年 rongfzh. All rights reserved.
  7 //
  8 
  9 #import "PacmanViewController.h"
 10 #define DEGREES_TO_RADIANS(x) (3.14159265358979323846 * x / 180.0)
 11 
 12 @interface PacmanViewController ()
 13 
 14 @end
 15 
 16 @implementation PacmanViewController
 17 - (void)viewDidLoad
 18 {
 19     [super viewDidLoad];
 20     UIButton *btn = [[UIButton alloc]init];
 21     [btn setTitle:@"暂停" forState:UIControlStateNormal];
 22     btn.frame = CGRectMake(10, 400, 145, 40);
 23     btn.backgroundColor = [UIColor greenColor];
 24     [btn addTarget:self action:@selector(pauseLayer) forControlEvents:UIControlEventTouchUpInside];
 25     [self.view addSubview:btn];
 26     
 27     [super viewDidLoad];
 28     UIButton *btn1 = [[UIButton alloc]init];
 29     [btn1 setTitle:@"继续" forState:UIControlStateNormal];
 30     btn1.frame = CGRectMake(160, 400, 145, 40);
 31     btn1.backgroundColor = [UIColor greenColor];
 32     [btn1 addTarget:self action:@selector(resumeLayer) forControlEvents:UIControlEventTouchUpInside];
 33     [self.view addSubview:btn1];
 34 
 35     
 36     self.view.backgroundColor = [UIColor yellowColor];
 37     
 38     CGFloat radius = 30.0f;//半径
 39     CGFloat diameter = radius * 2;//直径
 40     CGPoint arcCenter = CGPointMake(radius, radius);//中心点坐标
 41     
 42     // Create a UIBezierPath for Pacman's open state
 43     //以某个点为中心画弧线   创建pacman的开口路径
 44     _pacmanOpenPath = [UIBezierPath bezierPathWithArcCenter:arcCenter  //弧线中心点的坐标
 45                                                     radius:radius  //弧线所在圆的半径
 46                                                 startAngle:DEGREES_TO_RADIANS(35) //弧线开始的角度值
 47                                                   endAngle:DEGREES_TO_RADIANS(325) //弧线结束的角度值
 48                                                  clockwise:YES]; //是否顺时针画弧线
 49     
 50     [_pacmanOpenPath addLineToPoint:arcCenter]; 
 51     [_pacmanOpenPath closePath];
 52     
 53     // Create a UIBezierPath for Pacman's close state
 54     // 创建pacman的闭口路径
 55     _pacmanClosedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter
 56                                                       radius:radius
 57                                                   startAngle:DEGREES_TO_RADIANS(0)
 58                                                     endAngle:DEGREES_TO_RADIANS(360)
 59                                                    clockwise:YES];
 60     [_pacmanClosedPath addLineToPoint:arcCenter];
 61     [_pacmanClosedPath closePath];
 62     
 63     // Create a CAShapeLayer for Pacman, fill with yellow
 64     //创建这个Pacman的实体,目前还不知道这是怎么创建的???????
 65     _shapeLayer = [CAShapeLayer layer];
 66     _shapeLayer.path = _pacmanClosedPath.CGPath;//path定义了这个shape渲染的范围
 67     _shapeLayer.fillColor = [UIColor greenColor].CGColor;//整个shape的填充色    
 68     _shapeLayer.strokeColor = [UIColor grayColor].CGColor;//画笔的颜色,即边界线的颜色
 69     _shapeLayer.lineWidth = 1.0f;//layer边界线宽
 70     //_shapeLayer.bounds = CGRectMake(0, 0, diameter, diameter);//layer的边界大小
 71     _shapeLayer.position = CGPointMake(0, 40);//layer在它的superLayer上的位置
 72 //    _shapeLayer.frame = CGRectMake(0, 40, diameter, diameter);
 73     [self.view.layer addSublayer:_shapeLayer];
 74 
 75     //创建一个球球
 76     _ballPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(10,0) radius:10 startAngle:DEGREES_TO_RADIANS(0) endAngle:DEGREES_TO_RADIANS(360) clockwise:YES];
 77     _ballLayer = [CAShapeLayer layer];
 78     _ballLayer.fillColor = [UIColor redColor].CGColor;
 79     _ballLayer.path = _ballPath.CGPath;
 80     _ballLayer.position = CGPointMake(60,70);
 81     [self.view.layer addSublayer:_ballLayer];
 82 
 83     UIGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startAnimation)];
 84     [self.view addGestureRecognizer:recognizer];   
 85 }
 86 
 87 - (void)startAnimation {
 88     // 创建咬牙动画
 89     CABasicAnimation *chompAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
 90     chompAnimation.duration = 0.25;
 91     chompAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
 92     chompAnimation.repeatCount = HUGE_VALF;//无穷大
 93     chompAnimation.autoreverses = YES;
 94     // Animate between the two path values
 95     chompAnimation.fromValue = (id)_pacmanClosedPath.CGPath;
 96     chompAnimation.toValue = (id)_pacmanOpenPath.CGPath;
 97     [_shapeLayer addAnimation:chompAnimation forKey:@"chompAnimation"];
 98     
 99     // Create digital '2'-shaped path
100     //创建pacman走的路径
101     UIBezierPath *path = [UIBezierPath bezierPath];
102     [path moveToPoint:CGPointMake(30, 40)];
103     [path addLineToPoint:CGPointMake(280, 40)];
104     [path addLineToPoint:CGPointMake(280, 180)];
105     [path addLineToPoint:CGPointMake(60,180)];
106     [path addLineToPoint:CGPointMake(60, 300)];
107     [path addLineToPoint:CGPointMake(300, 300)];
108     
109     //行走动画    
110     CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
111     moveAnimation.repeatCount = HUGE_VALF;
112     moveAnimation.path = path.CGPath;
113     moveAnimation.duration = 6.0f;
114     // Setting the rotation mode ensures Pacman's mouth is always forward.  This is a very convenient CA feature.
115     moveAnimation.rotationMode = kCAAnimationRotateAuto;
116     [_shapeLayer addAnimation:moveAnimation forKey:@"moveAnimation"];
117     
118     //创建ball走的路径å
119     UIBezierPath *path1 = [UIBezierPath bezierPath];
120     [path1 moveToPoint:CGPointMake(30, 70)];
121     [path1 addLineToPoint:CGPointMake(270, 70)];
122     [path1 addLineToPoint:CGPointMake(270, 170)];
123     [path1 addLineToPoint:CGPointMake(30,170)];
124     [path1 addLineToPoint:CGPointMake(30, 330)];
125     [path1 addLineToPoint:CGPointMake(300, 330)];
126    
127     CAKeyframeAnimation *moveAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
128     moveAnimation1.repeatCount = HUGE_VALF;
129     moveAnimation1.path = path1.CGPath;
130     moveAnimation1.duration = 5.5f;
131     moveAnimation.rotationMode = kCAAnimationRotateAuto;
132 
133     [_ballLayer addAnimation:moveAnimation1 forKey:@"moveAnimation"];
134 }
135 
136 //暂停动画
137 -(void)pauseLayer
138 {
139     CFTimeInterval pausedTime = [self.view.layer convertTime:CACurrentMediaTime() fromLayer:nil];
140     self.view.layer .speed = 0.0;
141     self.view.layer .timeOffset = pausedTime;
142 }
143 
144 //继续动画
145 -(void)resumeLayer
146 {
147     CFTimeInterval pausedTime = [self.view.layer timeOffset];
148     self.view.layer.speed = 1.0;
149     self.view.layer.timeOffset = 0.0;
150     self.view.layer.beginTime = 0.0;
151     CFTimeInterval timeSincePause = [self.view.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
152     self.view.layer.beginTime = timeSincePause;
153 }
154 
155 - (void)didReceiveMemoryWarning
156 {
157     [super didReceiveMemoryWarning];
158     // Dispose of any resources that can be recreated.
159 }
160 
161 @end
View Code

代码中的注释非常清楚,就不再解释了。只再说一点:moveAnimation.rotationMode = kCAAnimationRotateAuto;这句话保证了pacman的嘴巴总是我们想要的方向。


这个动画做的很粗糙,ball的行走路径和pacman的嘴巴有时候都不在一条线上,也不是我预期想要的pacman和ball总是隔固定的大小。这两个没有符合预期的效果,也是我在做这个动画时碰到过的问题。

1、pacman的行走路径,是以pacman的哪个点来看的?2、pacman和ball走的路径不一样长,怎么保证总是隔固定大小?

第一个问题:经过试验,我发觉是以pacman圆上的最上面的点为基准的,即使翻转,依然是以那个点为基准。

第二个问题:利用beginTime,设不同的开始时间,还木有尝试。

好啦,动画系列就告一段落啦!在下个阶段,我将会学习不同格式图片的压缩、处理效率。

原文地址:https://www.cnblogs.com/wyqfighting/p/3209520.html