Detecting that the device moved - iphone

I am creating a motion detection alarm for the iPhone. This alarm will be set by pressing an 'Activate' button, and after a small countdown, will then take readings about whether it is moving. I have tried using the accelerometer to detect movement, but if the threshold becomes too low it activates constantly, whether the device is moving or not. If I set the threshold higher it does not detect movement, and will only detect specific speeds of motion.
Does anyone have any solutions as to how to do this correctly, not by an amount of force, but whether the phone has actually moved.
I have tried to find online examples of how to implement it but only came up with solutions for augmented reality and OpenGL etc. All I need is a simple detection of motion.
Thank you for any help!
EDIT:
I managed to get it working using some samples from the Apple documentation.
I've managed to achieve what I want using this accelerometer didAccelerate method:
- (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));
float accelerationThreshold = 1.01; // or whatever is appropriate - play around with different values
if (fabs(accelX) > accelerationThreshold || fabs(accelY) > accelerationThreshold || fabs(accelZ) > accelerationThreshold) {
[self.soundPlayer play];
accelX = accelY = accelZ = 0;
accelerometerActive = NO;
accelerometer.delegate = nil;
accelerometer = nil;
}
}

One way to do this could be to calculate a vector for gravity. If the phone isn't moving then the vector will remain fairly constant. Should the phone be picked up it is likely that the orientation of the phone will change, thus the gravity vector will also change (in relation to the orientation of the accelerometer).
To detect movement simply calculate the angle between the original vector set on 'Activate' and the current vector. Googling angles between 3d vectors will help you out with the mathmatics behind this.
Theoretically someone could pick the phone up and maintain the exact orientation but this is incredibly unlikely.
Hope this helps and good luck.

Related

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!
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.
}

apply force to a body in touchesMoved direction in box2d iphone

I am new to box2d. I have a problem i.e
when i touch the body and touchmoved(In touchmoved method i don't want move the body)upto some place and touch released.
in touchend i apply force like this...
b2Vec2 force = b2Vec2(0.0,15.0);
ballBody->SetLinearVelocity(force);
and find out the angle b/w touchbegin point to touchend point in this way
float angleRadians = atan2(touchBegin.x - touchEnd.x, touchBegin.y - touchEnd.y);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
cocosAngle1 = -1 * angleDegrees;
in that time,how to apply force to the body with cocosAngle1(touchend direction). Like paper in "Paper Toss" game.
how to apply force in touchmoved direction of body?...
please explain to me...

Moving a sprite with touches began, casting and parameters in obj - c?

I've been reading a book on the cocos2d framework for ios5 for a few days and have developed a small game that the book walks you through. To control the sprite in this game you use the accelerometer:
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.4f;
float sensitivity = 6.0f;
float maxVelocity = 100;
// adjust velocity based on current accelerometer acceleration
playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity;
// we must limit the maximum velocity of the player sprite, in both directions (positive & negative values)
if (playerVelocity.x > maxVelocity)
{
playerVelocity.x = maxVelocity;
}
else if (playerVelocity.x < -maxVelocity)
{
playerVelocity.x = -maxVelocity;
}
// Alternatively, the above if/else if block can be rewritten using fminf and fmaxf more neatly like so:
// playerVelocity.x = fmaxf(fminf(playerVelocity.x, maxVelocity), -maxVelocity);
}
Now I'm wondering if I can change this code to allow the sprite to still accelerate/decelerate along the x axis, but to use touch input rather than the accelerometer, and to go faster the longer the touch is held down for? So a touch to the right would move the sprite to that spot slowly, if the touch is released, it stops moving to that spot. The longer a touch is held down, the faster the sprite moves.
is there anything in the framework to allow me to implement a rotation mechanism that allows my sprite to rotate to the position that the touch was in, so it looks like its facing the point thats been touched?
Well, afaik theres no method that will determine the angle to the touch and then rotate the sprite accordingly, but if you have the x and y coordinates of the sprite and the touch you can calculate it yourself fairly easily.
CGPoint spriteCenter; // this should represent the center position of the sprite
CGPoint touchPoint; //location of touch
float distanceX = touchPoint.x - spriteCenter.x;
float distanceY = touchPoint.y - spriteCenter.y;
float angle = atan2f(distanceY,distanceX); // returns angle in radians
// do whatever you need to with the angle
Once you have the angle you can set the rotation of the sprite.

