Sprite Kit - define swipe gestures vector to click a sprite

I have a game in which circular objects shoot from the bottom of the screen, and I would like them to carry them in order to click them in the direction of my swipe. My problem is that I don’t know how to calculate the vector / direction of the swipe to get a circular object that can be clicked in the right direction at the appropriate speed.

The static vector "(5.5)" that I use should be calculated by the speed and direction of passage of the wipes. In addition, I need to make sure that as soon as I first contact the object, it will no longer be there to refrain from double-hitting the object. Here is what I am currently doing:

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self]; SKNode* node = [self nodeAtPoint:location]; [node.physicsBody applyImpulse:CGVectorMake(5, 5) atPoint:location]; } } 
+5
source share
3 answers

Here is an example of how to detect gestures:

Define instance variables first to preserve the starting location and time.

  CGPoint start; NSTimeInterval startTime; 

In touchsBegan, save the location / time of the touch event.

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Avoid multi-touch gestures (optional) */ if ([touches count] > 1) { return; } UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInNode:self]; // Save start location and time start = location; startTime = touch.timestamp; } 

Define swipe gestures. Adjust them accordingly.

 #define kMinDistance 25 #define kMinDuration 0.1 #define kMinSpeed 100 #define kMaxSpeed 500 

In touchs.Ended, determine if the user's gesture was successful by comparing the differences between start and end locations and timestamps.

 - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInNode:self]; // Determine distance from the starting point CGFloat dx = location.x - start.x; CGFloat dy = location.y - start.y; CGFloat magnitude = sqrt(dx*dx+dy*dy); if (magnitude >= kMinDistance) { // Determine time difference from start of the gesture CGFloat dt = touch.timestamp - startTime; if (dt > kMinDuration) { // Determine gesture speed in points/sec CGFloat speed = magnitude / dt; if (speed >= kMinSpeed && speed <= kMaxSpeed) { // Calculate normalized direction of the swipe dx = dx / magnitude; dy = dy / magnitude; NSLog(@"Swipe detected with speed = %g and direction (%g, %g)",speed, dx, dy); } } } } 
+9
source

There is another way to do this, you can add a panorama gesture, and then get speed from it:

First add a gesture of movement in your opinion:

 UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)]; [self.view addGestureRecognizer:gestureRecognizer]; 

Then process the gesture:

 - (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer { if (recognizer.state == UIGestureRecognizerStateBegan) { CGPoint location = [recognizer locationInView:recognizer.view]; if ([_object containsPoint:location]){ self.movingObject = YES; <.. object start moving ..> } } else if (recognizer.state == UIGestureRecognizerStateChanged) { if (!self.movingObject) return; CGPoint translation = [recognizer translationInView:recognizer.view]; object.position = CGPointMake(object.position.x + translation.x, object.position.y + translation.y); [recognizer setTranslation:CGPointZero inView:recognizer.view]; } else if (recognizer.state == UIGestureRecognizerStateEnded) { if (!self.movingObject) return; self.movingObject = NO; float force = 1.0f; CGPoint gestureVelocity = [recognizer velocityInView:recognizer.view]; CGVector impulse = CGVectorMake(gestureVelocity.x * force, gestureVelocity.y * force); <.. Move object with that impulse using an animation..> } } 
+1
source

In touchesBegan save the touch location as CGPoint, which you can access throughout the application.

In touchesEnded calculate the distance and direction of your initial touch (Began touch) and lower the touch (touchsEnded). Then apply the appropriate Impulse.

To refrain from double hitting, add the bool canHit that you set to NO when the pulse is applied, and return to YES when you are ready to press again. Before applying a pulse, make sure canHit is set to YES.

0
source

Source: https://habr.com/ru/post/1205450/


All Articles