iOS 애니메이션 실전 낚시 게임 인 스 턴 스 코드

머리말
최근 에 낚시 게임 을 썼 는데 평소에 게임 을 해 본 적 이 없어 요.이런 게임 은 cocos 2d 로 이 루어 져 야 한다 고 생각 했 는데 애니메이션 이 좋 은 효 과 를 얻 을 수 있다 는 것 을 알 게 되 었 습 니 다.먼저 효과 도 를 보 세 요.

사유 지도
먼저,우 리 는 사고 지도 를 살 펴 보 자.본 게임 은 주로 4 개의 큰 덩어리 로 나 뉘 는데 그 중에서 물고기의 실현 이 가장 복잡 하 다.

사유 지도
프로젝트 구조

준비 작업
먼저 필요 한 그림 을 준비 하 세 요.이 물고 기 는 사실은 그림 입 니 다.그림 의 크기 가 고정 되 고 각 프레임 의 위치 가 변화 하기 때문에 상하 로 움 직 이 는 물고기 로 보 입 니 다.


한 장의 그림
낚시 모듈
스윙 애니메이션
낚싯바늘 의 흔 들 림 범 위 는[MPI/4.0,-M_PI/4.0](수직 으로 0 도 아래로,시계 방향 으로)여기 서 타 이 머 를 이용 하여 각 도 를 바 꾸 었 습 니 다.타 이 머 를 사용 하 는 CAdisplayLink 는 화면 주사 율 과 일치 하 는 타이머 입 니 다.끊 기지 않 으 면 초당 새로 고침 횟수 가 60 회 이 고 본 Demo 의 많은 타 이 머 는 CAdisplayLink 를 사용 합 니 다.다음은 낚싯바늘 의 주요 코드(중점:1.닻 점 을 설치 한 후 frame 을 리 셋 하고 2.각도 변경,3.회전)입 니 다.그 중에서 하나의 block 이 각도 angle 을 FishingView 인터페이스 에 전달 하여 낚시 가 연못 에 떨 어 진 위 치 를 계산 하 는 것 을 정의 했다.

@property (nonatomic, strong) CADisplayLink *linkTimer;
@property (nonatomic, assign) BOOL isReduce;//    
@property (nonatomic, assign) CGFloat angle;//     
- (void)initView{
[self setAnchorPoint:CGPointMake(0.5, 0) forView:self];
UIImageView *gouImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - 35 , 30, 35)];
gouImageView.image = [UIImage imageNamed:@"fish_catcher_tong"];
[self addSubview:gouImageView];
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake((self.frame.size.width - 3)/2.0, 0, 3, self.frame.size.height - 35)];
lineView.backgroundColor = HEXCOLOR(0x9e664a);
[self addSubview:lineView];
//          
_linkTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(hookMove)];
//    link
[_linkTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
//         frame
- (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{
CGRect oldFrame = view.frame;
view.layer.anchorPoint = anchorpoint;
view.frame = oldFrame;
}
#pragma mark -     
- (void)hookMove{
if (self.isReduce){
_angle-=1.8*cos(1.5*_angle)*0.01;//    ,  cos         ,    
if (_angle < -M_PI/180*45){
self.isReduce = NO;
}
}else {
_angle+=1.8*cos(1.5*_angle)*0.01;
if (_angle > M_PI/180*45){
self.isReduce = YES;
}
}
if (self.angleBlock){
self.angleBlock(_angle);
}
// DLog(@"    %f",_angle);
//    
self.transform = CGAffineTransformMakeRotation(_angle);
}
물고기 모듈
물고기 모듈 은 UIImageView 에서 계승 하 는 클래스 입 니 다.
물고기 모듈 은 낚시 가 가능 한 물고기,낚시 가 불가능 한 물고기(사용 하지 않 아 도 된다),낚시 가 가능 한 물고기 세 가 지 를 초기 화 하 는 세 가지 방법 을 제공한다.
물고기의 이동 방식 은 두 가지 가 있 는데,매 거 진 정 의 를 사용 하여 왼쪽 에서 오른쪽으로,오른쪽 에서 왼쪽으로
물고기의 종 류 는 여섯 가지 로 매 거 로 정의 되 었 다.

typedef NS_ENUM(NSInteger, FishModelImageViewType){
FishModelImageViewTypeXHY = 0, //   
FishModelImageViewTypeSBY = 1, //   
FishModelImageViewTypeHSY = 2, //   
FishModelImageViewTypeBWY = 3, //   
FishModelImageViewTypeSHY = 4, //   
FishModelImageViewTypeSY = 5, //  
};
물고 기 를 낚 은 후의 대 리 를 제공 했다.

FishModelImageViewDelegate
//    -    -    
   - (void)catchTheFishWithType:(FishModelImageViewType)type
andDirection:(FishModelImageViewDirection)dir
andWinCount:(int)count;
1.동적 물고기
동적 물고 기 를 싣 는 방법

//   UIImageView
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 55, 55)];
//            ,  xhy1,xhy2,xhy3...,          ,                ,duration     
imageView.image = [UIImage animatedImageNamed:@"xhy" duration:1];
[self.view addSubview:imageView];
서로 다른 물고 기 를 초기 화하 고 크기 에 따라 이동 속도 가 다 르 기 때문에 애니메이션 시간 이 다 릅 니 다.

