What i want to do is read the acceleration.y and do something like:
if (acceleration.y > 0.8) {
// Do something
}
As didAccelerate is deprecated I wonder how to get the y-value:
motionManager = [[[CMMotionManager alloc] init] autorelease];
motionManager.accelerometerUpdateInterval = kUpdateInterval;
if (motionManager.accelerometerAvailable) {
[motionManager startAccelerometerUpdates];
}
else {
//this device doesn't have accelerometer notice somewhere??
}
- (void)startAccelerometerUpdates {
// READ Y-VALUE?????
}
I want to use raw accelerometer data so the app also works on 3GS. Is it possible to read the Y-value?
EDIT: the answer below is deprecated, check these posts for the right way.
Old answer:
Use a UIAccelerometer singleton instance for this, for example in your AppDelegate
//in your launching method
UIAccelerometer * accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
//delegate method:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
// use the y-property of the acceleration
}
Look at the CMMotionManager class reference and search section named "Handing Motion Updates at Specified Intervals". In the "Accelerometer" bullet, it says
Set the accelerometerUpdateInterval property to specify an update interval. Call the startAccelerometerUpdatesToQueue:withHandler: method, passing in a block of type CMAccelerometerHandler. Accelerometer data is passed into the block as CMAccelerometerData objects.
CMAccelerometerData has a reference to CMAcceleration which is a struct that holds per axis acceleration.
Related
I have a for....loop and the UI then is blocked when in the loop.
Is the accelerometer also blocked?
I have following code in viewDidLoad
- (void)viewDidLoad{
[super viewDidLoad];
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 1.0f/60.0f;
}
and further down
- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)acceleration {
acc=acceleration.x;
}
then an IBAction connected to a button which starts a loop
- (IBAction)doSomething {
for (int n = 1; n<=100;n++) {
// do someting in the loop
NSLog(#"x: %g", acc);
}
}
when logging the accelerometer x value it shows only the first value when the button is pressed and does not update when the loop is running. The same first value is repeating continuously.
Is there a way to log the acceleration when in the loop?
It would seem that UIAccelerometer needs the main thread so is getting blocked by the for...loop. Core Motion also has an accelerometer property in the CMMotionManager object that can report acceleration, and does better backgrounding since it's what Nike+ uses. There are two ways to access it - a pull method where you get the data directly, or a call-back. To be honest, I just tried it and couldn't get the call-back to work (mostly because it requires NSOperationQueue and I don't have much experience with that so I'm probably putting it on the wrong queue), but if you're ok with pulling data, which your approach seems to need, then this works:
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
[motionManager startAccelerometerUpdates];
for (int i = 0; i < 10000; i++)
{
NSLog(#"Acceleration: %f", motionManager.accelerometerData.acceleration.x);
}
I just tried it on a device and the values reported in the for...loop update with the current acceleration.
Source: UIBackgroundModes and UIAccelerometer
i have his code for making movemnt of the object through horizontal postion.
#define kAccelerationSpeed 10
#define kAccelerometerFrequency 200
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
CGPoint pt = thePlayer.position ;
CGFloat accel = acceleration.x * kAccelerationSpeed;
pt = [[CCDirector sharedDirector] convertToGL:pt];
pt = ccp (pt.x+accel>0 , yLocationOfPlayer+accel<768 );
}
in init statment
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
}
whats wrong with the above code,it is not working,when i tilt the screen,it is not making any movemnt for the "theplayer" object.please help me to do this.
thanks in advance.
Are you sure your delegates are setup to report accelerometer information? Are you also assigning thePlayer.position in the accelerometer callback? I can't recall why but I do recall trying assignment within the callback and the results were rather stuttered and problematic. The solution for me was to have a variable the accelerometer delegate call will modify and assign the position of thePlayer inside of a tick script based on the variable update in the delegate callback.
you're not assigning the position of the player sprite. Try this:
NSLog(#"position before = %#", [NSValue valueWithCGPoint:thePlayer.position]);
thePlayer.position = ccp (pt.x+accel>0 , yLocationOfPlayer+accel<768 );
NSLog(#"position after = %#", [NSValue valueWithCGPoint:thePlayer.position]);
The logging will help you to determine if 1) the delegate method is getting fired and 2) the positions are as you are expecting.
am developing one application using UIAccelerometer , and i retrived the x,y, z values .
i need to mive one object (consider UIImageView) using these values.
here is my code
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 1.0f/60.0f;
- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler
{
NSLog(#"%f %f %f",aceler.x,aceler.y,aceler.z);
//i think here i can give the position of objects, tried object.frame.size.x=accelr.x; but which is not assignable :(
}
what i can do for moving the object according to the accelarometer value, somethin like spirit level?
and any idea how to turn the accelerometer data into degrees?
At a spot in my game there is a brief use of the accelerometer. I use this code:
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 1.0f/60.0f;
to start the accelerometer and then update it using:
- (void)accelerometer:(UIAccelerometer *)accellerometer didAccelerate:(UIAcceleration *)acceleration {
if (whichLevel == 24) {
//Blah blah blah, using accelerometer
} else {
//Turn accelerometer off somehow?
}
//I have found out using this:
NSLog(#"Accelerometer being used");
//That the accelerometer is being used after I start it in the game.
}
And of course, in the .h I put a
This sort of code is used in more than a few tutorials-- But my point is, this is only used for a brief period, and I would like a way to turn it off while I am not using it. (Which none of the tutorials show you how to do)
Apple seems to say here: http://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MotionEvents/MotionEvents.html
-- that you should use
[motionManager stopAccelerometerUpdates];
but apparently you have to set it up that way in order to stop it that way. Do I have to change how I set it up in order to end it?? Or can I end it using what I have?
Thanks in advance,
The Me
Setting the accelerometer’s delegate to nil should let it know that you don’t need its updates anymore. It still might not get powered off entirely—the system watches it to deliver orientation-change events, for instance—but your app won’t be responsible for that.
Hello
I want the sensitivity changing, for when the user moves the device. At the moment its not very sensitive, I believe its on default. I want it so its more sensitive, so when the user shakes the phone a little bit the sound plays.
Here is the code
Thanks
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if(motion == UIEventSubtypeMotionShake)
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"whip" ofType:#"wav"];
if (theAudio) [theAudio release];
NSError *error = nil;
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
if (error)
NSLog(#"%#",[error localizedDescription]);
theAudio.delegate = self;
[theAudio play];
}
}
First, make sure your interface adopts the UIAccelerobeterDelegate protocol.
#interface MainViewController : UIViewController <UIAccelerometerDelegate>
Now in your implementation:
//get the accelerometer
self.accelerometer = [UIAccelerometer sharedAccelerometer];
self.accelerometer.updateInterval = .1;
self.accelerometer.delegate = self;
Implement the delegate method:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float x = acceleration.x;
float y = acceleration.y;
float b = acceleration.z;
// here you can write simple change threshold logic
// so you can call trigger your method if you detect the movement you're after
}
The values that the accelerometer returns for x,y, and z will always be a float between -1.0 and positive 1.0. You should call NSLog and output to the console x,y, and z values so you can get a feel for what they mean. Then you can develop a simple way to detect movement.
You cannot change how the shake events work. If you need something different you will have to write your own shake-detection code based on the x/y/z forces given to you by [UIAccelerometer sharedAccelerometer]; If you set the sharedAccelerometer's delegate to your class, you can get the accelerometer's accelerometer:didAccelerate: delegate callback.
If you're trying to recreate the shake gesture, here are a few things to bear in mind:
A shake is a motion in a direction, followed by a motion in the generally opposite direction. That means you'll have to keep track of your previous acceleration vectors, so that you know when they change. So that you don't miss it, you'll have to sample from the accelerometer pretty frequently.
CGFloat samplesPerSecond = 30;
[[UIAccelerometer sharedAccelerometer] setDelegate: self];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval: 1.0 / samplesPerSecond];
Then in your delegate callback:
- (void) accelerometer: (UIAccelerometer *) accelerometer didAccelerate: (UIAcceleration *) acceleration {
// TODO add this acceleration to a list of accelerations and keep the most recent (perhaps 30)
// TODO analyze accelerations and determine if a direction change occurred
// TODO if it did, then a shake occurred! Clear the list of accelerations and perform your action
}