How to hit objects with finger movement in Sprite

2020-02-29 11:22发布

问题:

I'm trying to make a game in which I have some SKSpriteNodes and the User can hit them with finger movement, I'm using apple's new Sprite Kit.

To do that I tried a trick - placing a Sprite - "X" (SKSpriteNode) where the finger is, and when the user moves the finger - change the position of this X sprite,

the problem is that it will hit the other sprites only if it's not in movement, I want the other sprites to respond to the current velocity of the moving finger- the faster the finger movement is- the stronger the collision should be.

Can you please assist me?

  • Although I feel the trick is not the right way to do this,I'm posting the code too.

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        if([touches count]==1)
        {
            self.X= [[SKSpriteNode alloc]initWithImageNamed:@"X"];
            self.X.name= @"X";
            UITouch *t= touches.allObjects[0];          
    
            self.X.position= [t locationInNode:self.GameNode];
            self.X.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:20];
            self.X.physicsBody.dynamic=YES; // Tried NO too...
            self.X.zPosition=1;
    
            [self.GameNode addChild:self.X];
        }
    }
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *t = touches.allObjects[0];
        self.X.position = [t locationInNode:self.GameNode];
    }
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [self.X removeFromParent];
    }
    

回答1:

After searching and making a lot of experiments, I finally have an answer!

The first step in the solution was provided by AyatollahAndy - finding the point of impact:

SKNode *node = [self nodeAtPoint:location];

this line gets the node that we hit in the specified location, if it returns nil we didn't hit anything.

secondly- we want to "Hit" the object, therefor we need to ApplyImpulse:

[node.physicsBody applyImpulse:CGVectorMake(thrustV.x, thrustV.y) atPoint:location];

Here you can see I applied the impulse with some vector that I created at the point of impact, That's it - pretty straight forward, I hope this will help others.

Sharing is caring, Thanks for taking the time to read my post.



回答2:

You could do something like this.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    touchOn=YES;
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self.parent];
    touchPos =location;
    [self.physicsBody setVelocity:CGVectorMake(0, 0)];

}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    touchOn=YES;
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self.parent];
    touchPos =location;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    touchOn=NO;
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    touchOn=NO;
}
-(void)update:(NSTimeInterval)dt {
    if (touchOn) {
        CGVector vector = CGVectorMake((touchPos.x-self.position.x)/dt, (touchPos.y-self.position.y)/dt);
        self.physicsBody.velocity=vector;
    }
}

Subclass a node and make a method called update that receives updates from the scene along with the change in time. Also add touches methods and keep track of the current touch position.



回答3:

Haven't had time to actually run this but how about something like this: don't bother with putting a node X like described above, rather:

In touchesBegan, keep track of the time and position of the touch

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];

    //store location of first touch
    self.firstTouch = location;

    //get time
    self.startTouch = [NSDate date];
}

In touchesMoved, check if you have touched any of the nodes, If so, work out the angle and speed based on the start and end positions of the touch and then apply velocity to the impacted node?

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];

    //if you've touched one of your nodes
    if ([node.name isEqualToString:@"whateverNode"]) {
     //work out time between touches
     NSTimeInterval timeBetween = [[NSDate date] timeIntervalSinceDate:self.startTouch];

     //work out angle between touches (if you want to send the impacted node in that direction)
     float angle = atan2f (location.y - self.firstTouch.y, location.x - self.firstTouch.y) ;

     //apply to node
     CGFloat thrust = 0.01/timeBetween; 

     CGPoint thrustVector = CGPointMake(thrust*cosf(angle),
               thrust*sinf(angle));
     [node.physicsBody applyTorque:thrustVector];
    }
}

Note the physics bit at the end could be (completely) incorrect.