//      git    
- (void)initViewWithType:(FishModelImageViewType)type andDuration:(double)time{
self.fishType = type;
switch (type) {
case FishModelImageViewTypeXHY://   
self.duration = 6.0;
self.frame = CGRectMake(-100, 0, 35, 40); //        
self.image = [UIImage animatedImageNamed:@"xhy" duration:time];
break;
case FishModelImageViewTypeSBY://   
self.duration = 7.0;
self.frame = CGRectMake(-100, 0, 50, 50);
self.image = [UIImage animatedImageNamed:@"sby" duration:time];
break;
case FishModelImageViewTypeHSY://   
self.duration = 8.0;
self.frame = CGRectMake(-100, 0, 50, 40);
self.image = [UIImage animatedImageNamed:@"hsy" duration:time];
break;
case FishModelImageViewTypeBWY://   
self.duration = 8.5;
self.frame = CGRectMake(-100, 0, 65, 53);
self.image = [UIImage animatedImageNamed:@"bwy" duration:time];
break;
case FishModelImageViewTypeSHY://   
self.duration = 9.0;
self.frame = CGRectMake(-100, 0, 55, 55);
self.image = [UIImage animatedImageNamed:@"shy" duration:time];
break;
case FishModelImageViewTypeSY://  
self.duration = 11.0;
self.frame = CGRectMake(-200, 0, 145, 90);
self.image = [UIImage animatedImageNamed:@"sy" duration:time];
break;
}
}
2.이동 하 는 물고기
제 공 된 그림 은 모두 머리 가 왼쪽으로 향 하기 때문에(위의 움 직 이 는 그림 참조)왼쪽 에서 오른쪽으로 돌아 가면 그림 은 미 러 반전 이 필요 합 니 다.
물고기 가 낚시 를 할 수 있 는 지 여 부 는 알림 으로 정 보 를 전달 하 는 것 으로 낚시 가 가능 하고 낚시 가 불가능 한 두 가지 상태 이다.
낚시 가능:물고기 갈고리 가 연못 에 가 라 앉 았 을 때 낚시 통 지 를 받 았 다(낚시 밑부분 의 좌 표를 전달).현재 물고 기 는 낚시 를 할 수 있다.낚시 확률 등 요소 에 따라 물고기 가 낚시 에 걸 렸 다 고 판단 한 후에 물고 기 를 회전 시 킨 다음 에 낚시 애니메이션 을 실시한다.애니메이션 이 끝 난 후 프 록 시 를 실행 합 니 다.

