Replace sharedAccelerometer with motionManager iOS - ios

I've tried several method but I cannot find a working method to replace my
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
most recently i've tried to replace that with
motionManager = [[CMMotionManager alloc] init];
motionManager.accelerometerUpdateInterval = (1.0 / kAccelerometerFrequency);
But it does not seem to work with my void
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
CGPoint pt = theCar.center;
CGFloat accel = acceleration.x * kAccelerationSpeed;
float halfCarWidth = theCar.frame.size.width / 2;
if(pt.x - halfCarWidth + accel > 0 && pt.x + halfCarWidth + accel < 320) {
pt.x += accel;
}
[theCar setCenter:pt];
}
So what do I replace the sharedAccelerometer with since it was depreciated in iOS 5

There is no delegate message with motion manager. Use a timer (NSTimer) and poll the motion manager for its values, at intervals.
self.motman = [CMMotionManager new];
if (!self.motman.accelerometerAvailable) {
// report error or whatever
return;
}
self.motman.accelerometerUpdateInterval = 1.0 / 30.0;
[self.motman startAccelerometerUpdates];
self.timer =
[NSTimer
scheduledTimerWithTimeInterval:self.motman.accelerometerUpdateInterval
target:self selector:#selector(pollAccel:) userInfo:nil repeats:YES];
Now pollAccel: is called repeatedly. Pull out the accelerometer info:
CMAccelerometerData* dat = self.motman.accelerometerData;
CMAcceleration acc = dat.acceleration;

Related

Sprite is "lagging" with accelerometer

The sprite rotate and move based on accelerometer's x axis. When the phone tilts further the sprite rotate and move faster. It's all working, but not smooth. When the sprite is moving slowly it is lagging.
I tried controlling the speed based on accelerometer's x axis.
if (data.acceleration.x >= 0.09) {
angle = 0.4 * data.acceleration.x;
}
if (data.acceleration.x >= 0.20) {
angle = 0.6 * data.acceleration.x;
}
if (data.acceleration.x <= -0.09) {
angle = 0.4 * data.acceleration.x;
}
if (data.acceleration.x <= -0.20) {
angle = 0.6 * data.acceleration.x;
}
if (data.acceleration.x <= 0.09 & data.acceleration.x >= -0.09) {
angle = 0;
}
But it does not solve the issue. Does somebody knows how to stop the lagging?
Code:
#import "GameScene.h"
static int kPlayerSpeed = 20.0;
#implementation GameScene
{
SKSpriteNode *_character;
// cmmotionmanager
float _destY;
float _currentY;
float _currentX;
CMAccelerometerData *_lastReading;
BOOL _shouldMoveToRight;
BOOL _shouldMoveToLeft;
}
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
// background settings
self.backgroundColor = [SKColor whiteColor];
// setup charachter
_character = [SKSpriteNode spriteNodeWithImageNamed:#"Monster_final_01"];
_character.position = CGPointMake(self.size.width * 0.5, self.size.height * 0.2);
_character.anchorPoint = CGPointMake(0.5, 0.5);
_character.xScale = 0.3;
_character.yScale = 0.3;
[self addChild:_character];
// setup motionmanager
self.manager = [[CMMotionManager alloc] init];
[self.manager setAccelerometerUpdateInterval:1.0/30.0];
[self.manager startAccelerometerUpdates];
}
-(void)acceleratorUpdates
{
CMAccelerometerData *data = self.manager.accelerometerData;
if(_lastReading == nil)
{
_lastReading = data;
}
BOOL threshhold = (fabs(_lastReading.acceleration.x - data.acceleration.x) > 0.01);
//if the absolute of acceleration is < the absolute of last, then we changed direction
BOOL changeDir = (fabs(data.acceleration.x) < fabs(_lastReading.acceleration.x));
//if changing direction is above our threshhold, or we didnt change direction
BOOL _aboveThreshold = ( threshhold && changeDir ) || (!changeDir);
CGFloat angle = 0;
CGFloat _destX = 0.0;
if (data.acceleration.x >= 0.09) {
angle = 0.4 * data.acceleration.x;
}
if (data.acceleration.x >= 0.20) {
angle = 0.6 * data.acceleration.x;
}
if (data.acceleration.x <= -0.09) {
angle = 0.4 * data.acceleration.x;
}
if (data.acceleration.x <= -0.20) {
angle = 0.6 * data.acceleration.x;
}
if (data.acceleration.x <= 0.09 & data.acceleration.x >= -0.09) {
angle = 0;
}
if(fabs(data.acceleration.x) > 0.25) { // tilting the device to the right
_destX = -(data.acceleration.x * kPlayerSpeed);
}
[_character removeAllActions];
SKAction *moveAction = [SKAction moveByX:_destX y:0 duration:0];
[_character runAction:moveAction];
_character.position = CGPointMake(_character.position.x + _destX, _character.position.y);
if(_aboveThreshold)
{
SKAction *rotateAction = [SKAction rotateByAngle:angle duration:0];
[_character runAction:rotateAction];
_lastReading = data;
}
NSLog(#"_lastReading.acceleration.x = %f & data.acceleration.x = %f", _lastReading.acceleration.x, data.acceleration.x);
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
}
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
[self acceleratorUpdates];
}

Get direction of device motion by using accelerometer in ios device

I want to get direction of the device motion by using accelerometer. I tried method suggested here as below :-
- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler {
if (fabsf(aceler.x) > 1.5)
{
shake = YES;
NSTimeInterval myInterval = .75;
[NSTimer scheduledTimerWithTimeInterval:myInterval target:self selector:#selector(endShake) userInfo:nil repeats:NO];
return;
}
if(shake)
{
totalG += aceler.x;
}
}
- (void) endShake {
shake = NO;
int direction;
if (totalG isLessThan 0) direction = 1;
if(totalG isGreaterThan 0) direction = -1;
[self changePageByShake:direction];
totalG = 0;
}
But it's not giving accurate results. Is there any standard way to get the direction of the device ?
Note :- This is different from orientation of the device.

Setting CPU Difficulty for Pong

Second time on here hoping that someone can guide me in the right direction.
I'm trying to implement a Pong game within an app for iOS devices (iPhone/iPod/iPad) and it works just fine, except for the fact that I can't beat the CPU, let alone score a point. Here's the implementation .m code:
#import "BTM_pongGame.h"
#import <QuartzCore/QuartzCore.h>
#define STEP_DURATION 0.05
#define RESET_BALL_ANIMATION_DURATION 0.5f
#define MARGIN_WHERE_BALL_IS_LEAVING 40
//#define CPU_SKILL 20
#interface BTM_pongGame ()
#end
#implementation BTM_pongGame
#synthesize cpuSkill, ballShape;
- (void)viewDidLoad
{
[super viewDidLoad];
cpuSkill = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:#"cpuSkill" defaultValue:#"20"];
ballShape = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:#"ballShape" defaultValue:#"1"];
if ([ballShape isEqual: #"1"]) {
self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;
} else {
//self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;
}
}
- (void) wordsPerLineInfoShowAlert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Choose Game"
message:#"Multiplayer or Single Player? You decide! Choose below."
delegate:self
cancelButtonTitle:#"Single Player"
otherButtonTitles:#"Go Back",#"Multi Player", nil];
[alert show];
}
- (void)alertView: (UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Single Player"]) {
[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];
self.mode = kGameSinglePlayer;
[self moveComputerPaddle];
//Disable panning of computer paddle
[self.playerOne.superview setGestureRecognizers:#[]];
[self resetBoardForNewRound];
} else if ([title isEqualToString:#"Multi Player"]) {
[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];
self.mode = kGameMultiPlayer;
[self resetBoardForNewRound];
} else if ( [title isEqualToString:#"Go Back"]){
[self navLeftTap];
}
}
// thanks to MrsVanBeveren for coding the reset score stuff
-(void)resetPlayerScoreLabels
{
playerOneScore = 0;
playerTwoScore = 0;
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self wordsPerLineInfoShowAlert];
[self startGameTimer];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[_gameTimer invalidate];
}
-(void)quitPressed:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)startGameTimer
{
[_gameTimer invalidate];
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:STEP_DURATION target:self selector:#selector(step:) userInfo:nil repeats:YES];
}
#pragma mark Game setup
/*
* Some maths to calculate a new starting direction
* By choosing mid left/right part of the unit circle
* we avoid getting straight up/down directions
*/
-(void)resetBallDirection
{
float randomUnity = arc4random_uniform(100)/100.0;
int horizontalDirection = (arc4random() % 2 ? 1 : -1);
float angle = M_PI_4 + randomUnity * M_PI_2;
float direction = horizontalDirection * angle;
dirX = sin(direction);
dirY = cos(direction);
}
-(void)resetBoardForNewRound
{
speed = self.view.frame.size.width / 50.0;
[self resetBallDirection];
[_gameTimer invalidate];
[UIView animateWithDuration:RESET_BALL_ANIMATION_DURATION animations:^{
self.ball.center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0);
} completion:^(BOOL finished){
[self startGameTimer];
}];
[self enlargeAnimation:self.ball];
}
-(void)updatePlayerScoreLabels
{
self.playerOneScoreLabel.text = [NSString stringWithFormat:#"%d",playerOneScore];
self.playerTwoScoreLabel.text = [NSString stringWithFormat:#"%d",playerTwoScore];
}
#pragma mark Paddle handling
- (IBAction)paddlePanned:(UIPanGestureRecognizer*)recognizer {
UIView *paddleWrapper = recognizer.view;
UIView *paddle = [[paddleWrapper subviews] lastObject];
switch([recognizer state]) {
case UIGestureRecognizerStateBegan: {
paddle.backgroundColor = UIColor.whiteColor;
}
break;
case UIGestureRecognizerStateChanged: {
CGPoint position = [recognizer locationInView:self.view];
CGFloat haldPaddleHeight = paddleWrapper.frame.size.height / 2.0;
CGPoint newCenter = paddleWrapper.center;
newCenter.y = position.y;
newCenter.y = MAX(haldPaddleHeight, newCenter.y);
newCenter.y = MIN(self.view.bounds.size.height - haldPaddleHeight, newCenter.y);
paddleWrapper.center = newCenter;
}
break;
case UIGestureRecognizerStateEnded: {
paddle.backgroundColor = UIColor.grayColor;
}
break;
default:
break;
}
}
#pragma mark Game loop
/*
* Game loop
* - Moves the ball and checks for obstacles
*/
- (void)step:(NSTimer*)timer
{
speed += 0.05;
[self checkForBallLevingSide];
CGPoint newCenter = self.ball.center;
CGFloat ballRadius = self.ball.frame.size.height / 2.0;
newCenter.x += dirX * speed;
newCenter.y += dirY * speed;
CGFloat upperEdge = ballRadius;
CGFloat bottomEdge = self.view.bounds.size.height - ballRadius;
// Bounce ball of top/bottom walls
if (newCenter.y <= upperEdge) {
dirY = ABS(dirY);
newCenter.y = upperEdge;
} else if (newCenter.y >= bottomEdge) {
dirY = -ABS(dirY);
newCenter.y = bottomEdge;
}
[UIView animateWithDuration:STEP_DURATION animations:^{
self.ball.center = newCenter;
}];
}
-(BOOL)didBallHitPaddle:(UIView *)paddle withinLimit:(CGFloat)limit
{
if (CGRectIntersectsRect(paddle.frame, self.ball.frame)){
[self deflectBallFromPaddle:paddle];
CGRect ballFrame = self.ball.frame;
ballFrame.origin.x = limit;
self.ball.frame = ballFrame;
return YES;
} else
return NO;
}
-(void)checkForBallLevingSide
{
float limitLeft = MARGIN_WHERE_BALL_IS_LEAVING;
float limitRight = self.view.bounds.size.width - self.ball.frame.size.width - MARGIN_WHERE_BALL_IS_LEAVING;
CGRect ballFrame = self.ball.frame;
CGFloat ballX = ballFrame.origin.x;
if (ballX < limitLeft) {
if (![self didBallHitPaddle:self.playerOne.superview withinLimit:limitLeft])
[self playerDidMiss:kPlayerOne];
}else if (ballX > limitRight) {
if (![self didBallHitPaddle:self.playerTwo.superview withinLimit:limitRight])
[self playerDidMiss:kPlayerTwo];
}
}
/*
* Calculates new dirX and dirY after the bounce.
* The longer from the paddle's middle the bigger the result angle gets. (Pong style)
*/
-(void)deflectBallFromPaddle:(UIView *)paddle
{
dirX *= -1;
CGFloat diff = self.ball.center.y - paddle.center.y;
float p = diff / paddle.frame.size.height * 2.0f;
dirY += p * 0.5;
}
-(void)playerDidMiss:(kPlayer)player
{
if (player == kPlayerOne) {
playerTwoScore++;
[self victoryShake:self.playerTwo];
[self enlargeAnimation:self.playerTwoScoreLabel];
}
else if (player == kPlayerTwo) {
playerOneScore++;
[self victoryShake:self.playerOne];
[self enlargeAnimation:self.playerOneScoreLabel];
}
[self resetBoardForNewRound];
[self updatePlayerScoreLabels];
}
-(void)moveComputerPaddle
{
UIView *paddle = self.playerOne.superview;
CGPoint cpuCenter = paddle.center;
CGFloat diff = self.ball.center.y - paddle.center.y;
CGFloat movement = MIN((int)cpuSkill, ABS(diff));
movement *= diff > 0 ? 1 : -1;
cpuCenter.y += movement;
[UIView animateWithDuration:0.1 animations:^{
self.playerOne.superview.center = cpuCenter;
} completion:^(BOOL b) {
[self moveComputerPaddle];
}];
}
#pragma mark Animation
-(void)victoryShake:(UIView *)view
{
CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:#"transform" ] ;
anim.values = [ NSArray arrayWithObjects:
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, -20.0f, 0.0f) ],
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, 20.0f, 0.0f) ],
nil ] ;
anim.autoreverses = YES ;
anim.repeatCount = 4.0f ;
anim.duration = 0.07f ;
[view.layer addAnimation:anim forKey:nil];
}
-(void)enlargeAnimation:(UIView *)view
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3.0, 3.0, 1.0)];
[animation setDuration:RESET_BALL_ANIMATION_DURATION * 0.5];
animation.repeatCount = 1.0f ;
[animation setAutoreverses:YES];
[view.layer addAnimation:animation forKey:nil];
}
#end
I've simply tried changing the number where it states #define CPU_SkILL and again #"cpuSkill" defaultValue:#"20"];, but I've had no luck with changing the number in any direction.
Any ideas?
Thank you in advance.
The cpuSkill variable controls the movement of the CPU-controlled paddle:
CGFloat movement = MIN((int)cpuSkill, ABS(diff));
So maybe the cpuSkill is higher than intended in every situation. Try much lower values or make some random little adjustment to movement after the calculation.
Also, you should ABS() the cpuSkill to avoid perfect moving when negative moving.

