3

I need to use the functionality of an accelerometer in my iPhone game. I just have to move an image by tilting the device. However most videos on YouTube just show the tilt feature that is somehow inverted and forget to include the calibration.

I want the user to calibrate their device to whatever position they're in. Does anyone know how I should get started on this?

halfer
  • 19,824
  • 17
  • 99
  • 186
lab12
  • 6,400
  • 21
  • 68
  • 106

1 Answers1

7

I made an app like this once. I'll post it here, but it's for iOS 4...

To calibrate:

int tapCount = 0;
- (void)cancelDoubleTap {
    if (tapCount < 2) {
        tapCount = 0;
    }
}
- (void)reset {
    [[NSUserDefaults standardUserDefaults] setFloat:0 forKey:@"X-Calibrate"];
    [[NSUserDefaults standardUserDefaults] setFloat:0 forKey:@"Y-Calibrate"];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Reset!" message:@"Calibration reset." delegate:nil cancelButtonTitle:@"Okay." otherButtonTitles:nil];
    [alert show];
    [alert release];
}
- (void)calibrate {
    if (tapCount == 3) {
        tapCount = 0;
        return;
    }
    [[NSUserDefaults standardUserDefaults] setFloat:accelX forKey:@"X-Calibrate"];
    [[NSUserDefaults standardUserDefaults] setFloat:accelY forKey:@"Y-Calibrate"];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Calibrated!" message:[NSString stringWithFormat:@"Calibrated to: %.2f %.2f.", accelX, accelY] delegate:nil cancelButtonTitle:@"Okay." otherButtonTitles:nil];
    [alert show];
    [alert release];
    tapCount = 0;
}
- (BOOL)canBecomeFirstResponder {
    return YES;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(cancelDoubleTap) userInfo:nil repeats:NO];
    tapCount ++;
    if (tapCount == 3) {
        [timer invalidate];
        [self reset];
        return;
    }
    if (tapCount == 2) {
        [timer invalidate];
        timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(calibrate) userInfo:nil repeats:NO];
    }  
}

And...

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    but = [[UIButton alloc] initWithFrame:window.frame];
    [but addTarget:self action:@selector(touchesEnded:withEvent:) forControlEvents:UIControlEventTouchUpInside];
    [window addSubview:but];
     // Override point for customization after application launch.
    box = [[UIView alloc] initWithFrame:CGRectMake(self.window.center.x - 50, self.window.center.y - 50, 100, 100)];
  [window makeKeyAndVisible];
    box.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.75];
    [window addSubview:box];
    [[UIAccelerometer sharedAccelerometer] setDelegate:self];
    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1/100.0)];
    slider = [[UISlider alloc] initWithFrame:CGRectMake(20, 438, 280, 22)];
    [slider setMinimumValue:2.0];
    [slider setMaximumValue:50.0];
    [window addSubview:slider];
    return YES;
 }

.h file:

#import <UIKit/UIKit.h>

@interface TilterAppDelegate : NSObject <UIApplicationDelegate, UIAccelerometerDelegate> {
    UIWindow *window;
    UIView *box;
    UISlider *slider;
    UIButton *but;
}

@property (nonatomic, retain) IBOutlet UIButton *but;
@property (nonatomic, retain) IBOutlet UISlider *slider;
@property (nonatomic, retain) IBOutlet UIView *box;
@property (nonatomic, retain) IBOutlet UIWindow *window;

@end

Move code:

 - (void)moveBoxByX:(float)x byY:(float)y {
    float newX = box.center.x + x;
    float newY = box.center.y + y;
    if (newX < 50)
        newX = 50;
    if (newX > 270)
        newX = 270;
    if (newY < 50)
        newY = 50;
    if (newY > 430)
        newY = 430;
    box.center = CGPointMake(newX, newY);
}

Should work most of the time.

halfer
  • 19,824
  • 17
  • 99
  • 186
Glenn Smith
  • 912
  • 1
  • 17
  • 37
  • 2
    THANKS!! I'm a developer too, so I have the 4.0 firmware as well. I'll check it out! – lab12 Jun 17 '10 at 19:46
  • 2
    Sorry can't give the bounty until 23 hrs later :(. But i'll make sure I give it to you! – lab12 Jun 17 '10 at 19:57
  • 1
    Very useful answer. I would give you an up-vote, but I've reached my daily voting limit :( –  Jun 24 '10 at 14:52
  • Old thread but what if we wanted to calibrate it from another view controller, how would that work. Also is this code for a landscape app or portrait? – SimplyKiwi Sep 18 '11 at 04:55
  • Implement UIAccelerometerDelegate in the separate class, or call the method to the original class with the delegate. Since it uses user defaults, it should then be accessible from any class. Also, it is regardless of the landscape/portrait. – Glenn Smith Sep 19 '11 at 22:43