//         
- (instancetype)initCanCatchFishWithType:(FishModelImageViewType)type andDirection:(FishModelImageViewDirection)dir{
if (self = [super init]){
self.direction = dir;
[self initViewWithType:type andDuration:1];
if (dir == FishModelImageViewFromLeft){//    ,            
self.transform = CGAffineTransformMakeScale(-1, 1); //  
}
[self initFishView];
}
return self;
}
#pragma mark -       (   )
- (void)initFishView{
//         
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationCanCatch:) name:NotificationFishHookStop object:nil];
//         
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationCannotCatch) name:NotificationFishHookMove object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeTimer) name:NotificationRemoveFishModelTimer object:nil];
//     
_linkTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(fishMove)];
//    link(      )
[_linkTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
_offsetX = ScreenWidth;
_offsetY = 100;
_fishWidth = self.frame.size.width;
//Y      
_randomRange = (int) (YuTangHeight - self.frame.size.height - OffSetYRange);
self.speed = (ScreenWidth + _fishWidth)/self.duration;//    
self.changeX = self.speed/60.0;//     60 
DLog(@"      :%f,    :%f", self.speed,self.changeX);
}
물고기 이동 애니메이션 과 낚시 애니메이션

- (void)fishMove{
if (self.direction == FishModelImageViewFromLeft){//    
if (_offsetX > ScreenWidth + _fishWidth){
_offsetY = arc4random()%_randomRange + OffSetYRange;
_offsetX = - _fishWidth - _offsetY;
}
_offsetX+=self.changeX;
self.frame = [self resetFrameOrigin:CGPointMake(_offsetX, _offsetY)];
if ([self fishCanBeCatchedWithOffsetX:_offsetX + _fishWidth]){
NSLog(@"         :%ld",(long)self.fishType);
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, -1, 1);//  
transform = CGAffineTransformRotate(transform, M_PI_2);//  90 
self.transform = transform;
self.frame = [self resetFrameOrigin:CGPointMake(ScreenWidth*2, 0)];
[self fishCatchedMoveUpWithOffsetX:_offsetX + _fishWidth];
_offsetX = ScreenWidth + _fishWidth + 1;//    
_linkTimer.paused = YES;//     
}
}else {//    
if (_offsetX < -_fishWidth){
_offsetY = arc4random()%_randomRange + OffSetYRange;
_offsetX = ScreenWidth + _offsetY;
}
_offsetX-=self.changeX;
self.frame = [self resetFrameOrigin:CGPointMake(_offsetX, _offsetY)];
if ([self fishCanBeCatchedWithOffsetX:_offsetX]){
NSLog(@"         :%ld",(long)self.fishType);
self.transform = CGAffineTransformMakeRotation(M_PI_2);
self.frame = [self resetFrameOrigin:CGPointMake(ScreenWidth*2, 0)];
[self fishCatchedMoveUpWithOffsetX:_offsetX];
_offsetX = -_fishWidth-1;//    
_linkTimer.paused = YES;//     
}
}
}
물고기 가 낚시 에 걸 릴 확률 과 획득 한 금화 개수

//         (      )
- (BOOL)fishCanBeCatchedWithOffsetX:(CGFloat)offsetX{
if (!self.isCanCatch) return NO;
if (fabs(offsetX - self.hookX) > self.changeX/2.0) return NO; //             
int random = arc4random()%100; //[0,99]
DLog(@"random:%d", random);
switch (self.fishType) {
case FishModelImageViewTypeXHY://    80%   2
if (random < 80){
self.moneyCount = 2;
return YES;
}
break;
case FishModelImageViewTypeSBY://    50%   5
if (random < 50) {
self.moneyCount = 5;
return YES;
}
break;
case FishModelImageViewTypeHSY://    30%   10
if (random < 30) {
self.moneyCount = 10;
return YES;
}
break;
case FishModelImageViewTypeBWY://    15%   20
if (random < 15) {
self.moneyCount = 20;
return YES;
}
break;
case FishModelImageViewTypeSHY://    5%   50
if (random < 5) {
self.moneyCount = 50;
return YES;
}
break;
case FishModelImageViewTypeSY://   1%   100
if (random < 1) {
self.moneyCount = 100;
return YES;
}
break;
}
self.moneyCount = 0;
return NO;
}
3.낚 인 물고기
낚 인 물고 기 를 초기 화 하 는 방법

