首页 > 代码库 > 应用程序开发之模仿史上最牛游戏(三)

应用程序开发之模仿史上最牛游戏(三)

  声明:转载请注明http://www.cnblogs.com/letougaozao/p/3720679.html

  • 关卡解锁
  • 关卡状态的设计
一、解锁动画(点一下解锁)
解锁前后
监听touch end方法,使用涂层layer动画
-加入QuartzCore.framework框架
-动画包括哪些内容呢?(注意播放声音的代码
 
1??整个关卡摇摆两下(旋转动画)、并且变大(缩放动画)
2??搁层消失(直接移除)
1.封装一个动画组的方法
- (CAAnimationGroup *)animationCroup
{
    //1.摇摆动画
    CAKeyframeAnimation *shake = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
    CGFloat angle = M_PI_4/4;
    shake.values = @[@(-angle), @(angle), @(-angle)];
    shake.repeatCount = 3;
    //2.伸缩动画
    CAKeyframeAnimation *scale = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
    scale.values = @[@1.2, @1];
    //3.添加动画组
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[shake, scale];
    return group;
}

2.执行前面的动画且设置代理(动画执行完之后执行后面的动画)

    //0.点击了,覆盖层就消失,且执行动画过程中,不允许用户交互
    [self setUserInteractionEnabled:NO];
    [_stageCover removeFromSuperview];
    
    //1.播放动画
    CAAnimationGroup *group = [self animationCroup];
    group.delegate = self;
    [self.layer addAnimation:group forKey:nil];
    //2.播放声音
    [[SoundManager sharedSoundManager] playSound:kSoundDrop];
2??锁掉下去(位移动画)
3??出现new且摇摆两下(可见之前new是隐藏的,改为不隐藏),显示白框(更改图片)
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    //1.锁掉下来
    CGFloat destY = [UIScreen mainScreen].bounds.size.height - self.frame.origin.y;
    CGFloat duration = destY/1000;
    [UIView animateWithDuration:duration animations:^{
        CGRect frame = _stageLock.frame;
        frame.origin.y = destY;
        _stageLock.frame = frame;
    } completion:^(BOOL finished) {
        [_stageLock removeFromSuperview];

        [_stageNew setHidden:NO];
        _stageRim.image = [UIImage imageNamed:@"select_stage_new.png"];
        
        CAAnimationGroup *group = [self animationCroup];
        
        [self.stageNew.layer addAnimation:group forKey:nil];
        
        [self setUserInteractionEnabled:YES];
    }];
}
二、关卡状态的设计
1??关卡状态(对状态的分析,才能设计后面有声明属性
-从未解锁(显示锁)
-即将解锁(一进来就解锁)
执行解锁动画
 
-已经解锁,从未玩过
 
-已经解锁,且玩过(如果为S显示后面的图片)
 
2??每一关用一个模型来保存状态(StageRecordModel)
-分数(成绩)score
-等级(A~F,S)rank
-是否解锁,unlocked;
-关卡编号(NSString)no
//分数
@property (nonatomic, assign) double score;
//编号
@property (nonatomic, assign) int no;
//等级(A~F,S)
@property (nonatomic, copy) NSString *rank;
//状态
@property (nonatomic, assign, getter = isUnlock) BOOL unlock;
 
3??归档
-遵循NSCoding协议<NSCoding>
-重写两个方法
#import "StageRecordModel.h"
#define kRank @"rank"
#define kNo @"no"
#define kUnlock @"unlock"
#define kScore @"score"

@implementation StageRecordModel

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        self.rank = [aDecoder decodeObjectForKey:kRank];
        self.no = [aDecoder decodeIntForKey:kNo];
        self.score = [aDecoder decodeDoubleForKey:kScore];
        self.unlock = [aDecoder decodeBoolForKey:kUnlock];
    }
    return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.rank forKey:kRank];
    [aCoder encodeInt:self.no forKey:kNo];
    [aCoder encodeDouble:self.score forKey:kScore];
    [aCoder encodeBool:self.isUnlock forKey:kUnlock];
}

@end
 