Moving a cocos2d-iphone+box2d boy in one direction

Please can someone advice me on this.
I have a cocos2d-iphone +box2d body I wish to move only in one direction(movement only from left to right of the iphone screen) using only the accelerometer controls and parallax scrolling. Please how do I do this as at the moment the body moves both to the left and right once the device is tilted. I do not want to use forces or impulse since I will NOT be enabling touch controls.
This is my accelerometer code :
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration
*)acceleration {
float32 accelerationFraction = acceleration.y * 6;
if (accelerationFraction < -1) {
accelerationFraction = -1;
} else if (accelerationFraction > 1) {
accelerationFraction = 1;
b2Vec2 gravity(-acceleration.y *10, acceleration.x *10);
world->SetGravity( gravity );
}
Thanks in advance for your help .
You should use mouseJoints. Look at this tutorial. There he explains exactly what you are trying to accomplish.

Making ball roll with iphone being tilted using Accelerometer

I am making an iphone app where a ball will roll around the screen based on how the user tilts the device. If the device is lies flat on the table theoretically the ball would not move. If the device is tilted standing completely upward the I want the ball to roll straight down at maximum speed. The speed depends on how far from the flat position the device is tilted. Also, it also works for if the user tilts right or left or up or combinations of the four. I am using the accelerometer right now and the ball moves and it works okay, I am just not real familiar with physics. If someone has any suggestions on how to get this to work smoothly please let me know.
Thanks!
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float xx = -[acceleration x];
float yy = [acceleration y];
float z = -[acceleration z];
z = 1 - z;
NSString * zaxis = [NSString stringWithFormat:#"%f", z];
lblz.text = zaxis;
lbly.text = [NSString stringWithFormat:#"%f", yy];
lblx.text = [NSString stringWithFormat:#"%f", xx];
CGFloat newx;
CGFloat newy;
if (yy > 0)
{
newy = ball.center.y - ((1 - yy) * z);
}
else
{
newy = ball.center.y + ((1 - yy) * z);
}
if (xx > 0)
{
newx = ball.center.x - ((1 - xx) * z);
}
else
{
newx = ball.center.x + ((1 - xx) * z);
}
CGPoint newPoint = CGPointMake(newx, newy);
ball.center = newPoint;
If you want to make it look more realistic and leverage existing stuff, look at some of the existing physics engines and 2d frameworks, Box2d and Cocos2d, but there are many others.
I think the key thing you are messing here is the difference between acceleration and velocity. You want the 'amount of tilt' to work as an acceleration. Each frame the balls Velocity should change by the acceleration, then the balls position should change by the balls velocity.
So just in X it should be something like:
float accelX = acceleration.x;
mVel.x += accelX; \\mVel is a member variable you have to store
ball.center.x += mVel.x;
---More Complex version
Now the more I think about it, it might not be the 'amount of tilt' you want to be the acceleration. You might want the amount of tilt to be the 'Target Velocity.' But you still want to use an acceleration to get there.
mTargetVel.x = acceleration.x;
//Now apply an acceleration to the velocity to move towards the Target Velocity
if(mVel.x < mTargetVel.x) {
mVel.x += ACCEL_X; //ACCEL_X is just a constant value that works well for you
}
else if(mVel.x > mTargetVel.x) {
mVel.x -= ACCEL_X;
}
//Now update the position based on the new velocity
ball.center.x += mVel.x;