//        
- (instancetype)initCatchedFishWithType:(FishModelImageViewType)type andDirection:(FishModelImageViewDirection)dir{
if (self = [super init]){
self.direction = dir;
[self initViewWithType:type andDuration:0.5];
//  x,y  , 30      ,85      
self.x = (30 - self.width)/2.0;
self.y = 85 - 6;
if (dir == FishModelImageViewFromLeft){//    ,            
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, -1, 1);//  
transform = CGAffineTransformRotate(transform, M_PI_2);//  90 
self.transform = transform;
}else {
self.transform = CGAffineTransformMakeRotation(M_PI_2);
}
}
return self;
}
물고기 가 잡 히 면 낚시 애니메이션 을 실행 합 니 다.

//        
- (void)fishCatchedMoveUpWithOffsetX:(CGFloat) offsetX{
//         45
//    
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"position"];
ani.duration = 0.7;
if (self.fishType == FishModelImageViewTypeSY){//      ,          
ani.fromValue = [NSValue valueWithCGPoint:CGPointMake(offsetX,45 + _fishWidth/2.0)];
ani.toValue = [NSValue valueWithCGPoint:CGPointMake(_hookX, 45 + _fishWidth/2.0)];
}else {
ani.fromValue = [NSValue valueWithCGPoint:CGPointMake(offsetX, (_offsetY < 60) ? 45 + _fishWidth/2.0 : _offsetY)];//            
ani.toValue = [NSValue valueWithCGPoint:CGPointMake(_hookX, 45 + _fishWidth/2.0)];
}
ani.delegate = self;
//                 
[ani setValue:kFishCatchedMoveUpValue forKey:kFishCatchedMoveUpKey];
[self.layer addAnimation:ani forKey:kFishCatchedMoveUpKey];
}
물고기 상류 애니메이션 이 끝 난 후 뒤 집 힌 물고 기 를 원상 태 로 복원 한 후,대 리 를 수행 하여 잡 은 물고 기 를 대 리 를 통 해 전달 합 니 다.

#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (flag){
if ([[anim valueForKey:kFishCatchedMoveUpKey] isEqualToString:kFishCatchedMoveUpValue]){//   
if (self.direction == FishModelImageViewFromLeft){
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, -1, 1);//  
transform = CGAffineTransformRotate(transform, 0);//  90 
self.transform = transform;
}else {
self.transform = CGAffineTransformMakeRotation(0);
}
if ([self.delegate respondsToSelector:@selector(catchTheFishWithType:andDirection:andWinCount:)]){
[self.delegate catchTheFishWithType:self.fishType andDirection:self.direction andWinCount:self.moneyCount];
}
}
}
}
낚시 보기
이것 은 실현 인터페이스 입 니 다.원래는 VC 에 적 혀 있 었 는데 나중에 발견 하면 추출 할 수 있 고 모든 것 을 추출 할 수 있 습 니 다.호출 할 때 매우 간단 합 니 다.정상 적 인 View 처럼 초기 화 한 후에 메 인 View 에 추가 하면 됩 니 다.view Did Disappeared 에서 자원 방출 을 말 하면 됩 니 다.