Detect hard taps anywhere on iPhone through accelerometer

I am trying to detect the taps which could be anywhere on iPhone not just iPhone screen. Here is a link which shows that it is possible.
Basically what i want to do is send an alert if user taps 3 times on iPhone while the Phone is in his pocket.
What i have achieved is that i can detect the 3 taps but i also get the false alerts as well in these cases. 1) if user walking, 2) waving his phone 3) running. I need to just check if user has hit his iPhone 3 times.
Here is my code.
- (void)accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration
{
if (handModeOn == NO)
{
if(pocketFlag == NO)
return;
}
float accelZ = 0.0;
float accelX = 0.0;
float accelY = 0.0;
accelX = (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor));
accelY = (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor));
accelZ = (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor));
self.z.text = [NSString stringWithFormat:#"%0.1f", -accelZ];
if((-accelZ >= [senstivity floatValue] && timerFlag) || (-accelZ <= -[senstivity floatValue] && timerFlag)|| (-accelX >= [senstivity floatValue] && timerFlag) || (-accelX <= -[senstivity floatValue] && timerFlag) || (-accelY >= [senstivity floatValue] && timerFlag) || (-accelY <= -[senstivity floatValue] && timerFlag))
{
timerFlag = false;
addValueFlag = true;
timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:#selector(timerTick:) userInfo:nil repeats:YES];
}
if(addValueFlag)
{
if (self.xSwitch.on)
{
NSLog(#"X sWitch is on");
[self.accArray addObject:[NSNumber numberWithFloat:-accelX]];
}
if (self.ySwitch.on)
{
NSLog(#"Y Switch is on");
[self.accArray addObject:[NSNumber numberWithFloat:-accelY]];
}
if (self.zSwitch.on)
{
NSLog(#"Z Switch is on");
[self.accArray addObject:[NSNumber numberWithFloat:-accelZ]];
}
}
//}
}
- (void)timerTick:(NSTimer *)timer1
{
[timer1 invalidate];
addValueFlag = false;
int count = 0;
for(int i = 0; i < self.accArray.count; i++)
{
if(([[self.accArray objectAtIndex:i] floatValue] >= [senstivity floatValue]) || ([[self.accArray objectAtIndex:i] floatValue] <= -[senstivity floatValue]))
{
count++;
[self playAlarm:#"beep-1" FileType:#"mp3"];
}
if(count >= 3)
{
[self playAlarm:#"06_Alarm___Auto___Rapid_Beeping_1" FileType:#"caf"];
[self showAlert];
timerFlag = true;
[self.accArray removeAllObjects];
return;
}
}
[self.accArray removeAllObjects];
timerFlag = true;
}
Any help will be really appreciated.
Thanks
You should apply a high pass filter to the accelerometer data. That will give you just the spikes in the signal - sharp taps.
I did a quick search on "UIAccelerometer high pass filter" and found several hits. The simplest code takes a rolling average of the accelerometer input, then subtracts that average from the instantaneous reading to find sudden changes. There are no doubt more sophisticated methods as well.
Once you have code that recognizes sharp taps, you'll need to craft code that detects 3 sharp taps in a row.
This is, as suggested by another answer, all to do with filtering the taps from the stream of accelerometer data. The impulse-like tap's will have a characteristic spectrogram (combination of frequencies) that can be detected when the response from a proper filter is higher than a threshold.
This is a very common operation on iPhone, I would suggest you look at official documentation such as here
The sample code I have linked to gives you two important things: official example code for high-pass filter AND a sample app that will graph the accelerometer data. This you can use to visual your taps, steps and jumps, to better understand why your filter responds falsely.
Furthermore, the internet is a huge source of literature on filter design - if you need to make a very high quality filter, you may need to consult the literature. I think however that a suitable second order filter would likely be sufficient.
#implementation HighpassFilter
- (id)initWithSampleRate:(double)rate cutoffFrequency:(double)freq
{
self = [super init];
if (self != nil)
{
double dt = 1.0 / rate;
double RC = 1.0 / freq;
filterConstant = RC / (dt + RC);
}
return self;
}
- (void)addAcceleration:(UIAcceleration *)accel
{
double alpha = filterConstant;
if (adaptive)
{
double d = Clamp(fabs(Norm(x, y, z) - Norm(accel.x, accel.y, accel.z)) / kAccelerometerMinStep - 1.0, 0.0, 1.0);
alpha = d * filterConstant / kAccelerometerNoiseAttenuation + (1.0 - d) * filterConstant;
}
x = alpha * (x + accel.x - lastX);
y = alpha * (y + accel.y - lastY);
z = alpha * (z + accel.z - lastZ);
lastX = accel.x;
lastY = accel.y;
lastZ = accel.z;
}
- (NSString *)name
{
return adaptive ? #"Adaptive Highpass Filter" : #"Highpass Filter";
}
#end
Importantly this filter is direction agnostic, since only the magnitude of the acceleration is filtered. This is crucial to make the response seem normal. Otherwise users may feel like the have to tap from different angles to find a sweetspot.
On another note, if this task is proving too difficult and fiddly, I strongly suggest capturing your data ( in a WAV file for example) and using one of any common signal anaylsing program to get a better idea of where it is going wrong. See Baudline
Here is how i achieved it.
- (void)accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration
{
if (pause)
{
return;
}
if (handModeOn == NO)
{
if(pocketFlag == NO)
return;
}
// float accelZ = 0.0;
// float accelX = 0.0;
// float accelY = 0.0;
rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));
rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));
float accelX = acceleration.x - rollingX;
float accelY = acceleration.y - rollingY;
float accelZ = acceleration.z - rollingZ;
if((-accelZ >= [senstivity floatValue] && timerFlag) || (-accelZ <= -[senstivity floatValue] && timerFlag)|| (-accelX >= [senstivity floatValue] && timerFlag) || (-accelX <= -[senstivity floatValue] && timerFlag) || (-accelY >= [senstivity floatValue] && timerFlag) || (-accelY <= -[senstivity floatValue] && timerFlag))
{
timerFlag = false;
addValueFlag = true;
timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:#selector(timerTick:) userInfo:nil repeats:YES];
}
if(addValueFlag)
{
[self.accArray addObject:[NSNumber numberWithFloat:-accelX]];
[self.accArray addObject:[NSNumber numberWithFloat:-accelY]];
[self.accArray addObject:[NSNumber numberWithFloat:-accelZ]];
}
}
Some good answers. Here's some working code. I implemented this as a subclass of UIGestureRecognizer so that you can just drop it in and attach it to a UIView or UIButton. Once triggered, it will have the "pressure" set to a float between 0.0f and 2.0f. You can optionally set the minimum and maximum pressures required to recognize. Enjoy.
#import <UIKit/UIKit.h>
#define CPBPressureNone 0.0f
#define CPBPressureLight 0.1f
#define CPBPressureMedium 0.3f
#define CPBPressureHard 0.8f
#define CPBPressureInfinite 2.0f
#interface CPBPressureTouchGestureRecognizer : UIGestureRecognizer <UIAccelerometerDelegate> {
#public
float pressure;
float minimumPressureRequired;
float maximumPressureRequired;
#private
float pressureValues[30];
uint currentPressureValueIndex;
uint setNextPressureValue;
}
#property (readonly, assign) float pressure;
#property (readwrite, assign) float minimumPressureRequired;
#property (readwrite, assign) float maximumPressureRequired;
#end
//
// CPBPressureTouchGestureRecognizer.h
// PressureSensitiveButton
//
// Created by Anthony Picciano on 3/21/11.
// Copyright 2011 Anthony Picciano. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import <UIKit/UIGestureRecognizerSubclass.h>
#import "CPBPressureTouchGestureRecognizer.h"
#define kUpdateFrequency 60.0f
#define KNumberOfPressureSamples 3
#interface CPBPressureTouchGestureRecognizer (private)
- (void)setup;
#end
#implementation CPBPressureTouchGestureRecognizer
#synthesize pressure, minimumPressureRequired, maximumPressureRequired;
- (id)initWithTarget:(id)target action:(SEL)action {
self = [super initWithTarget:target action:action];
if (self != nil) {
[self setup];
}
return self;
}
- (id)init {
self = [super init];
if (self != nil) {
[self setup];
}
return self;
}
- (void)setup {
minimumPressureRequired = CPBPressureNone;
maximumPressureRequired = CPBPressureInfinite;
pressure = CPBPressureNone;
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0f / kUpdateFrequency];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
}
#pragma -
#pragma UIAccelerometerDelegate methods
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
int sz = (sizeof pressureValues) / (sizeof pressureValues[0]);
// set current pressure value
pressureValues[currentPressureValueIndex%sz] = acceleration.z;
if (setNextPressureValue > 0) {
// calculate average pressure
float total = 0.0f;
for (int loop=0; loop<sz; loop++) total += pressureValues[loop];
float average = total / sz;
// start with most recent past pressure sample
if (setNextPressureValue == KNumberOfPressureSamples) {
float mostRecent = pressureValues[(currentPressureValueIndex-1)%sz];
pressure = fabsf(average - mostRecent);
}
// caluculate pressure as difference between average and current acceleration
float diff = fabsf(average - acceleration.z);
if (pressure < diff) pressure = diff;
setNextPressureValue--;
if (setNextPressureValue == 0) {
if (pressure >= minimumPressureRequired && pressure <= maximumPressureRequired)
self.state = UIGestureRecognizerStateRecognized;
else
self.state = UIGestureRecognizerStateFailed;
}
}
currentPressureValueIndex++;
}
#pragma -
#pragma UIGestureRecognizer subclass methods
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
setNextPressureValue = KNumberOfPressureSamples;
self.state = UIGestureRecognizerStatePossible;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
self.state = UIGestureRecognizerStateFailed;
}
- (void)reset {
pressure = CPBPressureNone;
setNextPressureValue = 0;
currentPressureValueIndex = 0;
}
#end