4??专门写一个工具类,来保存数据、读取数据(存模型数据,专门写一个工具类
这里有一个小细节:我们可以把路径直接写成一个宏(非常好用)
#define kPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"records.data"]
 
-存档方法 saveStageRecord
//存档
- (void)saveStageRecord:(StageRecordModel *)stageRecordModel
{
    if (stageRecordModel.no < 0) return;
    [allRecords setObject:stageRecordModel forKey:@(stageRecordModel.no)];
    [NSKeyedArchiver archiveRootObject:allRecords toFile:kPath];
}
 
 
-读档方法 stageRecordWithNo
   1.在类初始化的时候,加载所有的数据到字典(重写init方法)
- (id)init
{
    if (self = [super init]) {
        allRecords = [NSKeyedUnarchiver unarchiveObjectWithFile:kPath];
        if (!allRecords) {
            allRecords = [NSMutableDictionary dictionary];
            StageRecordModel *stageRecordModel = [[StageRecordModel alloc] init];
            stageRecordModel.no = 1;
            [allRecords setObject:stageRecordModel forKey:@(stageRecordModel.no)];
        }
    }
    return self;
}
 2.读档方法
//读档
- (StageRecordModel *)stageRecordWithNo:(int)no
{
    return allRecords[@(no)];
}
-将工具类设置成单例模式
     将单例代码抽成宏
     1.声明文件中
singleton_interface(StageRecordTool)
     2.实现文件中
singeton_implementation(StageRecordTool)
5??加载状态
-让StageModel拥有一个状态的属性
我们在StageInfo当中,添加一个StageRecordModel属性
//让关卡信息拥有一个StageRecordModel属性
@property (nonatomic, strong) StageRecordModel *stageRecordModel;
 
-在添加每一个Stage的时候,同时加载状态
        //2.1加载关卡的状态
        StageRecordModel *stageRecordModel =[[StageRecordTool sharedStageRecordTool] stageRecordWithNo:i + 1];
        
        //2.2加载关卡的信息
        StageInfo *stageInfo = [StageInfo stageInfoWith:stageDic];
        stageInfo.stageRecordModel = stageRecordModel;
        stageInfo.stageNo = i + 1;  
-重写setStageModel方法时,第三步-更新关卡的状态
//3.根据关卡的状态,获得关卡显示的内容
    [self updateStageState];
 
     我将下面出现情况所写的代码直接在最后贴出来,我觉得我写的还是比较容易理解的,每一种情况还是需要自己好好分析一下。
  1.关卡记录为nil,就显示未解锁状态
     直接设置不能和用户交互
     2.即将解锁,有关卡记录,但是unlock属性为NO
     第一次进入游戏的,把第一关加入,并且执行动画,,并且把解锁的unlock设置成YES
     3.解锁,unlock属性为YES,但是rink为nil
  溢出遮盖、锁
  边框显示白色
  显示new
     4.已解锁,unlock为YES,rank不为nil
  溢出遮盖、锁
  显示等级(rank)和阴影(shadow)
  移除new
  设置等级显示的图片
-判断是否是s(序列帧动画)
 
1.加载图片(当view是通过xib创建的时候,会调用awakeFromNib方法)
2.播放
#pragma mark 根据关卡状态、获得关卡要显示的内容
- (void)updateStageState
{
    if (!_stageInfo.stageRecordModel) {
        [self setUserInteractionEnabled:NO];
    } else {
        if (!_stageInfo.stageRecordModel.unlock) {
            [self updateStageWithWillUnlock];
        } else {
            [self updateStageWithUnlock];
        }
    }
}
#pragma mark 即将解锁时,执行的代码
- (void)updateStageWithWillUnlock
{
    //0.点击了,覆盖层就消失,且执行动画过程中,不允许用户交互
    [self setUserInteractionEnabled:NO];
    [_stageCover removeFromSuperview];
    
    //1.播放动画
    CAAnimationGroup *group = [self animationCroup];
    group.delegate = self;
    [self.layer addAnimation:group forKey:nil];
    //2.播放声音
    [[SoundManager sharedSoundManager] playSound:kSoundDrop];
    //3.设置unlock属性为YES
    _stageInfo.stageRecordModel.unlock = YES;
    [[StageRecordTool sharedStageRecordTool] saveStageRecord:_stageInfo.stageRecordModel];
}
#pragma mark 已经解锁,执行的代码
- (void)updateStageWithUnlock
{
    //1.遮盖和锁去掉
    [_stageCover removeFromSuperview];
    [_stageLock removeFromSuperview];
    
    if (_stageInfo.stageRecordModel.rank == nil) {
        
        //2.显示new
        [_stageNew setHidden:NO];
        
        //3.将边框换成黄色
        _stageRim.image = [UIImage imageNamed:@"select_stage_new.png"];
    } else {
        //2.显出阴影、等级
        [_stageShadow setHidden:NO];
        [_stageRank setHidden:NO];
        
        //3.把new移除
        [_stageNew removeFromSuperview];
        
        //4.根据等级显示图片
        _stageRank.image = [UIImage imageNamed:[NSString stringWithFormat:@"select_stage_%@.png", _stageInfo.stageRecordModel.rank]];
        if ([@"s" isEqualToString:_stageInfo.stageRecordModel.rank]) {
            [_stageRim startAnimating];
        } else {
            [_stageRim setImage:[UIImage imageNamed:@"select_stage_normal.png"]];
        }
    }
}

#pragma mark - 解锁的动画
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    //1.锁掉下来
    CGFloat destY = [UIScreen mainScreen].bounds.size.height - self.frame.origin.y;
    CGFloat duration = destY/1000;
    [UIView animateWithDuration:duration animations:^{
        CGRect frame = _stageLock.frame;
        frame.origin.y = destY;
        _stageLock.frame = frame;
    } completion:^(BOOL finished) {
        [_stageLock removeFromSuperview];

        [_stageNew setHidden:NO];
        _stageRim.image = [UIImage imageNamed:@"select_stage_new.png"];
        
        CAAnimationGroup *group = [self animationCroup];
        
        [self.stageNew.layer addAnimation:group forKey:nil];
        
        [self setUserInteractionEnabled:YES];
    }];
}
- (CAAnimationGroup *)animationCroup
{
    //1.摇摆动画
    CAKeyframeAnimation *shake = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
    CGFloat angle = M_PI_4/4;
    shake.values = @[@(-angle), @(angle), @(-angle)];
    shake.repeatCount = 3;
    //2.伸缩动画
    CAKeyframeAnimation *scale = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
    scale.values = @[@1.2, @1];
    //3.添加动画组
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[shake, scale];
    return group;
}