long time reader first time poster and so on.
My problem is this, Currently i am moving a sprite around the screen of an iPod touch (landscape) using the accelerometer x and y values and cocos2d. The user can calibrate where the accelerometer zero point is by touching the screen, this just grabs the current x and y values ready to subtract from the accelerometer while the app is running. This allows the user to select a comfortable position to hold the iPod.
This works fine when the iPod is sat flat on its back on the desk or held in the hand and tilted slightly towards me on the x axis when calibrated, the sprite will move at the same speed up and down the screen when tilted on the x axis.
However the further towards me the screen is tilted when calibrated something odd happens (well something i didn't expect anyway). If i the screen tilt on the x axis away from me the sprite moves up the screen at the usual speed or faster, if i tilt the screen towards me on the x axis the sprite moves down the screen much slower or sometimes not at all.
Looking at the accelerometer values for x i realised that when the iPod it tipped all the way towards me it is close to 0 with tilting away or towards me counting less than or more than 0. I have a feeling it could be because of this but am unsure of how to progress, Has anyone run into this problem before and managed to find a solution?
Here is the code i have so far.
TestLayer.H
@interface TestSceneLayer : CCLayer {
CCSprite *redShip;
float movementX, movementY;
float xCallib, yCallib;
BOOL willMoveX, willMoveY;
}
TestLayer.m
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
// Set up variables
CGSize winSize = [CCDirector sharedDirector].winSize;
UIAccelerationValue rollingX, rollingY, rollingZ;
float accelX, accelY, accelZ;
invertedControlls = NO;
// High pass filter for reducing jitter
rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
rollingY = (-acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));
accelX = acceleration.x - rollingX;
accelY = acceleration.y - -rollingY;
// Calculate movement for x and y axis
float accelDiffX = accelX - kRestAccelX;
float accelFractionX = accelDiffX / kMaxDiff;
movementY = kShipMaxPointsPerSec * accelFractionX;
float accelDiffY = accelY - kRestAccelY;
float accelFractionY = accelDiffY / kMaxDiff;
movementX = kShipMaxPointsPerSec * accelFractionY;
// Thresh holds for x and y axis movement
willMoveX = YES;
willMoveY = YES;
if (((movementX < 70.0f) && (movementX > -70.0f))) willMoveX = NO;
else if (((movementY < 70.0f) && (movementY > -70.0f))) willMoveY = NO;
}
- (void) applyAccelerometerToNode:(CCNode*)tempNode ForTime:(ccTime)dTime {
// temp node is the sprite being moved
CGSize screenSize = [[CCDirector sharedDirector]winSize];
float oldX = [tempNode position].x;
float oldY = [tempNode position].y;
float newX, newY;
if (willMoveY) {
newY = [tempNode position].y + (movementY * dTime);
} else newY = oldY;
if (willMoveX) {
newX = [tempNode position].x - (movementX * dTime);
} else newX = oldX;
// Constrain movement on screen to stop it shooting off like a little bastard
if ((newY > (screenSize.height - 40.0f)) || newY < 40.0f ) {
newY = oldY;
}
if ((newX > (screenSize.width -40)) || newX < 40.0f ) {
newX = oldX;
}
[tempNode setPosition:ccp(newX,newY)];
}
- (void) update:(ccTime)deltaTime {
[self applyAccelerometerToNode:redShip ForTime:deltaTime];
}
- (id) init {
if (([super init])) {
CCLOG(@"TestSceneLayer --> Layer init");
CGSize screenSize = [[CCDirector sharedDirector]winSize];
[self scheduleUpdate];
self.isTouchEnabled = YES;
self.isAccelerometerEnabled = YES;
// Grab the default Accelerometer values
xCallib = [GameManager sharedGameManager].xCallib;
yCallib = [GameManager sharedGameManager].yCallib;
// Setup and add children
redShip = [CCSprite spriteWithFile:@"red_ship.png"];
[redShip setPosition:ccp(50.0f, screenSize.height / 2)];
[redShip setScaleX:screenSize.width/1024.0f];
[redShip setScaleY:screenSize.height/768.0f];
[self addChild:redShip];
}
return self;
}
Constants.h
#define kFilteringFactor 0.1
#define kShipMaxPointsPerSec (winSize.height*0.5)
#define kRestAccelX (xCallib)
#define kMaxDiff 0.2
#define kRestAccelY (yCallib)
#define kMaxDiffY 0.1
I am thinking perhaps that i am attacking the x y values the wrong way and the maths is just all wrong. I want the user to be able to use the application from any position. Any help or pointer in the right direction will be greatly appreciated. If you need to know anything else please ask. I hope i managed to make myself clear.
Regards, James.