NSBundle *mainBundle = [NSBundle mainBundle]; farSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"farSound" ofType:@"caf"]]; nearSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"nearSound" ofType:@"caf"]]; levelSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"levelSound" ofType:@"caf"]];
利用ios设备的重力加速感应,来测量平面的水平位置。有加速度分量,则说明表面有倾斜.
1.AppDelegate中用+(void)initialize来初始化数据,但是里面不能给NSNotificationCenter addObserver,会报错
//initialize是个很好的初始化数据的地方 + (void)initialize { if ([self class] == [LevelAppDelegate class]) { NSNumber *defaultCalibrationOffset = [NSNumber numberWithFloat:0.0]; //为用户setting数据提供默认值 NSDictionary *resourceDict = [NSDictionary dictionaryWithObject:defaultCalibrationOffset forKey:BubbleLevelCalibrationOffsetKey]; [[NSUserDefaults standardUserDefaults] registerDefaults:resourceDict]; } }
在应用结束时,将其保存,这样下次打开时,在启动的时候就可以获取上次保存的数值
- (void)applicationWillTerminate:(UIApplication *)application { //退出程序前保存本次数据 float calibrationOffset = levelViewController.calibrationOffset; NSNumber *offset = [NSNumber numberWithFloat:calibrationOffset]; [[NSUserDefaults standardUserDefaults] setObject:offset forKey:BubbleLevelCalibrationOffsetKey]; }
2.重力感应
设置delegate,设置的对象需要实现UIAccelerometerDelegate接口
,设置部分参数,主要是更新的间隔,根据不同的应用需求,设置不一样的更新间隔,因为这个功能十分耗电
-(id) init { if (self = [super init]) { [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kUpdateFrequency)]; [[UIAccelerometer sharedAccelerometer] setDelegate:self]; } return self; }UIAccelerometerDelegate的方法
这个就是根据设置的间隔时间触发该方法,值得注意的是里面有个重力感应常用的方法,利用低通来实现一个重力感应缓慢变化的一个过程
// UIAccelerometer delegate method, which delivers the latest acceleration data. - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { // Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes //个人感觉就是让动画影响缓慢点 kFilteringFactor=0.05 accelerationX = acceleration.x * kFilteringFactor + accelerationX * (1.0 - kFilteringFactor); accelerationY = acceleration.y * kFilteringFactor + accelerationY * (1.0 - kFilteringFactor); // keep the raw reading, to use during calibrations currentRawReading = atan2(accelerationY, accelerationX); float calibratedAngle = [self calibratedAngleFromAngle:currentRawReading]; [levelView updateToInclinationInRadians:calibratedAngle]; }
代码种涉及到2个UIView界面,他们共同使用了同一个Controller,所以它自定义了一个初始化方法,我们可以看到,调用该初始化方法时,它还传入了一个Controller,例子中就是根控制器,这个我觉得在平时写代码种可以经常利用,是个相当不错的思路,此外注意的是,view中的Controller一般来说是assign的。
- (id)initWithFrame:(CGRect)frame viewController:(LevelViewController *)aController { self = [super initWithFrame:frame]; if (self != nil) { self.viewController = aController; } return self; }
里面利用了判断2个view是否有superview来获得当前view是否在显示状态中,不错的方法!
- (void)flipAction:(id)sender { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:kTransitionDuration]; [UIView setAnimationTransition:([levelView superview] ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.view cache:YES]; if ([calibrationView superview]) { [calibrationView removeFromSuperview]; [self.view addSubview:levelView]; } else { [levelView removeFromSuperview]; [calibrationView resetToInitialState:self]; [self.view addSubview:calibrationView]; } [UIView commitAnimations]; }
5.音乐播放
初始化音乐文件,一共三种音效,分别代表水平偏离位置的远,近,中
NSBundle *mainBundle = [NSBundle mainBundle]; farSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"farSound" ofType:@"caf"]]; nearSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"nearSound" ofType:@"caf"]]; levelSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"levelSound" ofType:@"caf"]];调用方法,例子中根据一个参数,判断距离,从而决定播放的音效是哪个
- (void)updateLevelSoundForAngle:(float)angle { float absAngle = fabs(angle); if (absAngle <= kMaxVariationForLevelSound) { [levelSound play]; } else if (absAngle <= kMaxVariationForNearSound) { [nearSound play]; } else if (absAngle <= kMaxVariationForFarSound) { [farSound play]; } }实际调用方法,可以看到增加了一个控制变量,每10次才调用以此音乐播放,否则太过频繁
soundUpdateCounter++; if (soundUpdateCounter == 10) { // update sound at a tenth the rate of the animation [self updateLevelSoundForAngle:rotation]; soundUpdateCounter = 0; }