- (void)viewDidLoad {
[super viewDidLoad];
_fishView = [[FishingView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_fishView];
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[_fishView removeFishViewResource];
}
1.낚시 초기 화
낚시 초기 화
낚싯바늘 이 흔 들 리 는 각 도 를 대 리 를 통 해 본 인터페이스 로 전달 합 니 다.

#pragma mark -   
- (void)initHookView{
_fishHookView = [[FishHookView alloc] initWithFrame:CGRectMake((ScreenWidth - 30)/2.0, 5, 30, 85)];
__weak typeof (self) weakSelf = self;
_fishHookView.angleBlock = ^(CGFloat angle) {
weakSelf.angle = angle;
};
[self addSubview:_fishHookView];
UIImageView *yuGanImageView = [[UIImageView alloc] initWithFrame:CGRectMake(ScreenWidth/2.0 - 2, 0, ScreenWidth/2.0, 50)];
yuGanImageView.image = [UIImage imageNamed:@"fish_gan_tong"];
[self addSubview:yuGanImageView];
}
갈고리 애니메이션:양어장 에 클릭 제스처 가 추가 되 었 습 니 다.클릭 한 후에 낚시 동작 을 수행 하고 낚시 의 흔 들 림 타 이 머 를 중단 합 니 다.갈고리 애니메이션 이 끝 난 후에 고속 물고기 모듈 에 걸 릴 수 있다 는 알림 을 보 내 고 낚시 의 밑부분 중심 좌 표를 전달 합 니 다.낚싯줄 은 CAShape Layer 로 그립 니 다.그리고 strokeEnd 애니메이션 을 집행 합 니 다.

//    
- (void)fishBtnAction{
if (self.fishHookState != FishHookStateShake) return; //          
[self.fishHookView hookTimerPause];//        
double degree = _angle*180/M_PI;//  
double rate = tan(_angle);//  
DLog(@"degree:%f---rate:%f",degree,rate);
//       x    ,          , y    
_lineOffsetX = ScreenWidth/2.0 - (FishLineHeigth)*rate;
//    xy 
_hookBottomX = ScreenWidth/2.0 - (FishLineHeigth + FishHookHeight)*rate;
_hookBottomY = FishLineHeigth + FishHookHeight;
//    
double aniDuration = [self hookOutOfRiver] ? 0.5 : 1;
//    
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(ScreenWidth/2.0 ,5)];
[path addLineToPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
//    
_linePathLayer = [CAShapeLayer layer];
_linePathLayer.frame = self.bounds;
_linePathLayer.path = path.CGPath;
_linePathLayer.strokeColor = [HEXCOLOR(0x9e664a) CGColor];
_linePathLayer.fillColor = nil;
_linePathLayer.lineWidth = 3.0f;
_linePathLayer.lineJoin = kCALineJoinBevel;
[self.layer addSublayer:_linePathLayer];
//    
CAKeyframeAnimation *ani = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
ani.duration = aniDuration;
ani.values = @[@0,@0.8,@1];
ani.keyTimes = @[@0,@0.6,@1];
ani.delegate = self;
[ani setValue:kLineDownAnimationValue forKey:kLineDownAnimationKey];
[_linePathLayer addAnimation:ani forKey:kLineDownAnimationKey];
//    
_hookAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//    
CGFloat tempOffsetX = ScreenWidth/2.0 - (FishLineHeigth*0.8)*rate;
NSValue *p1 = [NSValue valueWithCGPoint:CGPointMake(ScreenWidth/2.0 ,5)];
NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(tempOffsetX, FishLineHeigth*0.8)];
NSValue *p3 = [NSValue valueWithCGPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
_hookAnimation.duration = aniDuration;
_hookAnimation.values = @[p1,p2,p3];
_hookAnimation.keyTimes = @[@0,@0.7,@1];//      
//                 
_hookAnimation.removedOnCompletion = NO;
_hookAnimation.fillMode=kCAFillModeForwards;
[_fishHookView.layer addAnimation:_hookAnimation forKey:@"goukey"];
}
낚시 동작:갈고리 애니메이션 이 끝 난 후 타 이 머 를 켜 고 이 방법 을 실행 합 니 다.카운트다운 이 마지막 초 일 때 물고 기 는 걸 리 지 않 습 니 다(물고기 가 걸 리 는 애니메이션 0.7s,걸 리 는 애니메이션 의 시간 을 남 겨 야 합 니 다).타 이 머 는 0 시 낚시 불가 알림 을 보 내 물고기 모듈 에 걸 리 면 안 된다 는 것 을 알 리 고 걸 리 는 애니메이션 을 실행 합 니 다.

//      
- (void)hookStop:(NSTimer *)timer{
_stopDuration-=1;
//        
if (_stopDuration == 1){
//         
self.fishHookState = FishHookStateUp;
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationFishHookMove object:nil];
}
if (_stopDuration <= 0){
//     
[timer setFireDate:[NSDate distantFuture]];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
[path addLineToPoint:CGPointMake(ScreenWidth/2.0 ,5)];
_linePathLayer.path = path.CGPath;
//    
double aniDuration = [self hookOutOfRiver] ? 0.5 : 1;
//  
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
ani.duration = aniDuration;
ani.fromValue = [NSNumber numberWithFloat:0];
ani.toValue = [NSNumber numberWithFloat:1];
ani.delegate = self;
ani.removedOnCompletion = NO;
ani.fillMode=kCAFillModeForwards;
[ani setValue:kLineUpAnimationValue forKey:kLineUpAnimationKey];
[_linePathLayer addAnimation:ani forKey:kLineUpAnimationKey];
[_fishHookView.layer removeAllAnimations];
NSValue *p1 = [NSValue valueWithCGPoint:CGPointMake(ScreenWidth/2.0 ,5)];
NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
_hookAnimation.duration = aniDuration;
_hookAnimation.values = @[p2,p1];
_hookAnimation.keyTimes = @[@0,@1];
[_fishHookView.layer addAnimation:_hookAnimation forKey:@"goukey"];
}
}
금화 애니메이션&가산 점 애니메이션
언 더 훅 애니메이션 시작,총 금화 10 개 감소
낚시 애니메이션 시작,낚시 불가 알림 발송,낚시 상태 낚시 상태
물고 기 를 잡 으 면(물고기 모듈 에이전트 의 실행 여부 에 따라 잡 았 는 지 판단)금화 애니메이션 과 가산 점 애니메이션 을 실행 합 니 다.
낚시 애니메이션 이 끝나 면 낚시 할 수 있 는 알림 을 물고기 모듈 에 보 내 고 낚시 좌 표를 전달 하여 낚시 에 걸 린 타 이 머 를 엽 니 다.
낚시 애니메이션 이 끝나 면 낚시 상 태 를 바 꾸 고 View 를 제거 하 며 낚시 가 계속 흔 들 립 니 다.

