我找到了一个对我的游戏有用的小教程:
http://blog.mellenthin.de/archives/2012/02/13/an-one-finger-rotation-gesture-recognizer/
但我无法弄清楚如何将该手势转换为使用cocos2d,我已经在cocos2d中找到了预制手势的示例,但没有自定义手势,是否可能?
编辑仍然存在以下问题:
我已经从下面的Sentinel添加了代码,Gesture和RotateGesture都已添加到我的解决方案中并正在编译。虽然在旋转课中我现在只看到选择器,我该怎么设置它们?由于上面项目中的自定义手势如下所示:
自定义手势的头文件:
#import <Foundation/Foundation.h>
#import <UIKit/UIGestureRecognizerSubclass.h>
@protocol OneFingerRotationGestureRecognizerDelegate <NSObject>
@optional
- (void) rotation: (CGFloat) angle;
- (void) finalAngle: (CGFloat) angle;
@end
@interface OneFingerRotationGestureRecognizer : UIGestureRecognizer
{
CGPoint midPoint;
CGFloat innerRadius;
CGFloat outerRadius;
CGFloat cumulatedAngle;
id <OneFingerRotationGestureRecognizerDelegate> target;
}
- (id) initWithMidPoint: (CGPoint) midPoint
innerRadius: (CGFloat) innerRadius
outerRadius: (CGFloat) outerRadius
target: (id) target;
- (void)reset;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
@end
.m用于自定义手势文件:
#include <math.h>
#import "OneFingerRotationGestureRecognizer.h"
@implementation OneFingerRotationGestureRecognizer
// private helper functions
CGFloat distanceBetweenPoints(CGPoint point1, CGPoint point2);
CGFloat angleBetweenLinesInDegrees(CGPoint beginLineA,
CGPoint endLineA,
CGPoint beginLineB,
CGPoint endLineB);
- (id) initWithMidPoint: (CGPoint) _midPoint
innerRadius: (CGFloat) _innerRadius
outerRadius: (CGFloat) _outerRadius
target: (id <OneFingerRotationGestureRecognizerDelegate>) _target
{
if ((self = [super initWithTarget: _target action: nil]))
{
midPoint = _midPoint;
innerRadius = _innerRadius;
outerRadius = _outerRadius;
target = _target;
}
return self;
}
/** Calculates the distance between point1 and point 2. */
CGFloat distanceBetweenPoints(CGPoint point1, CGPoint point2)
{
CGFloat dx = point1.x - point2.x;
CGFloat dy = point1.y - point2.y;
return sqrt(dx*dx + dy*dy);
}
CGFloat angleBetweenLinesInDegrees(CGPoint beginLineA,
CGPoint endLineA,
CGPoint beginLineB,
CGPoint endLineB)
{
CGFloat a = endLineA.x - beginLineA.x;
CGFloat b = endLineA.y - beginLineA.y;
CGFloat c = endLineB.x - beginLineB.x;
CGFloat d = endLineB.y - beginLineB.y;
CGFloat atanA = atan2(a, b);
CGFloat atanB = atan2(c, d);
// convert radiants to degrees
return (atanA - atanB) * 180 / M_PI;
}
#pragma mark - UIGestureRecognizer implementation
- (void)reset
{
[super reset];
cumulatedAngle = 0;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if ([touches count] != 1)
{
self.state = UIGestureRecognizerStateFailed;
return;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
CGPoint nowPoint = [[touches anyObject] locationInView: self.view];
CGPoint prevPoint = [[touches anyObject] previousLocationInView: self.view];
// make sure the new point is within the area
CGFloat distance = distanceBetweenPoints(midPoint, nowPoint);
if ( innerRadius <= distance
&& distance <= outerRadius)
{
// calculate rotation angle between two points
CGFloat angle = angleBetweenLinesInDegrees(midPoint, prevPoint, midPoint, nowPoint);
// fix value, if the 12 o'clock position is between prevPoint and nowPoint
if (angle > 180)
{
angle -= 360;
}
else if (angle < -180)
{
angle += 360;
}
// sum up single steps
cumulatedAngle += angle;
// call delegate
if ([target respondsToSelector: @selector(rotation:)])
{
[target rotation:angle];
}
}
else
{
// finger moved outside the area
self.state = UIGestureRecognizerStateFailed;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
if (self.state == UIGestureRecognizerStatePossible)
{
self.state = UIGestureRecognizerStateRecognized;
if ([target respondsToSelector: @selector(finalAngle:)])
{
[target finalAngle:cumulatedAngle];
}
}
else
{
self.state = UIGestureRecognizerStateFailed;
}
cumulatedAngle = 0;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
self.state = UIGestureRecognizerStateFailed;
cumulatedAngle = 0;
}
@end
然后它的初始化如下:
// calculate center and radius of the control
CGPoint midPoint = CGPointMake(image.frame.origin.x + image.frame.size.width / 2,
image.frame.origin.y + image.frame.size.height / 2);
CGFloat outRadius = image.frame.size.width / 2;
// outRadius / 3 is arbitrary, just choose something >> 0 to avoid strange
// effects when touching the control near of it's center
gestureRecognizer = [[OneFingerRotationGestureRecognizer alloc] initWithMidPoint: midPoint
innerRadius: outRadius / 3
outerRadius: outRadius
target: self];
[self.view addGestureRecognizer: gestureRecognizer];
下面的选择器也位于gestureRecogonizer初始化的同一个文件中:
- (void) rotation: (CGFloat) angle
{
// calculate rotation angle
imageAngle += angle;
if (imageAngle > 360)
imageAngle -= 360;
else if (imageAngle < -360)
imageAngle += 360;
// rotate image and update text field
image.transform = CGAffineTransformMakeRotation(imageAngle * M_PI / 180);
[self updateTextDisplay];
}
我似乎无法在RotateGesture课程中工作,任何人都可以帮助我,我已经被困在这几天了。
答案 0 :(得分:1)
以下是关于GitHub的项目:SFGestureRecognizers
它使用iOS UIGestureRecognizer中的构建,不需要集成到cocos2d源中。使用它,如果你可以使用UIGestureRecognizer,你可以像你一样做任何手势。
例如:
我创建了一个基类Gesture
,并将其子类化为任何新手势:
//Gesture.h
@interface Gesture : NSObject <UIGestureRecognizerDelegate>
{
UIGestureRecognizer *gestureRecognizer;
id delegate;
SEL preSolveSelector;
SEL possibleSelector;
SEL beganSelector;
SEL changedSelector;
SEL endedSelector;
SEL cancelledSelector;
SEL failedSelector;
BOOL preSolveAvailable;
CCNode *owner;
}
- (id)init;
- (void)addGestureRecognizerToNode:(CCNode*)node;
- (void)removeGestureRecognizerFromNode:(CCNode*)node;
-(void)recognizer:(UIGestureRecognizer*)recognizer;
@end
//Gesture.m
#import "Gesture.h"
@implementation Gesture
- (id)init
{
if (!(self = [super init]))
return self;
preSolveAvailable = YES;
return self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch
{
//! For swipe gesture recognizer we want it to be executed only if it occurs on the main layer, not any of the subnodes ( main layer is higher in hierarchy than children so it will be receiving touch by default )
if ([recognizer class] == [UISwipeGestureRecognizer class])
{
CGPoint pt = [touch locationInView:touch.view];
pt = [[CCDirector sharedDirector] convertToGL:pt];
for (CCNode *child in owner.children)
{
if ([child isNodeInTreeTouched:pt])
{
return NO;
}
}
}
return YES;
}
- (void)addGestureRecognizerToNode:(CCNode*)node
{
[node addGestureRecognizer:gestureRecognizer];
owner = node;
}
- (void)removeGestureRecognizerFromNode:(CCNode*)node
{
[node removeGestureRecognizer:gestureRecognizer];
}
#pragma mark - Private methods
-(void)recognizer:(UIGestureRecognizer*)recognizer
{
CCNode *node = recognizer.node;
if (preSolveSelector && preSolveAvailable)
{
preSolveAvailable = NO;
[delegate performSelector:preSolveSelector withObject:recognizer withObject:node];
}
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStatePossible && possibleSelector)
{
[delegate performSelector:possibleSelector withObject:recognizer withObject:node];
}
else if (state == UIGestureRecognizerStateBegan && beganSelector)
[delegate performSelector:beganSelector withObject:recognizer withObject:node];
else if (state == UIGestureRecognizerStateChanged && changedSelector)
[delegate performSelector:changedSelector withObject:recognizer withObject:node];
else if (state == UIGestureRecognizerStateEnded && endedSelector)
{
preSolveAvailable = YES;
[delegate performSelector:endedSelector withObject:recognizer withObject:node];
}
else if (state == UIGestureRecognizerStateCancelled && cancelledSelector)
{
preSolveAvailable = YES;
[delegate performSelector:cancelledSelector withObject:recognizer withObject:node];
}
else if (state == UIGestureRecognizerStateFailed && failedSelector)
{
preSolveAvailable = YES;
[delegate performSelector:failedSelector withObject:recognizer withObject:node];
}
}
@end
子类示例:
//RotateGesture.h
#import "Gesture.h"
@interface RotateGesture : Gesture
- (id)initWithTarget:(id)target
preSolveSelector:(SEL)preSolve
possibleSelector:(SEL)possible
beganSelector:(SEL)began
changedSelector:(SEL)changed
endedSelector:(SEL)ended
cancelledSelector:(SEL)cancelled
failedSelector:(SEL)failed;
@end
//RotateGesture.m
#import "RotateGesture.h"
@implementation RotateGesture
- (id)initWithTarget:(id)target
preSolveSelector:(SEL)preSolve
possibleSelector:(SEL)possible
beganSelector:(SEL)began
changedSelector:(SEL)changed
endedSelector:(SEL)ended
cancelledSelector:(SEL)cancelled
failedSelector:(SEL)failed
{
if (!(self = [super init]))
return self;
preSolveSelector = preSolve;
delegate = target;
possibleSelector = possible;
beganSelector = began;
changedSelector = changed;
endedSelector = ended;
cancelledSelector = cancelled;
failedSelector = failed;
gestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(recognizer:)];
gestureRecognizer.delegate = self;
return self;
}
@end
使用示例:
- (void)addRotateGesture
{
RotateGesture *rotateRecognizer = [[RotateGesture alloc] initWithTarget:self
preSolveSelector:@selector(rotateGesturePreSolveWithRecognizer:node:)
possibleSelector:nil
beganSelector:@selector(rotateGestureStateBeganWithRecognizer:node:)
changedSelector:@selector(rotateGestureStateChangedWithRecognizer:node:)
endedSelector:@selector(rotateGestureStateEndedWithRecognizer:node:)
cancelledSelector:@selector(rotateGestureStateCancelledWithRecognizer:node:)
failedSelector:@selector(rotateGestureStateFailedWithRecognizer:node:)];
[rotateRecognizer addGestureRecognizerToNode:movableAreaSprite];
}
......你只需要实现所需的选择。
这是我的角度计算。在我的情况下,我只是使用一个按钮,它是最后两个位置。 - (void)onRotatorDraggedWithArgs:(EventArgs *)e { CGPoint buttonPosition = [e.params CGPointValue]; float angle = atanf((buttonPosition.x - currentCastPosition.x)/(buttonPosition.y - currentCastPosition.y));
if (buttonPosition.y > currentCastPosition.y)
angle -= M_PI_2;
else
angle += M_PI_2;
currentCastAngle = CC_RADIANS_TO_DEGREES(angle);
[worldState.activeCastIcon rotateToAngle:currentCastAngle animated:NO];
currentPosition = buttonPosition;
}