How to move CCSprite Using Accelerometer - iphone

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);
}

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;
}
}

Moving Ball with pan

I'm using pan gesture and after it moves I'm trying to get it to move at the angle that the touch happen. I though to get the point of the touch when the pan happened and then when the user lifted their finger. After that calculate the angle of the points and use that to move. I'm not sure what I'm doing wrong here.
-(void) dragging:(UIPanGestureRecognizer *)p{
UIView *v = p.view;
CGPoint velocity;
if(p.state == UIGestureRecognizerStateBegan){
self.origC = v.center;
self.pointIn = [p locationInView:[UIApplication sharedApplication].keyWindow];
//NSLog(#"%f",self.pointIn.x);
//pointInWindow = CGPointMake(pointIn.x, pointIn.y);
}
//NSLog(#"%f,%f orig %f, %f",pointInWindow.x, pointInWindow.y,self.origC.x,self.origC.y);
//velocity = [p velocityInView:v.superview];
//NSLog(#"x=%f",velocity.x);
//NSLog(#"y=%f",velocity.y);
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
CGPoint delta = [p translationInView:v.superview];
CGPoint c = self.origC;
c.x += delta.x;
c.y += delta.y;
v.center = c;
}completion:nil];
if(p.state == UIGestureRecognizerStateEnded){
CGPoint lastPoint = [p locationInView:[UIApplication sharedApplication].keyWindow];
NSLog(#"orig %f , last %f",self.pointIn.x,lastPoint.x);
self.lateC = v.center;
CGFloat deltaX = self.pointIn.x - lastPoint.x;
CGFloat deltaY = self.pointIn.y - lastPoint.y;
double angle = atan(deltaX/deltaY) * 180/M_PI;
if(angle < 0)
angle += 360;
//NSLog(#"%f",angle);
self.addy = angle;
self.addx = angle;
}
}
This is in my ViewController :
-(void) animateBalls:(NSTimer*) time{
for(Ball *balls in self.view.subviews){
[UIView beginAnimations:nil context:nil];
//[UIView setAnimationRepeatAutoreverses:NO];
CGFloat x;
CGFloat y;
for(Ball *subBalls in self.view.subviews){
if(balls != subBalls)
if((CGRectIntersectsRect([balls frame], [subBalls frame]))){
[subBalls changeDirectionX];
[subBalls changeDirectionY];
}
}
CGPoint point = balls.center;
if(point.x + 25 > self.view.bounds.size.width)
[balls changeDirectionX];
if(point.x - 25 < 0)
[balls changeDirectionX];
if(point.y + 25 > self.view.bounds.size.height)
[balls changeDirectionY];
if(point.y - 25 < 0)
[balls changeDirectionY];
if(balls.directionX == 1){
x = point.x + (2 * cos(balls.addx));
}
else{
x = point.x - (2 * cos(balls.addx));
//balls.addx;
}
if(balls.directionY == 1){
y = point.y + (2 * sin(balls.addx));
}
else
y = point.y - (2 * sin(balls.addx));
//balls.addy;
//CGFloat x = (CGFloat) random()/(CGFloat) RAND_MAX * self.view.bounds.size.width;
//CGFloat y = (CGFloat) random()/(CGFloat) RAND_MAX * self.view.bounds.size.height;
CGPoint squarePostion = CGPointMake(x, y);
balls.center = squarePostion;
[UIView commitAnimations];
//[self.view setNeedsDisplay];
}
}

Accelerometer based movement

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.

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.