Accelerometer based movement - iphone

Now woking on game that uses accelerometer to move player sprite left and right.
I used this tutorial: COCOS2D_ACCELEROMETER_MOVEMENT
This works only sometime….some time not move..How can I resolve this problem?
Here is my sample: See this Sample
Thanks for reading this…what's wrong with my code ? Is there any other way?
Here is my code:
#define kHeroMovementAction 1
#define kPlayerSpeed 500
- (void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
// use the running scene to grab the appropriate game layer by it's tag
// grab the player sprite from that layer using it's tag
CCSprite *playerSprite = mPlayer;
float destX, destY;
BOOL shouldMove = NO;
float currentX = playerSprite.position.x;
float currentY = playerSprite.position.y;
if(acceleration.x > 0.25) { // tilting the device upwards
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else if (acceleration.x < -0.25) { // tilting the device downwards
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else
if(acceleration.y < -0.25) { // tilting the device to the right
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else if (acceleration.y > 0.25) { // tilting the device to the left
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else {
destX = currentX;
destY = currentY;
}
if(shouldMove)
{
CGSize wins = [[CCDirector sharedDirector] winSize];
// ensure we aren't moving out of bounds
if(destX < 30 || destX > wins.width - 30 || destY < 30 || destY > wins.height - 100) {
// do nothing
} else {
CCAction *action = [CCMoveTo actionWithDuration:0.5f position: CGPointMake(destX, playerSprite.position.y)];
[playerSprite stopActionByTag:kHeroMovementAction];
[action setTag:kHeroMovementAction];
[playerSprite runAction:action];
}
} else {
// should stop
[playerSprite stopActionByTag:kHeroMovementAction];
}
}
Updates: Here is best way to do this.

You should look at Ray Wenderlich's scrolling tutorial here
His accelerometer part is near the bottom of the page.

Related

How to make background repeat in vertical direction using parallax

I have been looking to make background repeat in vertical direction but there is always some flickering..
I searched a lot on goggle and some book for reference but not able to find a proper reply
There are lot of proper reply for background repeat on horizontal direction
-(void) update:(ccTime)delta
{
CCSprite* sprite;
CCARRAY_FOREACH([spriteBatch children], sprite)
{
NSNumber* factor = [speedFactors objectAtIndex:sprite.zOrder];
CGPoint pos = sprite.position;
pos.y -= scrollSpeed * [factor floatValue] * (delta * 50);
if (pos.y < -screenSize.height)
{
pos.y += (screenSize.height * 2) - 2;
}
sprite.position = pos;
}
}
Loading new background each time? I strongly suspect flickering is caused by loading time in texture. You can use threaded loading to avoid flickering.
Here is once other question with something similar problem.
Continuous-horizontal-scrolling-of-background-in-cocos2d: Refer my answer
Continuous vertical scroll:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define MM_BG_SPEED_DUR ( IS_IPAD ? (6.0f) : (2.0f) )
-(void)onEnter
{
[super onEnter];
[self initBackground];
[self schedule: #selector(tick:)];
}
-(void)initBackground
{
NSString *tex = #"BG/Background.png";//[self getThemeBG];
mBG1 = [CCSprite spriteWithFile:tex];
mBG1.position = ccp(s.width*0.5f,s.height*0.5f);
[self addChild:mBG1 z:LAYER_BACKGROUND];
mBG2 = [CCSprite spriteWithFile:tex];
mBG2.position = ccp(s.width*0.5f,s.height*0.5f+mBG1.contentSize.Height);
mBG2.flipY = true;
[self addChild:mBG2 z:LAYER_BACKGROUND];
}
-(void)scrollBackground:(ccTime)dt
{
CGSize s = [[CCDirector sharedDirector] winSize];
CGPoint pos1 = mBG1.position;
CGPoint pos2 = mBG2.position;
pos1.y -= MM_BG_SPEED_DUR;
pos2.y -= MM_BG_SPEED_DUR;
if(pos1.y <=-(s.height*0.5f) )
{
pos1.y = pos2.y + mBG2.contentSize.height;
}
if(pos2.y <=-(s.height*0.5f) )
{
pos2.y = pos1.y + mBG1.contentSize.height;
}
mBG1.position = pos1;
mBG2.position = pos2;
}
-(void)tick:(ccTime)dt
{
[self scrollBackground:dt];
}

"Ghost rectangle" affecting program?

Yesterday there was a rectangle stuck in the top corner of my program, and for some reason no matter what I did I could not get it out of there. Today I re-ran the program, and it disappeared, but I believe it's memory is still stuck because it's affecting my code.
I'm trying to detect when rectangle A (motioned by accelerometer) contacts rectangle B (randomly placed; motionless). Nothing happens when A contacts B, however when I move A into the top corner where the ghost rectangle was all of yesterday it runs my if statement continuously until I move it away.
Here is the code just incase it's needed
#synthesize Button;
#synthesize Rand;
//Awaking the accelerometer
-(void) awakeaccelerometer
{
[[UIAccelerometer sharedAccelerometer]setUpdateInterval:1.0/50.0];//<---Sensitivity
[[UIAccelerometer sharedAccelerometer]setDelegate:self];
NSLog(#"Accelerometer is awake");
float randX = arc4random() % 320;
float randY = arc4random() % 548;
CGPoint randNewPlace = CGPointMake(randX, randY);
Rand.center = randNewPlace;
}
//Controlling the accelerometer
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
#define MovingObjectRadius 4
//Acceleration for player
valueX = acceleration.x * 10; //speeds
valueY = acceleration.y * -10; //speeds
//Create new integers
int newX = (int)(Button.center.x + valueX);
int newY = (int)(Button.center.y + valueY);
//Position Validate...This stops the movements from going past the screen; 320 pixels
//For X
if (newX > (320 - MovingObjectRadius))
{
newX = (320 - MovingObjectRadius);
}
if (newX < (0 + MovingObjectRadius))
{
newX = (0 + MovingObjectRadius);
}
//For Y
if (newY > (548 - MovingObjectRadius))
{
newY = (548 - MovingObjectRadius);
}
if (newY < (0 + MovingObjectRadius))
{
newY = (0 + MovingObjectRadius);
}
//Make the new point
CGPoint buttonNewCenter = CGPointMake(newX,newY);
Button.center = buttonNewCenter;
CGRect blockRect = CGRectMake(newX, newY, 20, 20);
CGRect targetRect = CGRectMake(randX, randY, 20, 20);
if (CGRectIntersectsRect(blockRect, targetRect))
{
float tnewX = arc4random() % 320;
float tnewY = arc4random() % 548;
CGPoint randNewPl = CGPointMake(tnewX, tnewY);
Rand.center = randNewPl;
}
}

How to move CCSprite Using Accelerometer

hi I am developing a cocos2d Game. I want to move CCSprite with accelerometer value change. I have implemented this code for accelerometer. but in landscape position tilt iphone sprite is moving up and down. but i want to move sprite forward and backward.
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1/60];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[self scheduleUpdate];
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.4f;
float sinsitivity = 6.0f;
//float maxVelocity = 100;
// because we are in landscape mode where x is always +90 or -90
// float acely = acceleration.x;
float acelx = acceleration.y;
movement = movement * deceleration + acelx * sinsitivity;
float angleRadians = atanf((float)acceleration.y / (float)acceleration.x);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
// float cocosAngle = angleDegrees;
if(angleDegrees<85 && angleDegrees >-85 )
{
_player.rotation = angleDegrees;
}
//NSLog(#" angle = %f",angleDegrees);
if([ShieldCover visible]==TRUE)
{
ShieldCover.rotation= angleDegrees;
}
// CGPoint converted = ccp( (float)acceleration.y, (float)acceleration.x);
// update the rotation based on the z-rotation
// the sprite will always be 'standing up'
//_player.rotation = (float) CC_RADIANS_TO_DEGREES( atan2f( converted.x, converted.y) + M_PI );
// ShieldCover.rotation =(float) CC_RADIANS_TO_DEGREES( atan2f( converted.x, converted.y) + M_PI );
}
- (void)update:(ccTime)delta {
//assuming that you have a sprite called _fireman with 100 px width
if ( _player.position.y > 0 && _player.position.y < 320) {
//_fireman is at neither edge of the screen so move the paddle!
_player.position = ccp(_player.position.x, _player.position.y + movement);
}
if ( _player.position.y < 0 ) {
//_fireman hit the left edge of the screen, set the left bound position with no movement.
_player.position = ccp( _player.position.x, 319);
}
if ( _player.position.y > 320 ) {
//_fireman hit the right edge of the screen, set the right bound position with no movement.
_player.position = ccp(_player.position.x, 1 );
}
if ( _player.position.y < 1 && movement > 1 ) {
//_fireman is at the left edge of the screen and the device is tiled right. Move the _fireman!
_player.position = ccp(_player.position.x , _player.position.y+ movement);
}
if ( _player.position.y > 319 && movement < 0) {
//_fireman is at the right edge of the screen and the device is tiled left. Move the _fireman!
_player.position = ccp(_player.position.x , _player.position.y+ movement);
}
barracuda.position = ccp(barracuda.position.x,_player.position.y);
particles.position = ccp(_player.position.x-30, _player.position.y-10);
parteMagnet.position = ccp(_player.position.x, _player.position.y);
}
// Try this
-(id) init
{
if (self == [super init])
{
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1/60];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[self scheduleUpdate];
}
return self;
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.4f;
float sinsitivity = 6.0f;
float acelx = acceleration.y;
movement = movement * deceleration + acelx * sinsitivity;
float angleRadians = atanf((float)acceleration.y / (float)acceleration.x);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
if(angleDegrees<85 && angleDegrees >-85 )
{
_player.rotation = angleDegrees;
}
if([ShieldCover visible]==TRUE)
{
ShieldCover.rotation= angleDegrees;
}
}
- (void)update:(ccTime)delta
{
if ( _player.position.y > 0 && _player.position.y < 320)
{
_player.position = ccp(_player.position.x, _player.position.y + movement);
}
if ( _player.position.y < 0 )
{
_player.position = ccp( _player.position.x, 319);
}
if ( _player.position.y > 320 )
{
_player.position = ccp(_player.position.x, 1 );
}
if ( _player.position.y < 1 && movement > 1 )
{
_player.position = ccp(_player.position.x , _player.position.y+ movement);
}
if ( _player.position.y > 319 && movement < 0)
{
_player.position = ccp(_player.position.x , _player.position.y+ movement);
}
barracuda.position = ccp(barracuda.position.x,_player.position.y);
particles.position = ccp(_player.position.x-30, _player.position.y-10);
parteMagnet.position = ccp(_player.position.x, _player.position.y);
}

cocos2d + Accelerometer issue

I finished my game (cocos2d) but when I make an archive (from xcode product->Archive) then click on share (to get game.api) then put it in the itunes and sync to my iphone the accelerometer it seem that it didn't work I tested the game in 5 devices and it didn't work, the ship always in fix place and it didn't move, But if I click build and go from the xcode it work properly on all the developer devices I use the code below :
inside the init
- (id)init
{
if ((self = [super init]))
{
self.isAccelerometerEnabled = YES;
[self scheduleUpdate];
}
accelerometer handeler:
- (void)accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration {
#define kFilteringFactor 0.1
UIAccelerationValue rollingX, rollingY, rollingZ;
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 = acceleration.x - rollingX;
CGSize winSize = [CCDirector sharedDirector].winSize;
#define kRestAccelX 0.6
#define kShipMaxPointsPerSec (winSize.height*0.5)
#define kMaxDiffX 0.2
float accelDiffX = kRestAccelX - ABS(accelX);
float accelFractionX = accelDiffX / kMaxDiffX;
float pointsPerSecX = kShipMaxPointsPerSec * accelFractionX;
_shipPointsPerSecY = pointsPerSecX;
}
ship position:
- (void)updateShipPos:(ccTime)dt {
CGSize winSize = [CCDirector sharedDirector].winSize;
float maxY = winSize.height - _ship.contentSize.height/2;
float minY = _ship.contentSize.height/2;
float newY ;
(isYAxisInverted) ? newY = _ship.position.y + (-_shipPointsPerSecY * dt) : newY = _ship.position.y + (_shipPointsPerSecY * dt);
newY = MIN(MAX(newY, minY), maxY);
_ship.position = ccp(_ship.position.x, newY);
}
and in the update :
- (void)update:(ccTime)dt {
...
[self updateShipPos:dt];
...}
the solution is to replace:
UIAccelerationValue rollingX;
by
UIAccelerationValue rollingX = 0, rollingY = 0, rollingZ = 0;

iPhone, cocos2d and accelerometer

I'm reading 'Learn iPhone and iPad Cocos2D Game Development' and in chapter 4, there's a simple sample using accelerometer. It works well if I use x-axis only as the book but with y-axis, sprite's movement is not smooth if it on the edge of the screen.
+ (id)scene
{
CCScene* scene = [CCScene node];
CCLayer* layer = [GameScene node];
[scene addChild:layer];
return scene;
}
- (id)init
{
if ((self = [super init]))
{
CCLOG(#"%#: %#", NSStringFromSelector(_cmd), self);
self.isAccelerometerEnabled = YES;
player = [CCSprite spriteWithFile:#"alien.png"];
[self addChild:player z:0 tag:1];
CGSize screenSize = [[CCDirector sharedDirector] winSize];
float imageHeight = [player texture].contentSize.height;
player.position = CGPointMake(screenSize.width / 2, imageHeight / 2);
[self scheduleUpdate];
}
return self;
}
- (void)dealloc
{
CCLOG(#"%#: %#", NSStringFromSelector(_cmd), self);
[super dealloc];
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.4f;
float sensitivity = 6.0f;
float maxVelocity = 100;
playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity;
playerVelocity.y = playerVelocity.y * deceleration + acceleration.y * sensitivity;
if (playerVelocity.x > maxVelocity)
{
playerVelocity.x = maxVelocity;
}
else if (playerVelocity.x < -maxVelocity)
{
playerVelocity.x = -maxVelocity;
}
if (playerVelocity.y > maxVelocity)
{
playerVelocity.y = maxVelocity;
}
else if (playerVelocity.y < -maxVelocity)
{
playerVelocity.y = -maxVelocity;
}
}
- (void)update:(ccTime)delta
{
CGPoint pos = player.position;
pos.x += playerVelocity.x;
pos.y += playerVelocity.y;
CGSize screenSize = [[CCDirector sharedDirector] winSize];
float imageWidthHalved = [player texture].contentSize.width * 0.5f;
float leftBorderLimit = imageWidthHalved;
float rightBorderLimit = screenSize.width - imageWidthHalved;
if (pos.x < leftBorderLimit)
{
pos.x = leftBorderLimit;
playerVelocity = CGPointZero;
}
else if (pos.x > rightBorderLimit)
{
pos.x = rightBorderLimit;
playerVelocity = CGPointZero;
}
float imageHeightHalved = [player texture].contentSize.height * 0.5f;
float topBorderLimit = screenSize.height - imageHeightHalved;
float bottomBorderLimit = imageHeightHalved;
if (pos.y < bottomBorderLimit)
{
pos.y = bottomBorderLimit;
playerVelocity = CGPointZero;
}
else if (pos.y > topBorderLimit)
{
pos.y = topBorderLimit;
playerVelocity = CGPointZero;
}
player.position = pos;
}
What's the problem?
If you want you can try what I did in my game:
#define SIGN(x) ((x < 0.0f) ? -1.0f : 1.0f)
- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration {
float kFilteringFactor = 0.01;
accels[0] = acceleration.x * kFilteringFactor + accels[0] * (1.0f - kFilteringFactor);
accels[1] = acceleration.y * kFilteringFactor + accels[1] * (1.0f - kFilteringFactor);
accels[2] = acceleration.z * kFilteringFactor + accels[2] * (1.0f - kFilteringFactor);
float xx;
float yy;
// extract the acceleration components
xx = -[acceleration x];
yy = [acceleration y];
// Has the direction changed?
float accelDirX = SIGN(xvelocity) * -1.0f;
float newDirX = SIGN(xx);
float accelDirY = SIGN(yvelocity) * -1.0f;
float newDirY = SIGN(yy);
// Accelerate. To increase viscosity, lower the values below 1.0f
if (accelDirX == newDirX)
xaccel = (abs(xaccel) + 0.99f) * SIGN(xaccel);
if (accelDirY == newDirY)
yaccel = (abs(yaccel) + 0.99f) * SIGN(yaccel);
// Apply acceleration changes to the current velocity
xvelocity = -xaccel * xx;
yvelocity = -yaccel * yy;
[sprite moveByAccelerometerX:yvelocity Y:xvelocity];
}
First of all, thanks for reading my book! :)
You can find an improved filtering method (ease exponential) that I'm using in this article, it also contains basic info on how the accelerometer works.
You can learn more about accelerometer input from the Tilt to Live developers and their approach, comes with a sample project.
I have bought the book and I found that the edge of screen collision detection doesn't work properly unless you have the same size sprite as in the example. Either make your sprite the same size or make the sprite wrap around the screen instead of stopping, which is what I did.