问题
I'm new to Sprite Kit and I'm wondering how you can make a sprite follow the touches. For example, my player sprite is on the bottom of the screen. When I tap on the top of the screen, the player sprite should move to the touch point with a certain speed - and if I move my finger it should always be pointing towards the touch point. This is how I tried to implement it:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
CGPoint diff = rwSub(location, self.player.position);
CGPoint norm = rwNormalize(diff);
SKAction *act = [SKAction moveByX:norm.x * 10 y:norm.y * 10 duration:0.1];
[self.player runAction:[SKAction repeatActionForever:act] withKey:@"move"];
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
CGPoint diff = rwSub(location, self.player.position);
CGPoint norm = rwNormalize(diff);
SKAction *act = [SKAction moveByX:norm.x * 10 y:norm.y * 10 duration:0.1];
[self.player runAction:[SKAction repeatActionForever:act] withKey:@"move"];
}
}
However, the sprite moves very laggy when moving the finger. Is there a way I can make the movement nice and smooth?
Any help would be greatly appreciated!
EDIT: I think I have found a solution I modified the touchesMoved function:
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
for (UITouch *touch in touches) {
[self.player removeActionForKey:@"move"];
CGPoint location = [touch locationInNode:self];
CGPoint diff = rwSub(location, self.player.position);
CGPoint norm = rwNormalize(diff);
[self.player setPosition: rwAdd(self.player.position, rwMult(norm, 2))];
SKAction *act = [SKAction moveByX:norm.x * 10 y:norm.y * 10 duration:0.01];
[self.player runAction:[SKAction repeatActionForever:act] withKey:@"move"];
}
}
}
回答1:
I'd bind the UITouch
to the Sprite on touchesBegan
, unbind on touchesEnded
. Then on every update approach the UITouch
position with a one pole filter.
No need for actions at all, also you don't need to implement touchesMoved
this way. The whole stuff become more encapsulated.
Or use SKPhysicsJointSpring. Create a node for the touch, then a spring joint that connects your sprite and the touch node. Then adjust touch node position only.
Sprite
@interface ApproachingSprite : SKSpriteNode
@property (nonatomic, weak) UITouch *touch;
@property (nonatomic) CGPoint targetPosition;
-(void)update;
@end
@implementation ApproachingSprite
-(void)update
{
// Update target position if any touch bound.
if (self.touch)
{ self.targetPosition = [self.touch locationInNode:self.scene]; }
// Approach.
CGFloat filter = 0.1; // You can fiddle with speed values
CGFloat inverseFilter = 1.0 - filter;
self.position = (CGPoint){
self.targetPosition.x * filter + self.position.x * inverseFilter,
self.targetPosition.y * filter + self.position.y * inverseFilter,
};
}
@end
Scene
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*) event
{ self.sprite.touch = [touches anyObject]; }
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*) event
{ self.sprite.touch = nil; }
-(void)update:(CFTimeInterval) currentTime
{ [self.sprite update]; }
来源:https://stackoverflow.com/questions/21597014/ios-sprite-kit-how-to-make-sprite-follow-touches