Moving the 3d object in iOS application?

I am working on rotating the 3d object in my application by using the application downloaded from here.I succeed on stopping the rotating object as below, but I can't rotate the object again from the stopped position.Below is the piece of code I've worked from the downloaded project
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
{
    if (aRotate) {
        [self startOrStopAutorotation:nil];
    }
    if ([[event touchesForView:self.view] count] > 1) // Pinch gesture, possibly two-finger movement
{
//CGPoint directionOfPanning = CGPointZero;
}
    else{
        CGPoint currentMovementPosition = [[touches anyObject] locationInView:glView_];
        [self renderByRotatingAroundX:(lastMovementPosition.x - currentMovementPosition.x) rotatingAroundY: (lastMovementPosition.y - currentMovementPosition.y) scaling:1.0f translationInX:0.0f translationInY:0.0f];
        lastMovementPosition = currentMovementPosition;
    }
}
}
- (void)renderByRotatingAroundX:(float)xRotation rotatingAroundY:(float)yRotation scaling:(float)scaleF translationInX:(float)xTranslation translationInY:(float)yTranslation{
    
    glView_ = [[REGLView alloc] initWithFrame:CGRectMake(0, 0, 320, 320) colorFormat:kEAGLColorFormatRGBA8 multisampling:YES];
    [self.view addSubview:glView_];
    
    
    camera_ = [[RECamera alloc] initWithProjection:kRECameraProjectionOrthographic];
    camera_.position = CC3VectorMake(0, 0, 320);
    camera_.upDirection = CC3VectorMake(0, 1, 0);
    camera_.lookDirection = CC3VectorMake(0, 0, -1);
    camera_.frustumNear = 10;
    camera_.frustumFar = 640;
    camera_.frustumLeft = -glView_.frame.size.width / 2.0;
    camera_.frustumRight = glView_.frame.size.width / 2.0;
    camera_.frustumBottom = -glView_.frame.size.height / 2.0;
    camera_.frustumTop = glView_.frame.size.height / 2.0;
    
    scene_ = [[REScene alloc] init];
    scene_.camera = camera_;
    
    world_ = [[REWorld alloc] init];
    [scene_ addChild:world_];
    
    director_ = [[REDirector alloc] init];
    director_.view = glView_;
    director_.scene = scene_;
    
//    currentCalculatedMatrix = CATransform3DIdentity;
    GLfloat currentModelViewMatrix[16]  = {0.402560,0.094840,0.910469,0.000000, 0.913984,-0.096835,-0.394028,0.000000, 0.050796,0.990772,-0.125664,0.000000, 0.000000,0.000000,0.000000,1.000000};
    currentCalculatedMatrix = CATransform3DScale(currentCalculatedMatrix, 0.5, 0.5 * (320.0/480.0), 0.5);
    
////    if ((xRotation != 0.0) || (yRotation != 0.0))
//{
GLfloat totalRotation = sqrt(xRotation*xRotation + yRotation*yRotation);
CATransform3D temporaryMatrix = CATransform3DRotate(currentCalculatedMatrix, totalRotation * M_PI / 180.0,
((xRotation/totalRotation) * currentCalculatedMatrix.m12 + (yRotation/totalRotation) * currentCalculatedMatrix.m11),
((xRotation/totalRotation) * currentCalculatedMatrix.m22 + (yRotation/totalRotation) * currentCalculatedMatrix.m21),
((xRotation/totalRotation) * currentCalculatedMatrix.m32 + (yRotation/totalRotation) * currentCalculatedMatrix.m31));
if ((temporaryMatrix.m11 >= -100.0) && (temporaryMatrix.m11 <= 100.0))
currentCalculatedMatrix = temporaryMatrix;
    float currentScaleFactor = sqrt(pow(currentCalculatedMatrix.m11, 2.0f) + pow(currentCalculatedMatrix.m12, 2.0f) + pow(currentCalculatedMatrix.m13, 2.0f));
xTranslation = xTranslation / (currentScaleFactor * currentScaleFactor);
yTranslation = yTranslation / (currentScaleFactor * currentScaleFactor);
// Use the (0,4,8) components to figure the eye's X axis in the model coordinate system, translate along that
temporaryMatrix = CATransform3DTranslate(currentCalculatedMatrix, xTranslation * currentCalculatedMatrix.m11, xTranslation * currentCalculatedMatrix.m21, xTranslation * currentCalculatedMatrix.m31);
// Use the (1,5,9) components to figure the eye's Y axis in the model coordinate system, translate along that
temporaryMatrix = CATransform3DTranslate(temporaryMatrix, yTranslation * currentCalculatedMatrix.m12, yTranslation * currentCalculatedMatrix.m22, yTranslation * currentCalculatedMatrix.m32);
if ((temporaryMatrix.m11 >= -100.0) && (temporaryMatrix.m11 <= 100.0))
currentCalculatedMatrix = temporaryMatrix;
[self convert3DTransform:&currentCalculatedMatrix toMatrix:currentModelViewMatrix];    
   
// Black background, with depth buffer enabled
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
And below is the code I've worked for stopping and stopping
- (void)startOrStopAutorotation:(id)sender;
{
    id dLink=nil;
    if (aRotate){
        dLink=[[REDisplayLink sharedDisplayLink] observers];
        [[REDisplayLink sharedDisplayLink] removeObserver:[dLink objectAtIndex:0]];
    }
    else{
        CADisplayLink *aDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(handleAutorotationTimer)];
[aDisplayLink setFrameInterval:2];
[aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        //          [[REDisplayLink sharedDisplayLink] addObserver:[[REDirector alloc]init]];
    }
    aRotate = !aRotate;
}

Resources