#pragma mark - CAAnimationDelegate     
//    
- (void)animationDidStart:(CAAnimation *)anim{
//      
if ([[anim valueForKey:kLineDownAnimationKey] isEqualToString:kLineDownAnimationValue]){
self.fishHookState = FishHookStateDown;//    
//  
self.moneyLabel.text = [NSString stringWithFormat:@"%d", _totalMoney-=10];
self.winMoney = 0;
}else if ([[anim valueForKey:kLineUpAnimationKey] isEqualToString:kLineUpAnimationValue]){//      
self.fishHookState = FishHookStateUp;//    
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationFishHookMove object:nil];
}
if (self.isCatched){//       
HHShootButton *button = [[HHShootButton alloc] initWithFrame:CGRectMake(_lineOffsetX, 0, 10, 10) andEndPoint:CGPointMake(10, 200)];
button.setting.iconImage = [UIImage imageNamed:@"coin"];
button.setting.animationType = ShootButtonAnimationTypeLine;
[self.bgImageView addSubview:button];
[self bringSubviewToFront:button];
[button startAnimation];
HHWinMoneyLabel *winLabel = [[HHWinMoneyLabel alloc] initWithFrame:CGRectMake(_lineOffsetX - 100/2, ScreenFullHeight - FishSeaHeight, 100, 30)];
winLabel.text = [NSString stringWithFormat:@"+%d",_winMoney];
[self addSubview:winLabel];
self.isCatched = !self.isCatched;
//    
self.moneyLabel.text = [NSString stringWithFormat:@"%d", _totalMoney+=self.winMoney];
}
}
//    
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (flag){
if ([[anim valueForKey:kLineDownAnimationKey] isEqualToString:kLineDownAnimationValue]){//      
self.fishHookState = FishHookStateStop;//    
//    
NSDictionary *dic = @{@"offsetX":[NSString stringWithFormat:@"%.2f",_hookBottomX],@"offsetY":[NSString stringWithFormat:@"%.2f",_hookBottomY]};
//         ,       
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationFishHookStop object:nil userInfo:dic];
_stopDuration = [self hookOutOfRiver] ? 1 : arc4random()%3 + 3; //    [3,5),    1s
//       
[_fishTimer setFireDate:[NSDate distantPast]];
}else if ([[anim valueForKey:kLineUpAnimationKey] isEqualToString:kLineUpAnimationValue]){//      
self.fishHookState = FishHookStateShake;//    
[_linePathLayer removeFromSuperlayer];
[_fishHookView hoolTimerGoOn];//       
_catchedHeight = 0;
//       
[self removeTheCatchedFishes];
}
}
}
물고기 모듈 의 대리 방법
낚시 에 걸 린 물고 기 를 만 들 고 낚시 에 걸 면 낚시 와 함께 낚시 애니메이션 을 실행 할 수 있 습 니 다.

