Using accelerometer for animation and output? - iphone

i'm new to xcode and objective c, so be indulgent :)
i wrote an app where i can move a small ball over the display using the accelerometer.
in addition i want to output the accelerometer data on the display.
the problem is, when i want to output the data the ball won't move.
thanks for help!
xLabel.text = [NSString stringWithFormat:#"x: %f.02", acceleration.x];
yLabel.text = [NSString stringWithFormat:#"y: %f.02", acceleration.y];
zLabel.text = [NSString stringWithFormat:#"z: %f.02", acceleration.z];
Here's the initializing code:
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer]; //Share reference
accel.delegate = self;
accel.updateInterval = 1.0f / 60.0f;

That may be because you trying to both the tasks on main thread which is not possible simultaneously.
I think you can use Core animation (which uses its own thread to perform its operations) to move object instead of directly changing frame of the object (which requires main thread).

Related

Acceleration in a for..... loop

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

Cocos2d v2.0: unable to add CCParticleSystem to scene

I'm trying to add CCParticleFlower to my Cocos2d v2.0 (with ARC enabled) HelloWorld scene.
That's the code I am running:
CCParticleFlower* system = [[CCParticleFlower alloc] initWithTotalParticles:10];
// Set some parameters that can't be set in Particle Designer
// system.positionType = kCCPositionTypeFree;
// system.autoRemoveOnFinish = YES;
system.visible = TRUE;
[system setDuration:4.0f];
system.position = CGPointMake(150.0f, 100.0f);
[self addChild:system z:0];
I tried several variants but I'm not quiet sure what I am doing wrong as I never managed to run it.
E.g.:
CCParticleSystem * system = [CCParticleFlower node];
system.position = CGPointMake(150.0f, 100.0f);
[self addChild:system];
Make sure to include the texture that is used on the particle system in your project.
Try resetting the system and see if it works. [system reset]. You could even try [system scheduleUpdate] just in case its not updating correclty.

Why am I getting 0 degrees from magneticField property the whole time?

I'm trying to get the device's declination from the magnetic North in degrees, by relying solely on the device's magnetometer. This is the code I've written but I just get 0 degrees.. What am I doing wrong ?
CMMotionManager *motionManager;
motionManager = [[CMMotionManager alloc] init];
[motionManager startDeviceMotionUpdates];
CMDeviceMotion *deviceMotion;
deviceMotion = [[CMDeviceMotion alloc] init];
while(!self.stopButtonPressed)
{
double x = motionManager.deviceMotion.magneticField.field.x;
double y = motionManager.deviceMotion.magneticField.field.y;
double degrees = asin(y/sqrt(pow(x, 2.0) + pow(y, 2.0))) * 180.0 / M_PI ;
int degreesRounded = (int)degrees;
NSLog(#"Degrees : %i", degreesRounded);
}
It is likely that the simulator doesn't return normal values for these methods, so you will need to test on a real device.
The CLLocationManager's method, didUpdateHeading: doesn't work on the simulator, so you are probably experiencing something similar here.
Edit:
From the docs:
"The latest sample of device-motion data. (read-only)
#property(readonly) CMDeviceMotion *deviceMotion
Discussion
If no device-motion data is available, the value of this property is nil. An application that is receiving device-motion data after calling startDeviceMotionUpdates periodically checks the value of this property and processes the device-motion data."
Check to see if that property of your motion manager is nil. If it is, then you would get 0 for the magnetic field property.
Edit 2:
Instead of using startDeviceMotionUpdates, you should be using startMagnetometerUpdatesToQueue:. The docs say this:
"Magnetometer. Set the magnetometerUpdateInterval property to specify an update interval. Call the startMagnetometerUpdatesToQueue:withHandler: method, passing a block of type CMMagnetometerHandler. Magnetic-field data is passed into the block as CMMagnetometerData objects."
Docs are here.
What thread is the above code running on? If you're running it on the main thread, you probably won't get see updates to the device motion data over time. Use an NSTimer or similar mechanism to sample the motion over time, so the main thread is free to do other things (like service requests from the core motion sub-system).
Here is what I tested on a real device:
CMMotionManager *myMotionManager= [[CMMotionManager alloc] init];
myMotionManager.deviceMotionUpdateInterval = 1;
[myMotionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXMagneticNorthZVertical toQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
double x = myMotionManager.deviceMotion.magneticField.field.x;
double y = myMotionManager.deviceMotion.magneticField.field.y;
double z = myMotionManager.deviceMotion.magneticField.field.z;
NSLog(#"Field.x= %f; Field.y = %f; Field.z= %f",x,y,z);
}];

turning off iPhone accelerometer while not using it

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.

Best way to display a game score on iPhone with cocos2d?

I am looking to persistently display a game score in an iPhone app using cocos2d. Going off the code that cocos2d shows the FPS the app is running at:
-(void) showFPS
{
frames++;
accumDt += dt;
if ( accumDt > 0.1) {
frameRate = frames/accumDt;
frames = 0;
accumDt = 0;
}
NSString *str = [NSString stringWithFormat:#"%.1f",frameRate];
[FPSLabel setString:str];
[FPSLabel draw];
}
I can get the score to display properly, but it flickers, even though the app is running at faster that 60 FPS... Any ideas?
For anyone who might be interested, I ended up using a cocos2d Label as so:
scoreLabel = [Label labelWithString: [NSString stringWithFormat:#"%d", score] dimensions: CGSizeMake(180, 20) alignment: UITextAlignmentRight fontName:#"Arial" fontSize: 20];
[scoreLabel setPosition: cpv(100,100)];
[self add: scoreLabel];
Hopefully this can help someone else.
Try using LabelAtlas instead. It is faster (it consumes much less CPU).
See the AtlasDemo that comes with the cocos2d distribution to see how to use it.