Search code examples
iphoneobjective-ccore-animationaccelerometermove

Best way to move UIViews in Game (Without User Interaction)


I am searching for a good and fluid way to move multiple UIViews over the Screen at once. The Action should happen when the Accelerometer detects acceleration. I have already tried this way:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{

    CGPoint ObjectPos = Object.center;

    ObjectPos.x -= acceleration.x;

    Object.center = ObjectPos;
}

(of course I added some tweaking to improve the movement detection), but all in all, it still is not very fluid.

I hoped there is some way with core animation, but it does not seem to work with the acceleration pretty well.

Help is really appreciated, thanks!


Solution

  • I advise you to read this piece of documentation: Isolating the Gravity Component from Acceleration Data and the section below that called 'Isolating Instantaneous Motion from Acceleration Data'.

    Basically, you need to filter out gravity in order to get smooth movement. The link provides sample-code.

    Edit: UIAccelerometer was deprecated in iOS 5.0, and the accompanying documentation seems to be gone as well.

    For future reference I did some digging and found, what seems to be, a 'carbon copy' of the original sample code (source):

    // This example uses a low-value filtering factor to generate a value that uses 10 percent of the
    // unfiltered acceleration data and 90 percent of the previously filtered value
    
    
    // Isolating the effects of gravity from accelerometer data
    #define kFilteringFactor 0.1
    - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
        // Use a basic low-pass filter to keep only the gravity component of each axis.
        accelX = (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor));
        accelY = (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor));
        accelZ = (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor));
        // Use the acceleration data.
    }
    
    // shows a simplified high-pass filter computation with constant effect of gravity.
    
    // Getting the instantaneous portion of movement from accelerometer data
    #define kFilteringFactor 0.1
    - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
        // Subtract the low-pass value from the current value to get a simplified high-pass filter
        accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)) );
        accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)) );
        accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) );
        // Use the acceleration data.
    }