Hi all,
I'm trying to build an object which lets you "grab" a corner with your finger and move it around as if it were a real object (it would rotate and translate depending on where you grabbed it and moved to).
For some reason, though the rotation works fine and in theory the translation seems to work fine as well, the object does not move as much as it should (so the touch slowly gains distance between itself and the object) and the object seems to jump between two positions as it moves making it almost seem as if there are two (because it flickers with surprising frequency).
I'll post the relevant methods here:
Bearing2D is just a struct containing distance and angle data (floats). Bearings are taken from "North" (the top direction of the screen) as is the convention. All angles are in radians.
Any help would be much appreciated.
I'm trying to build an object which lets you "grab" a corner with your finger and move it around as if it were a real object (it would rotate and translate depending on where you grabbed it and moved to).
For some reason, though the rotation works fine and in theory the translation seems to work fine as well, the object does not move as much as it should (so the touch slowly gains distance between itself and the object) and the object seems to jump between two positions as it moves making it almost seem as if there are two (because it flickers with surprising frequency).
I'll post the relevant methods here:
Code:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touches began on Physical Object");
if([touches count] == 1) {
UITouch * touch = [[touches allObjects] objectAtIndex:0];
self.throwStartLocation = [touch locationInView:[self superview]];
NSLog(@"Touch location: (%f, %f)", self.throwStartLocation.x, self.throwStartLocation.y);
self.throwStartTime = [touch timestamp];
self.touchBearingFromCentre = [self calculateBearingFromCentre:self.throwStartLocation];
}
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if([touches count] == 1) {
UITouch * touch = [[touches allObjects] objectAtIndex:0];
CGPoint touchLocation = [touch locationInView:[self superview]];
//Get new bearings
Bearing2D bearing = [self calculateBearingFromCentre:touchLocation];
//Calculate required translation
float trans = bearing.distance - self.touchBearingFromCentre.distance;
float tx = trans * sinf(bearing.angle);
float ty = - (trans * cosf(bearing.angle));
self.center = CGPointMake(self.center.x+tx, self.center.y+ty);
//Calculate required rotation
self.transform = CGAffineTransformRotate(self.transform, bearing.angle - self.touchBearingFromCentre.angle);
//Set saved positions to current touch positions
self.throwStartLocation = touchLocation;
self.throwStartTime = [touch timestamp];
self.touchBearingFromCentre = bearing;
}
}
- (Bearing2D) calculateBearingFromCentre: (CGPoint) touchLocation {
CGPoint centre = self.center;
Bearing2D bearing;
bearing.distance = distanceBetweenTwoPoints2D(centre, touchLocation);
float angle = asinf(ABS(touchLocation.x - centre.x)/bearing.distance);
BOOL TOP = (touchLocation.y <= centre.y);
BOOL LEFT = (touchLocation.x <= centre.x);
if(TOP && !LEFT) {
//Top Right Quadrant
bearing.angle = angle;
} else if (!TOP && !LEFT) {
//Bottom Right Quadrant
bearing.angle = (M_PI- angle);
} else if (!TOP && LEFT) {
//Bottom Left Quadrant
bearing.angle = M_PI + angle;
} else if(TOP && LEFT) {
//Top Left Quadrant
bearing.angle = 2*M_PI - angle;
}
NSLog(@"Touch is at a bearing of %f and a distance of %f from centre at (%f, %f)", bearing.angle, bearing.distance, centre.x, centre.y);
return bearing;
}
Bearing2D is just a struct containing distance and angle data (floats). Bearings are taken from "North" (the top direction of the screen) as is the convention. All angles are in radians.
Any help would be much appreciated.