首页 > 代码库 > 应用程序开发之模仿史上最牛游戏(四)
应用程序开发之模仿史上最牛游戏(四)
一、需要一个新的控制器(ReadyViewController)
-新建控制器,通过push方式到这个新控制器
-给控制器的view制定类(根据图片选择颜色)
-给线起名字
1??给每一个Stage添加手势监听
//2.4为stageView添加手势监听 [stageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(itemClick:)]];
2??需要控制器来跳转下一个界面(Block的方式)
-把控制器的某一段代码,在StageView中调用
1.让StageView拥有一个Block属性(Block属性只能用copy)
@property (nonatomic, copy) void (^itemClickBlock)(StageInfo *stageInfo);
2.在控制器初始化时,给StageView的block赋值
//3.跳转到ReadyViewController的block方法 stageView.itemClickBlock = ^(StageInfo *stageInfo) { [self performSegueWithIdentifier:@"ready" sender:stageInfo]; };
3.在用户点击时StageView中调用block
#pragma mark -view点击的手势监听的方法 - (void)itemClick:(UIGestureRecognizer *)tap { if (_itemClickBlock != nil) { Stage *stageView = (Stage*)tap.view; _itemClickBlock(stageView.stageInfo); } }
4.让Ready控制器拥有一个StageModel属性
//关卡信息 @property (nonatomic, strong) StageInfo *stageInfo;
在调转之前调用的方法中传递
#pragma mark - 跳转到ReadyViewController的过程会执行的方法 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { ReadyViewController *ready = segue.destinationViewController; ready.stageInfo = (StageInfo*)sender; }
注明:整个过程实现了将StageInfo从Stage中,一直传递到准备开始游戏的控制器中(ReadyViewController),整个传递过程是
Stage--->StageView--->StageViewController--->ReadyViewController
二、搭建界面
1??搭建界面
-游戏首先会进入到一个准备的界面
界面中的字体会动画的形式跳出来(玩过的都懂的),在动画执行完之后,这个界面消失。可见这个界面并不需要一个专门的控制器来管理,只需要一个View即可,但是我们需要封装好这个View
-第二个界面包含更多的元素
1.返回按钮
2.开始按钮
3.介绍的UIImageView
4.旁边的图标(根据StageInfo来设置)
5.简介的UILable(根据StageInfo显示不同的信息)
6.计分器(有较复杂的逻辑,所以我们专门写一个类来实现它的逻辑)
2??设置label
//2.加载关卡的label _stageTitle.text = [NSString stringWithFormat:@"Stage %d", _stageInfo.stageNo]; _stageIntro.text = [_stageInfo.intro stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];
3??过度的View(单独创建一个View)
-设置背景图片
-拖几个label
-控制器把Model传递给View,让View根据Model设置几个label
1.重写setStageInfo方法
2.设置数据
-设置label显示时候的动画、声音
一种办法(UIView)
另一种办法(涂层动画)
1.初始化一个定时器
2.给定时器写一个方法来执行动画
3.移除UIView
#pragma mark - 重写setStageInfo对象 - (void)setStageInfo:(StageInfo *)stageInfo { [self setFullView:@"select_bg.jpg"]; _stageInfo = stageInfo; //0.播放声音 [[SoundManager sharedSoundManager] playSound:kSoundReady]; //1.设置准备界面的标题 _stageReadyTitle.text = [NSString stringWithFormat:@"STAGE %d", stageInfo.stageNo]; //2.设置几个label的文字 NSArray *strings = [stageInfo.title componentsSeparatedByString:@"\\n"]; int count = _labels.count; CGFloat timeCount = 0; for (int i = 0; i<count; i++) { UILabel *label = _labels[i]; label.text = strings[i]; label.hidden = YES; CGFloat delay = 0.3 * (i + 1); timeCount += delay; label.tag = i + 1; [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(showLabel:) userInfo:label repeats:NO]; } //3.设置一个定时器,移除自身的View [NSTimer scheduledTimerWithTimeInterval:timeCount target:self selector:@selector(removeView) userInfo:nil repeats:NO]; } #pragma mark 显示label的动画 - (void)showLabel:(NSTimer *)timer { //1.取出label并且设置不隐藏 UILabel *label = timer.userInfo; label.hidden = NO; //2.添加动画到涂层 CAAnimationGroup * group = [self animationCroup]; [label.layer addAnimation:group forKey:nil]; //3.播放声音 [[SoundManager sharedSoundManager] playSound:kDropTitle(label.tag)]; } - (CAAnimationGroup *)animationCroup { //1.伸缩动画 CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"]; scale.fromValue = @0; scale.toValue = @1; //2.位移动画 CAKeyframeAnimation *trans = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"]; trans.values = @[@0, @40, @20]; //3.添加动画组 CAAnimationGroup *group = [CAAnimationGroup animation]; group.animations = @[scale, trans]; return group; } #pragma mark 移除View - (void)removeView { [self removeFromSuperview]; _removeBlock(); }
4??记分板(业务逻辑较多,直接封装一个View)
-新建一个ReadyScoreView类
-拖一个UIView-UIImageView-6个label
-给labels添加数据
1.添加两个属性给stageInfo(因为这里我们要根据单位和格式来设置记分板中的label)
@property (nonatomic, copy) NSString *format;
@property (nonatomic, copy) NSString *unit;
2.显示数据
-根据积分来显示计分器的位置
1.拖一个
2.根据积分来确定它的位置
- (void)setStageInfo:(StageInfo *)stageInfo { _stageInfo = stageInfo; //1.确定每一个label显示的值 CGFloat margin = (stageInfo.max - stageInfo.min)/5; int count = _labels.count; for (int i = 0; i<count; i++) { UILabel *label = _labels[i]; CGFloat score = stageInfo.max - i * margin; label.text = [NSString stringWithFormat:stageInfo.format, score]; } //2.显示计分器的位置 [self setScoreHintCenter:margin]; if (!_stageInfo.stageRecordModel.rank) { _scoreHint.hidden = YES; return; } //3.执行动画 self.transform = CGAffineTransformMakeTranslation(0, 200); [UIView animateWithDuration:0.3 animations:^{ //平移动画(CGAffineTransformIdentity表示清空所有的属性) self.transform = CGAffineTransformIdentity; } completion:^(BOOL finished) { CAKeyframeAnimation *blink = [CAKeyframeAnimation animationWithKeyPath:@"hidden"]; blink.values = @[@0, @1, @0]; blink.repeatCount = 3; [_scoreHint.layer addAnimation:blink forKey:nil]; }]; } #pragma mark 设置指示器的位置 - (void)setScoreHintCenter:(CGFloat)margin { CGPoint center = _scoreHint.center; // 计算现在积分 和 最差成绩 的差距 CGFloat delta = _stageInfo.stageRecordModel.score - _stageInfo.min; // 计算 每一分 占据 多少宽度 CGFloat widthPerScore = center.x / (margin * 6); // 根据 积分差距 和 每分占据的宽度 来计算总宽度差距 center.x -= delta * widthPerScore; if (center.x <= 0) { center.x = 0; } _scoreHint.center = center; }
-动画Block(在第一个界面的动画结束之后再显示第二个界面)
1.给Block赋值
_stageReadyView.removeBlock = ^{ _stageScoreView.stageInfo = _stageInfo; };
2.动画
#pragma mark 移除View - (void)removeView { [self removeFromSuperview]; _removeBlock(); }
3.如果没有玩过,直接不显示计分器
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。