Search code examples
ioscocos2d-iphoneaccelerometerlandscape

How to keep rollingY consistent when user flips over iDevice while in landscape mode?


In my app, I'm the game is set for landscape mode allowing the user to be able to flip the device with the game auto-rotating to match the angle. When the user tilts the device to its right, the hero will travel to the right, and when tilted to the left, the hero goes left.

I have that part figured out, but the problem comes in when the user flips the iDevice over (because of the headphone jack or placement of the speaker), the app is auto-rotated, but the rollingY is setting the hero's position.x to be inverted. Tilting left makes hero go right, and tilting right makes hero go left. After looking at the NSLogs of the accelY value when flipping around the iDevice, it doesn't seem possible to be able to reverse the position.x when rotated?

I guess this is more of a math question.

Here is my code:

-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
#define kFilteringFactor 0.75
    static UIAccelerationValue rollingX = 0, rollingY = 0, rollingZ = 0;

    rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
    rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));
    rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));

    float accelX = rollingX;
    float accelY = rollingY;
    float accelZ = rollingZ;

    NSLog(@"accelX: %f, accelY: %f, accelZ: %f", accelX, accelY, accelZ);

    CGSize winSize = [CCDirector sharedDirector].winSize;
#define kRestAccelX 0.6
#define kShipxMaxPointsPerSec (winSize.height * 1.0)
#define kMaxDiffX 0.2

#define kRestAccelY 0.0
#define kShipyMaxPointsPerSec (winSize.width * 0.5)
#define kMaxDiffY 0.2

    float accelDiffX = kRestAccelX - ABS(accelX);
    float accelFractionX = accelDiffX / kMaxDiffX;
    float pointsPerSecX = kShipxMaxPointsPerSec * accelFractionX;

    float accelDiffY = -accelY;
    float accelFractionY = accelDiffY / kMaxDiffY;
    float pointsPerSecY = kShipyMaxPointsPerSec * accelFractionY;

    _shipPointsPerSecX = pointsPerSecY;
    _shipPointsPerSecY = pointsPerSecX;

    CCLOG(@"accelX: %f, pointsPerSecX: %f", accelX, pointsPerSecX);
    CCLOG(@"accelY: %f, pointsPerSecY: %f", accelY, pointsPerSecY);
}

-(void)updateShipPos:(ccTime)dt
{
    CGSize winSize = [CCDirector sharedDirector].winSize;

    float maxX = winSize.width - _ship.contentSize.width;
    float minX = _ship.contentSize.width / 2;

    float maxY = winSize.height - _ship.contentSize.height / 2;
    float minY = _ship.contentSize.height / 2;

    float newX = _ship.position.x + (_shipPointsPerSecX * dt);
    float newY = _ship.position.y + (_shipPointsPerSecY * dt);

    newX = MIN(MAX(newX, minX), maxX);
    newY = MIN(MAX(newY, minY), maxY);

    _ship.position = ccp(newX, newY);
}

The idea is, I'm trying to make it so that pointsPerSecY is positive when tilting to the right and negative when tilted to the left. The problem is when the user flips the device, they are inverted since the device is flipped. Is there a way to make it so that it will stay positive when tilted to the right and negative to the left, no matter the orientation, when flipped while being in landscape?


Solution

  • How about to do something like this?

    if ([[UIApplication sharedApplication] statusBarOrientaion]==UIInterfaceOrientationLandscapeLeft) {
        pointsPerSecY *= -1;
    }