如何最好地给落球真实世界的引力

时间:2014-03-27 20:39:34

标签: ios objective-c sprite-kit game-physics core-motion

我是一个相当新的应用程序开发人员,也是Sprite Kit的新手。我正在创造一个游戏,我想要一个球总是向下坠落,好像它是在重力。这只是一个2D应用程序,所以我想要的是当球落下时,当你向左倾斜手机时,球向下移动并离开屏幕,如果你向右倾斜手机,球会在屏幕上向下移动。为了更好地了解我想要的东西,我在photoshop中制作了一个快速图表:

Ball falling diagram

我想了解一些最简单,最好的方法。我的第一个想法是记录偏航并用它来决定球向左或向右移动的距离。这需要一些计算才能使球完全落在90度,虽然听起来对我来说很可能,但我不确定它是否真的有可能。

有人认为这是做到这一点的方法还是有更好的方法呢?

我在尝试第一个想法时遇到的一个问题是当我倾斜手机时,球左右移动(没有任何正确的计算,因此它完全不准确),我会将手机向左倾斜(对于例如)我进一步倾斜它,它变得越不敏感,所以球将向左移动更少。这会阻止我的想法工作,我不确定是否有办法绕过它。

我遇到的一个更大的问题是,当我在座位上转身时,偏航也会发生变化!我认为这与指南针有关,因为滚动或音高都没有像我这样改变。我确信可以做些什么来纠正这个问题,因为我玩游戏时使用陀螺仪从来没有这个问题。如果有人能指出我正确的方向,我会很感激,或者我可能只是在一个单独的新问题中提出这个问题。下面是我在photoshop中快速绘制的另一个图表,以帮助解释问题。图1是我希望能够倾斜手机的方式,但当你转身时(图2),球会向左或向右移动,具体取决于你转动的距离。 (是的,这是指在图2中持有电话的人)

phone tilt diagram

非常感谢帮助!

3 个答案:

答案 0 :(得分:11)

这是我刚刚从我建立的一个演示项目中抽出的一些代码。这是通过将一堆视图与UIKit Dynamics连接而创建的一条绳索。根据您的描述,我认为行为与您正在寻找的行为相同。

需要注意的是,此代码遵循真正的重力方向,因此如果您将手机设置为平面,则在与屏幕平行的平面中,重力将为0或接近0,因为其完整幅度将沿着z轴。您可能希望对其进行标准化,以使方向发生变化,但幅度保持不变。

在此示例中,self.gravityUIGravityBehavior,但您可以使用相同的代码来提供您想要的任何类型的重力模拟。只需注销运动管理器处理程序中的值,即可查看可能获得的值。

self.motionManager = [[CMMotionManager alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:self.motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error) {
    CMAcceleration gravity = motion.gravity;
    dispatch_async(dispatch_get_main_queue(), ^{
        self.gravity.gravityDirection = CGVectorMake(gravity.x, -gravity.y);
    });
}];

我希望这有帮助!

答案 1 :(得分:3)

这是SpriteKit的解决方案:

1.创建一个新的SpriteKit项目 enter image description here

2.添加CoreMotion框架

enter image description here

3.在您的MyScene'中导入新框架。类:

#import <CoreMotion/CoreMotion.h>

4.示例针对此方向进行了优化:

enter image description here

5.将此代码添加到&#39; touchesBegan&#39; “MyScene”的方法&#39;类

    sprite.size = CGSizeMake(20, 20);
    sprite.physicsBody= [SKPhysicsBody bodyWithCircleOfRadius:sprite.size.width/2];

6.将此代码添加到&#39;更新&#39; “MyScene”的方法&#39;类

CMMotionManager *_motionManager;
-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
    if (_motionManager== nil) {
        _motionManager=[[CMMotionManager alloc]init];
        _motionManager.deviceMotionUpdateInterval=0.025;
        [_motionManager startDeviceMotionUpdates];
    }

    CMAcceleration gravity=  _motionManager.deviceMotion.gravity;
    self.physicsWorld.gravity = CGVectorMake(gravity.y*4, -gravity.x/4);

}

你必须四处寻找重力的最佳因素。

希望这是有用的

答案 2 :(得分:0)

快捷代码:

 if motion.isDeviceMotionAvailable {
            self.motion.deviceMotionUpdateInterval = 1.0 / 60.0
            self.motion.showsDeviceMovementDisplay = true
            self.motion.startDeviceMotionUpdates(using: .xMagneticNorthZVertical)
            // Configure a timer to fetch the motion data.
            self.timer = Timer(fire: Date(), interval: (1.0/60.0), repeats: true,
                               block: { (timer) in
                                if let data = self.motion.deviceMotion {
                                  let gravityData = data.gravity
                                  scene.physicsWorld.gravity = CGVector(dx: 9.8 * (gravityData.x), dy: 9.8 * (gravityData.y))
                                }
            })
            // Add the timer to the current run loop.
            RunLoop.current.add(self.timer, forMode: .defaultRunLoopMode)
          }