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

  声明:转载请注明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

时间: 2024-11-05 12:48:51

应用程序开发之模仿史上最牛游戏(三)的相关文章

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

声明:转载请注明http://www.cnblogs.com/letougaozao/p/3708887.html 新建关卡控制器 自定义UIScrollView 增加UIPageView 每个关卡的View 整体效果展示 一.新建关卡控制器 1??拖线 -修改控制器class -修改控制器的View的class(方便设置背景) -装资源文件 -返回按钮 二.自定义UIScrollView 1??在初始化方法里面做一些事情 -添加四张背景图片 1.创建四个FullView 2.将这四个view加

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

一.需要一个新的控制器(ReadyViewController) -新建控制器,通过push方式到这个新控制器 -给控制器的view制定类(根据图片选择颜色) -给线起名字 1??给每一个Stage添加手势监听 //2.4为stageView添加手势监听 [stageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(itemClick:)]]; 2??需要控

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

很多天没有更新博客了,一方面是回杭州了几天,另一方面是开始做项目练习了.感谢关注我的一些朋友- 这些天会陆续把自己做这个项目的过程更新出来,喜欢的朋友可以一起学习一下 声明:转载请注明http://www.cnblogs.com/letougaozao/p/3708887.html 游戏配置 第一个界面-主界面 游戏设置界面 音乐.音效 一.游戏该有的配置 -Status Bar Hide 注意:IOS7如何隐藏状态栏:plist加个view controller-base.... 设置成NO就

微信小程序开发-地图map组件上使用input组件

微信小程序开发-地图map组件上使用input组件 标签: 微信小程序 uni-app 原生组件层级关系 微信小程序在最高层级 在微信小程序中原生组件包括camera canvas input(仅在focus时表现为原生组件) live-player live-pusher map textarea video 在微信小程序开发中原生组件的层级是最高的,所以页面中的其他组件无论设置 z-index 为多少,都无法盖在原生组件上. 后插入的原生组件可以覆盖之前的原生组件. 原生组件还无法在 pic

史上最牛逼的菜刀

6月17号,某牛在朋友圈发了消息: 史上最牛逼的中国菜刀即将发布,过市面上所有的 waf,而且把 webshell 玩到让你瞠目结舌的境界 当时有消息称 6 月底将会发布新版菜刀. 果不其然,在 6 月 20 日,原本已经关闭的 maicaidao.com 又开放了,而且下载量瞬间就到了 660 +. 话不多说,赶紧去下载一个体验一波到底有多牛逼. 文章发布时站点又关闭了,具体原因不得而知.(脉搏SP小编注:应该是被DDoS了) 脉搏小编看了一下whois变更,认为应该还是老兵作品.相关阅读<红

企业级openvpn生产标准史上最牛最全最实战课程

企业级openvpn生产标准史上最牛最全最实战课程 近100节,让你轻松精通openvpn及技术 http://edu.51cto.com/pack/view/id-277.html 企业级OpenVPN技术中级运维实战视频课程(上) 1 课前思想必看 2 VPN概述介绍与图解 3 VPN的作用介绍与图解 4 VPN的企业应用分类介绍与图解1 5 VPN的企业应用分类介绍与图解2 6 常见隧道协议介绍-PPTP 7 常见隧道协议介绍-L2TP 8 常见隧道协议介绍-IPSEC-SSLVPN 9

史上最牛逼的javascript俄罗斯方块,63行代码搞定啊

<!doctype html><html><head></head><body> <div id="box" style="width:252px;font:25px/25px 宋体;background:#000;color:#9f9;border:#999 20px ridge;text-shadow:2px 3px 1px #0f0;"></div> <script>

Menu史上最牛的侧滑效果

GAG-master史上最牛的侧滑效果,其中加载图片展示的时候也是慢慢翻转效果,侧滑Menu更是牛逼.  其中自定义BlurFoldingActionBarToggle 提供了onDrawerOpened()和onDrawerClosed()方法,  然后在这两个方法里面设置打开和关闭等各项操作. 运行效果: 查看完整源码地址:http://www.itlanbao.com/code/20150909/10000/100518.html package me.storm.ninegag; imp

HDOJ 1406 完数(打表,附讨论区出现的史上最牛逼打表,0ms)

 完数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 22197    Accepted Submission(s): 8115 Problem Description 完数的定义:如果一个大于1的正整数的所有因子之和等于它的本身,则称这个数是完数,比如6,28都是完数:6=1+2+3:28=1+2+4+7+14. 本题的任务是判