声明:转载请注明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;
}
应用程序开发之模仿史上最牛游戏(三),布布扣,bubuko.com