#pragma mark - FishModelImageViewDelegate        
- (void)catchTheFishWithType:(FishModelImageViewType)type andDirection:(FishModelImageViewDirection)dir andWinCount:(int)count{
self.isCatched = YES;
FishModelImageView *fishImageView = [[FishModelImageView alloc] initCatchedFishWithType:type andDirection:dir];
[self.fishHookView addSubview:fishImageView];
fishImageView.y = fishImageView.y + _catchedHeight;
_catchedHeight += 8;//     y     
//    
self.winMoney += count;
}
2.양어장 초기 화
간단 한 물고기 배경 만 들 기 및 클릭 제스처 추가
3.물고기 초기 화
for 순환 을 통 해 여러 종류의 물고 기 를 만 들 수 있 습 니 다.

//   
for (int i = 0; i < 8; i++){
FishModelImageView *model1 = [[FishModelImageView alloc] initCanCatchFishWithType:FishModelImageViewTypeXHY andDirection: (i%2 == 0) ? FishModelImageViewFromRight : FishModelImageViewFromLeft];
model1.delegate = self;
[self.bgImageView addSubview:model1];
}
4.자원 제거
타이머 가 소각 되 지 않 으 면 순환 참조 로 인해 메모리 가 누 출 될 수 있 기 때문에 수 동 으로 제거 해 야 합 니 다.그리고 애니메이션 이 프 록 시 를 실행 하고 끝 난 후에 끝 위치 에 머 물 러 도 방출 되 지 않 기 때문에 수 동 으로 자원 을 방출 해 야 합 니 다.

- (void)removeFishViewResource{
//               
_linePathLayer = nil;
//       
[_fishTimer invalidate];
_fishTimer = nil;
//        
[self.fishHookView hoolTimerInvalidate];
//          
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationRemoveFishModelTimer object:nil];
}
총결산
이로써 본 게임 은 이미 완성 되 었 습 니 다.많이 쓰 고 어 지 럽 습 니 다.좋 지 않 은 점 이 있 으 면 비판 과 지적 을 환영 합 니 다.모두 에 게 도움 이 되 기 를 바 랍 니 다.본 demo 주소[https://github.com/Ccalary/FishingGame]

좋은 웹페이지 즐겨찾기