Hey,
I have been messing around and have come up with different gesture methods all built into a class to share.
Here is the location the zip file you can grab: http://www.vantagetechnic.com/programming/iphone/Gestures.zip
Also, I have included a CGPointUtil.h which houses:
CGFloat distanceBetweenPoints (CGPoint first, CGPoint second);
CGFloat angleBetweenPoints(CGPoint first, CGPoint second);
typedef struct
{
CGPoint point1;
CGPoint point2;
} CGLine;
typedef struct
{
CGPoint center;
CGFloat radius;
} CGCircle;
typedef struct
{
CGLine line1;
CGLine line2;
CGPoint center;
} CGX;
typedef struct
{
CGPoint center;
CGFloat width;
CGFloat height;
} CGSquare;
CGCircle CGMakeCircle(CGPoint center, CGFloat radius);
CGX CGMakeX(CGLine line1, CGLine line2, CGPoint center);
CGLine CGMakeLine(CGPoint point1, CGPoint point2);
CGSquare CGMakeSquare(CGPoint center, CGFloat width, CGFloat height);
CGFloat angleBetweenLines(CGLine line1, CGLine line2);
CGFloat distanceBetweenLines(CGLine line1, CGLine line2);
BOOL CGCircleCollision(CGCircle circle1, CGCircle circle2);
The main class that you will want to import for all gestures is "Gestures.h"
In Gestures you will have access to Gestures.circle - for circle gesture, Gestures.X - an X like Gesture, and Gestures.square - square like Gesture. Also, the Gestures class itself has isSwipeLeft, isSwipeRight, isSwipeUp, and isSwipeDown. Along with that you will be using [Gestures startTouch:CGPoint], and [Gestures addPoint:CGPoint]. If you do use the Gestures startTouch and addPoint, then you will have access to the following two functions: [Gestures accelerationSpeedX] - the acceleration speed in X direction of the touch, and [Gestures accelerationSpeedY] - the acceleration speed in Y direction of the touch. Each of those functions uses the standard Acceleration = distance / (0.5 * time^2) formula.
Here are the headers for each file:
Gestures.h
#import <UIKit/UIKit.h>
#import "CGPointUtils.h"
#import "circleGesture.h"
#import "xGesture.h"
#import "squareGesture.h"
@interface Gestures : NSObject {
circleGesture *circle;
xGesture *X;
squareGesture *square;
NSMutableArray *points;
CGPoint firstTouch;
CGPoint lastTouch;
NSTimeInterval firstTouchTime;
NSTimeInterval lastTouchTime;
}
@property (nonatomic, retain) circleGesture *circle;
@property (nonatomic, retain) NSMutableArray *points;
@property (nonatomic, retain) xGesture *X;
@property (nonatomic, retain) squareGesture *square;
@property (readwrite) CGPoint firstTouch;
@property (readwrite) CGPoint lastTouch;
@property (readwrite) NSTimeInterval firstTouchTime;
@property (readwrite) NSTimeInterval lastTouchTime;
-(BOOL) isSwipeLeft:(int) tolerance;
-(BOOL) isSwipeRight:(int) tolerance;
-(BOOL) isSwipeUp:(int) tolerance;
-(BOOL) isSwipeDown:(int) tolerance;
-(void) addPoint:(CGPoint) point;
-(CGPoint) getLeft;
-(CGPoint) getRight;
-(CGPoint) getDown;
-(CGPoint) getUp;
-(CGFloat) accelerationSpeedX;
-(CGFloat) accelerationSpeedY;
@end
circleGesture.h
#import <UIKit/UIKit.h>
#import "CGPointUtils.h"
@interface circleGesture : NSObject {
NSMutableArray *points;
CGPoint firstTouch;
NSTimeInterval firstTouchTime;
float CircleClosureDistanceVariance;
float MaximumCircleTime;
float RadiusVariancePercent;
float OverlapTolerance;
}
@property (nonatomic, retain) NSMutableArray *points;
@property (readwrite) CGPoint firstTouch;
@property (readwrite) NSTimeInterval firstTouchTime;
@property (readwrite) float CircleClosureDistanceVariance;
@property (readwrite) float MaximumCircleTime;
@property (readwrite) float RadiusVariancePercent;
@property (readwrite) float OverlapTolerance;
-(void) startCircle:(CGPoint) touch;
-(void) addPoint:(CGPoint)touch;
-(CGCircle) getCircle;
-(BOOL) isCompleteCircle:(CGPoint)touch;
@end
squareGesture.h
#import <UIKit/UIKit.h>
#import "CGPointUtils.h"
@interface squareGesture : NSObject {
NSMutableArray *points;
CGPoint firstTouch;
CGPoint lastTouch;
CGSquare gestureSquare;
NSTimeInterval firstTouchTime;
float SquareClosureTolerance;
float timeTolerance;
float straightnessTolerance;
float squarenessTolerance;
}
@property (nonatomic, retain) NSMutableArray *points;
@property (readwrite) CGPoint firstTouch;
@property (readwrite) CGPoint lastTouch;
@property (readwrite) CGSquare gestureSquare;
@property (readwrite) NSTimeInterval firstTouchTime;
@property (readwrite) float SquareClosureTolerance;
@property (readwrite) float timeTolerance;
@property (readwrite) float straightnessTolerance;
@property (readwrite) float squarenessTolerance;
-(void) startSquare:(CGPoint) touch;
-(void) addPoint:(CGPoint)touch;
-(CGSquare) getSquare;
-(BOOL) isCompleteSquare;
@end
xGesture.h
#import <UIKit/UIKit.h>
#import "CGPointUtils.h"
@interface xGesture : NSObject {
CGX gestureX;
CGFloat centerTolerance;
CGFloat timeTolerance;
CGPoint firstTouch;
CGPoint lastTouch;
NSTimeInterval firstLineTime;
NSTimeInterval secondLineTime;
int count;
CGLine line1;
CGLine line2;
}
@property (readwrite) CGFloat centerTolerance;
@property (readwrite) CGFloat timeTolerance;
@property (readwrite) CGPoint firstTouch;
@property (readwrite) CGPoint lastTouch;
@property (readwrite) int count;
@property (readwrite) NSTimeInterval firstLineTime;
@property (readwrite) NSTimeInterval secondLineTime;
@property (readwrite) CGX gestureX;
@property (readwrite) CGLine line1;
@property (readwrite) CGLine line2;
-(void) addLine:(CGLine) line;
-(void) startTouch:(CGPoint) point;
-(void) endTouch:(CGPoint) point;
-(BOOL) isX;
-(CGX) getX;
@end
Also here are examples on how to use each one:
Example of all the complex Gestures:
// Note this is assuming you have allocated the Gestures Class in gesture.
// self.gesture = [[Gestures alloc] init];
-(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView: [touch view]];
CGPoint converted = [[Director sharedDirector] convertCoordinate:point];
[self.gesture.circle startCircle:converted];
[self.gesture.X startTouch:converted];
[self.gesture.square startSquare:converted];
return kEventHandled;
}
-(BOOL) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView: [touch view]];
CGPoint converted = [[Director sharedDirector] convertCoordinate:point];
[self.gesture.circle addPoint:converted];
// This part of circle is only needed on move if you
// wish to continue detecting the circle on move instead of
// on release of touch
/*if([self.gesture.circle isCompleteCircle:converted])
{
// Do whatever here on complete circle
// Start a new circle so on move we can keep detecting
// Circles
[self.gesture.circle startCircle:converted];
}
// Reset the start of the circle if over a certain point count
// keeps us from staying in an indefinite NO circle detection
// on move only
if([self.gesture.circle.points count] > 15)
{
[self.gesture.circle startCircle:converted];
}*/
[self.gesture.square addPoint:converted];
}
-(BOOL) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView: [touch view]];
CGPoint converted = [[Director sharedDirector] convertCoordinate:point];
[self.gesture.X endTouch:converted];
if([self.gesture.X isX])
{
//Do whatever on successful X Gesture
}
if([self.gesture.square isCompleteSquare])
{
///Do whatever on successful square gesture
}
}
You may wish to play around with the following settings on the Circle Gesture:
self.gesture.circle.CircleClosureDistanceVariance = CGFloat;
self.gesture.circle.MaximumCircleTime = float;
self.gesture.circle.RadiusVariancePercent = float;
self.gesture.circle.OverlapTolerance = float;
//These are the default values for them:
//CircleClosureDistanceVariance = 50.0;
//MaximumCircleTime = 2.0;
//RadiusVariancePercent = 25.0;
//OverlapTolerance = 3;
You may wish to play around with the following settings on the Square Gesture:
self.gesture.square.SquareClosureTolerance = float;
self.gesture.square.timeTolerance = float;
self.gesture.square.straightnessTolerance = float;
self.gesture.square.squarenessTolerance = float;
//These are the default values
//The values of 80 for straightness and square seem to do
//a good job of keeping it square without allowing a circle
//but yet allowing a loose enough square shape to be detected
//SquareClosureTolerance = 20;
//timeTolerance = 20;
//straightnessTolerance = 80;
//squarenessTolerance = 80;
You may wish to play around with the following on X Gesture:
self.gesture.X.centerTolerance = CGFloat;
self.gesture.X.timeTolerance = CGFloat;
//These are the default values
//centerTolerance = 8;
//timeTolerance = 10;
I have tested each one of the complex gestures and they do work. I have not taken the time to fully test the isSwipe methods, but in theory they should work just fine.
One more note, if you have c++ files you only need to change the .m of these to .mm to be included with other c++ files properly.