1 Pod AVFoundation框架,ReactiveCocoa框架vim
-->從終端打開項目 cd+文件路徑 設計模式
-->建立Podfile文件 vim Podfile 多線程
-->安裝第三方框架 pod installapp
2 使用pch文件框架
-->新建pch文件異步
-->將須要用到的全局的頭文件和宏添加進去async
3 導入ttf字體文件並使用ide
-->獲取字體文件ttf函數
-->將ttf文件copy到項目中字體
-->在Info.plist中添加項
-->在Project--Build Phases--Copy Bundle Resoueces中添加資源
-->使用(要使用字體的真實名稱,而不是文件名)
二 基礎頁面的搭建
根據須要將項目分紅相應的模塊,在這裏按照頁面以及功能劃分
1 開始頁面
1-1 添加按鈕
- (void)setMainView { _startBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 20, SCREEN_WIDTH / 2, SCREEN_HEIGHT)]; _startBtn.backgroundColor = [UIColor blackColor]; _startBtn.titleLabel.font = [UIFont fontWithName:@"FZMiaoWuS-GB" size:36]; [_startBtn setTitle:@"開始遊戲 " forState:UIControlStateNormal]; WeakSelf; [[_startBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { [weakSelf buttonHideAnimation]; [weakSelf presentViewController:[[GameSceneViewController alloc] init] animated:false completion:^{ [SoundPlayer pauseBGMMusic]; }]; }]; [self.view addSubview:_startBtn];
1-2 給按鈕添加點擊事件
[_startButton rac_signalForControlEvents:UIControlEventTouchUpInside]
返回一個 RACSignal
,能夠理解爲 一個信號,用於監聽事件,後面 subscribeNext:^(id x) {}
用於訂閱信號
1-3 給按鈕添加動畫
# pragma mark : 按鈕消失/ 出現動畫 - (void)buttonHideAnimation { [UIView animateWithDuration:0.4 animations:^{ _startBtn.center = CGPointMake(- _startBtn.center.x, _startBtn.center.y); _settingBtn.center = CGPointMake(_settingBtn.center.x + SCREEN_WIDTH, _settingBtn.center.y); }]; } - (void)buttonShowAnimation { [UIView animateWithDuration:0.4 animations:^{ _startBtn.center = CGPointMake(SCREEN_WIDTH / 4, _startBtn.center.y); _settingBtn.center = CGPointMake(SCREEN_WIDTH / 4 * 3, _settingBtn.center.y); }]; }
使用的是UIView的block動畫
2 倒計時動畫頁面
- (CAAnimationGroup *)setAnimationGroup { //縮放動畫 CABasicAnimation *animation1 = [CABasicAnimation animation]; [animation1 setKeyPath:@"transform.scale"]; [animation1 setFromValue:@1.0]; [animation1 setToValue:@4.0]; [animation1 setDuration:1.0]; //透明度改變更畫 CABasicAnimation *animation2 = [CABasicAnimation animation]; [animation2 setKeyPath:@"alpha"]; [animation2 setFromValue:@1.0]; [animation2 setToValue:@0.3]; [animation2 setDuration:1.0]; CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init]; animationGroup.animations = [NSArray arrayWithObjects:animation1, animation2, nil]; [animationGroup setDuration:1.0]; [animationGroup setDelegate:self]; return animationGroup; }
使用的是CABasicAnimation基礎動畫
這個ManoBoo在簡書中已經講的很詳細了,此處略去
3 遊戲界面以及點擊按鈕以後的閃爍動畫效果
如何搭建遊戲界面,在簡書中也有很是詳細的介紹
4 點擊錯誤後彈出的失敗頁面
4-1 此處重點在於如何在xib中使用位置的綁定
4-2 點擊結束按鈕後會跳轉回開始頁面
用 presentViewController 方法進入遊戲頁面,對應的,用 dismissViewControllerAnimated 方法能夠返回
用 pushViewController 方法進入的話,則須要調用 popViewControllerAnimated 方法返回
5 設置頁面的搭建
5-1 與錯誤頁面的搭建相似,區別在於其中加入了按鈕動畫
5-1 水波紋動畫按鈕
將CABasicAnimation基礎動畫和CAKeyframeAnimation幀動畫結合使用
- (void)drawRect:(CGRect)rect{ NSInteger pulsingCount = 6;//波紋的環數 double animationDuration = 5; CALayer * animationLayer = [CALayer layer];//動畫layer for (int i = 0; i < pulsingCount; i++) { //保證波紋是個圓形 CALayer * pulsingLayer = [CALayer layer]; pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height); pulsingLayer.borderColor = [UIColor colorWithRed:54 green:83 blue:254 alpha:1].CGColor; pulsingLayer.borderWidth = 1; pulsingLayer.cornerRadius = rect.size.height / 2; //縮放動畫 CABasicAnimation * scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; scaleAnimation.fromValue = @0.8; scaleAnimation.toValue = @2.4; //關鍵幀動畫 透明度 CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; opacityAnimation.values = @[@1, @0.9, @0.8, @0.7, @0.6, @0.5, @0.4, @0.3, @0.2, @0.1, @0]; opacityAnimation.keyTimes = @[@0, @0.1, @0.2, @0.3, @0.4, @0.5, @0.6, @0.7, @0.8, @0.9, @1]; //動畫執行的速度 默認 CAMediaTimingFunction * defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; CAAnimationGroup * animationGroup = [CAAnimationGroup animation]; animationGroup.beginTime = CACurrentMediaTime() + (double)i * animationDuration / (double)pulsingCount; animationGroup.duration = animationDuration; animationGroup.repeatCount = HUGE; animationGroup.timingFunction = defaultCurve;//動畫運行的節奏 animationGroup.animations = @[scaleAnimation, opacityAnimation]; [pulsingLayer addAnimation:animationGroup forKey:nil]; [animationLayer addSublayer:pulsingLayer]; } [self.layer addSublayer:animationLayer]; }
5-2 圓形按鈕
重繪drawRect方法
- (void)drawRect:(CGRect)rect { self.backgroundColor = [UIColor clearColor]; self.layer.borderWidth = 1; self.layer.borderColor = [UIColor whiteColor].CGColor; self.layer.cornerRadius = rect.size.width / 2; }
5-3 點擊去簡書按鈕以後會跳轉到其餘頁面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.jianshu.com/users/28aed6e79eac/timeline"]];
1 分數管理器
1-1 使用 NSUserDefaults 本地存儲,對全局變量bestScore進行更新,若currentScore小於bestScore,則bestScore不變,不然,將currentScore的值賦給bestScore
+ (float)getBestScore{ NSNumber *bestScore = [[NSUserDefaults standardUserDefaults] objectForKey:BestScoreKey]; if(bestScore == nil){ [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:0.0] forKey:BestScoreKey]; bestScore = [NSNumber numberWithFloat:0.0]; } return bestScore.floatValue; } + (void)updateWithCurrentScore:(float)currentScore{ float bestScore = [self getBestScore]; bestScore = bestScore < currentScore ? currentScore : bestScore; [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:bestScore] forKey:BestScoreKey]; }
1-2 在失敗頁面中顯示出來以及在控制檯中輸出
_failureView.currentScoreLab.text = [NSString stringWithFormat:@"%.1f",_currentScore]; _failureView.historyScoreLab.text = [NSString stringWithFormat:@"最佳成績:%.f",[ScoreManager getBestScore]]; _failureView.tipLab.text = @"再接再勵哦"; NSLog(@"歷史最佳:%.1f",[ScoreManager getBestScore]); NSLog(@"當前成績:%.1f",_currentScore);
1-3 使用_currentScore來計算當前點擊正確的按鈕數,即分數,若按鈕的狀態爲勝利,則加一
if (type == CompleteTypeVictory) { _currentScore += 1.0; [[SoundPlayer shareInstance] changeSound]; [self updateClickOnTrue]; [self updateGameSpeed]; }
2 速度控制器
- (void)updateGameSpeed{ if (_currentScore < 200) { _gameSpeed = 2.5 * (1 + _currentScore / 200); }else{ _gameSpeed = 5.0; } [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:_gameSpeed] forKey:GameSpeedKey]; }
3 音樂播放器
使用AVAudioPlayer控制播放音樂
dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(dispatchQueue, ^{ //獲取音樂文件路徑 NSURL *soundUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"C-%d",i] ofType:@"wav"]]; if (!_audioPlayer) { _asset = [[AVURLAsset alloc] initWithURL:soundUrl options:nil]; //實例化音樂播放控件 _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:_asset.URL error:nil]; } if (_audioPlayer != nil) { _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"C-%d",i] ofType:@"wav"]] error:nil]; _audioPlayer.delegate = self; [_audioPlayer play]; if (i < 213) { ++i; }else{ i = 1; } }else{ NSLog(@"初始化失敗"); } });
1 單例模式
若但願一個類只有一個實例存在,同時可獲得這個特定實例提供的服務入口,那麼能夠使用單例設計模式
在整個項目中,這個累的對象只能被初始化一次,這種特性能夠用在某些須要全局共享的資源中,好比管理類,引擎類
UIApplication,NSUserDefaults等都是iOS的系統單例
static SoundPlayer *instance; //單例模式,保證只有一個soundPlayer對象 + (SoundPlayer *)shareInstance{ @synchronized(instance) { if (!instance) { instance = [[SoundPlayer alloc] init]; } return instance; } }
2 多線程
iOS中,只有主線程,才能當即刷新UI,若是是經過偵聽異步消息,觸發回調函數,或者調用異步方法,請求刷新UI,都會產生線程阻塞和延遲的問題
多線程:讓CPU在同一時間內運行兩行以上代碼
iOS是一個支持多任務的操做系統,所以在編寫iOS的多線程程序時,可分爲兩個部分:傳統的多線程處理方式(NSThread)或者使用GCD派遣隊列(Dispatch Queue)與block塊來分派程序
GCD提供了3中類型的隊列:main,concurrent,serial
main隊列:程序代碼默認運行的隊列,iOS會將全部跟可視化組件有關的運行程序放在這個隊列,main隊列必定要使用異步模式,若使用同步模式,會形成app運行程序產生死結
concurr隊列:有4 種(優先權),高優先權,中優先權,低優先權,背景取得concurrent隊列的進入點後,能夠選擇異步或同步運行
serial隊列:用戶本身建立的隊列,隊列建立時徐給出惟一識別的名字(字符串型),serial隊列必定是dispatch_sync()
每一個區塊中程序代碼在各類隊列中運行有兩種方式:同步,異步
同步:(sync)同一隊列,被設置爲同步模式的線程必定要先運行晚纔回輪到下一個線程運行:dispatch_sync()
異步:(async)同一隊列全部線程一塊兒執行:dispatch_async()
dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); dispatch_async(dispatchQueue, ^{ });
3 weakSelf
防止block的循環引用
#define WeakSelf __weak typeof(self) weakSelf = self