我是Sprite Kit的新手,我想知道如何让精灵跟随触摸。例如,我的播放器精灵位于屏幕的底部。当我点击屏幕顶部时,玩家精灵应该以一定的速度移动到触摸点 - 如果我移动手指,它应该总是指向触摸点。这就是我尝试实现它的方式:
-(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"];
}
}
然而,当移动手指时,精灵移动非常迟钝。有没有办法让运动变得美妙动人?
非常感谢任何帮助!
编辑:我想我找到了一个修改了touchesMoved函数的解决方案:- (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"];
}
}
}
答案 0 :(得分:3)
我将UITouch
绑定到touchesBegan
上的精灵,解除touchesEnded
上的绑定。然后在每次更新时使用单极点过滤器接近UITouch
位置。
根本不需要采取任何行动,也不需要以这种方式实施touchesMoved
。整个东西变得更加封装。
或使用SKPhysicsJointSpring
。为触摸创建一个节点,然后创建一个连接您的精灵和触摸节点的弹簧接头。然后仅调整触摸节点位置。
@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
-(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]; }