需求:
kids 在答题的时候手拿设备根据倾斜度将小球滚动对应的hole中代表选中答案。
现实:
基本思路:
利用CoreMotion中提供的陀螺仪和加速计来检测当前设备的倾斜度和当前在xy坐标方向小球的速度来实现小球的移动
1.控制小球的移动方向:
通过 CMMotionManager 来实时获取设备当前的状态,然后更新小球的移动方向。
2. 控制小球的速度,实现小球根据设备的倾斜度以不同的速度移动
2.1根据小球当前在xy坐标方向上的速度来计算小球当前的加速度,在计算单位时间内小球移动的距离,并更新小球的位置.
2.2利用 UIDynamicAnimator 来实现。
具体实现:
CMMotionManager的使用很简单,可以看这篇文章 [https://www.jianshu.com/p/c4fff00b50ff](https://www.jianshu.com/p/c4fff00b50ff)
这里主要说下第二个问题和其他一些坑:
控制小球速度2.1 实现代码:
- (void)updateLocation {
static NSDate *lastUpdateTime = nil;
if (lastUpdateTime) {
//计算两次更新之间有多长时间
NSTimeInterval updatePeriod = [[NSDate date] timeIntervalSinceDate:lastUpdateTime];
//计算球现在的速度。速度= 速度 + 加速度*时间
self.ballXVelocity = self.ballXVelocity + (self.accelleration.x * updatePeriod);
self.ballYVelocity = self.ballYVelocity + (self.accelleration.y * updatePeriod);
//设置当前的imageView的中心点。后面乘以5000,是为了让小球位移的快一些,很明显能够看到效果。
//横屏
CGPoint point = CGPointMake(self.currentPoint.x + self.ballXVelocity * updatePeriod * KSpeedVelocity, self.currentPoint.y - self.ballYVelocity * updatePeriod * KSpeedVelocity);
[self updateCurrentPoint:point];
}
//更新时间
lastUpdateTime = [NSDate date];
}
2.2利用 UIDynamicAnimator 来实现。首先大家可以先看下这篇文章https://www.jianshu.com/p/e34dfae218f3 熟悉下UIDynamicAnimator的使用。
看具体实现:
//开启小球的游戏
- (void)playBall{
if ([self.manager isDeviceMotionAvailable]) {
self.manager.deviceMotionUpdateInterval = 1 /60;
__weak __typeof(&*self) weakSelf = self;
[self.manager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
double gravityX = motion.gravity.x;
double gravityY = motion.gravity.y;
NSString *velocityX = [NSString stringWithFormat:@"%0.2f",fabs(gravityX)] ;
NSString *velocityY = [NSString stringWithFormat:@"%0.2f",fabs(gravityY)];
if ([velocityX floatValue] > 0 && [velocityY floatValue] > 0) {
// self.gyroscopeBallView.accelleration = motion.gravity;
// 开启主队列异步线程,更新球的位置。
dispatch_async(dispatch_get_main_queue(), ^{
double xy = 0.0;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (orientation == UIInterfaceOrientationPortrait) {
xy = atan2(gravityX, gravityY);
[weakSelf.pushBehvior1 setPushDirection:CGVectorMake(gravityX, gravityY)];
}else if (orientation == UIInterfaceOrientationLandscapeLeft) {
xy = atan2(gravityY, -gravityX);
[weakSelf.pushBehvior1 setPushDirection:CGVectorMake(gravityY, -gravityX)];
}else if (orientation == UIInterfaceOrientationLandscapeRight) {
xy = atan2(-gravityY, gravityX);
[weakSelf.pushBehvior1 setPushDirection:CGVectorMake(-gravityY, gravityX)];
}else {
}
// 计算相对于y轴的重力方向
weakSelf.gravityBehavior.angle = xy-M_PI_2;
[self.ball updateBallCenter];
self.resultLable.text = [self getCorrectAnswer];
});
}
看完代码是不是觉得很简单,现在说下需要注意的地方:
- 计算小球速度的方法2.1和2.2 对比,亲测方法2.2 比较好,因为2.1会出现卡顿的情况而且小球的回弹效果2.2的实现方式也比较好。
-
要注意一点在设备横竖屏下重力在xy坐标上的大小和设备屏幕坐标系直接是存在一定的差异性的,自己手绘了一张图大家可以参考下:
image.png
总结:
大家可以自己动手实践下,这里主要给出一些自己的心得体会和一些需要注意的地方
最后给大家推荐个不错的公众号 "说神码",或者大家可以扫描下面的二维码关注

网友评论