2016-02-25 101 views
4

我在我的遊戲,無需配對SKFieldNode不能存在的精靈,所以我的解決方案是創建的SKSpriteNode一個子類,併爲SKFieldNode一個屬性,但它沒有工作,因爲SKSpriteNode表現奇怪(我不記得發生了什麼)。所以我的下一個方法是將子類更改爲SKNode,然後我將SKSpriteNodeSKFieldNode作爲這個新的SKNode的一個屬性。但後來事實證明,touchesMoved將只移動其中一個屬性(以最高者爲準),其結果始終是SKSpriteNodeSKNode子類不流動兒童

什麼是解決這個問題的最佳方法,以及如何解決這個問題,這樣我就可以爲每個SKSpriteNode設置一個SKFieldNode,同時仍然確保操作和方法仍然正常工作。

當前SKNode子類代碼:

@interface Whirlpool : SKNode 
- (instancetype)initWithPosition:(CGPoint)pos region:(float)region strength:(float)strength falloff:(float)falloff; 
@property (nonatomic, strong) SKFieldNode *gravityField; 
@end 

#import "Whirlpool.h" 
#import "Categories.h" 

@implementation Whirlpool 
- (instancetype)initWithPosition:(CGPoint)pos region:(float)region strength:(float)strength falloff:(float)falloff { 
    if (self = [super init]) { 
     // whirlpool sprite 
     SKSpriteNode *whirlpoolSprite = [[SKSpriteNode alloc] initWithImageNamed:@"whirlpool"]; 
     whirlpoolSprite.size = CGSizeMake(100, 100); 
     whirlpoolSprite.position = pos; 
     //removing physicsBody and associated attributes for now so that the boat does not collide with the whirlpool 
     //whirlpoolSprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:whirlpoolSprite.size.width/2]; 
     //whirlpoolSprite.physicsBody.dynamic = NO; 
     whirlpoolSprite.zPosition = 1; 
     whirlpoolSprite.name = @"whirlpool"; 
     [whirlpoolSprite runAction:[SKAction repeatActionForever:[self sharedRotateAction]]]; 

     // whirlpool gravity field 
     _gravityField = [SKFieldNode radialGravityField]; 
     _gravityField.position = pos; 
     _gravityField.strength = strength; 
     _gravityField.falloff = falloff; 
     _gravityField.region = [[SKRegion alloc] initWithRadius:region]; 
     _gravityField.physicsBody.categoryBitMask = gravityFieldCategory; 
     _gravityField.zPosition = 1; 

     [self addChild:whirlpoolSprite]; 
     [self addChild:_gravityField]; 
    } 

    return self; 
} 

- (SKAction *)sharedRotateAction { 
    static SKAction *rotateWhirlpool; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     rotateWhirlpool = [SKAction rotateByAngle:-M_PI * 2 duration:4.0]; 
    }); 

    return rotateWhirlpool; 
} 

@end 

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    // we don't want the player to be able to move the whirlpools after the button is pressed 
    if (_isRunning) { 
     return; 
    } 

    for (UITouch *touch in touches) { 
     CGPoint location = [touch locationInNode:self]; 
     SKNode *node = [self nodeAtPoint:location]; 
     // if the finger touches the boat or the whirlpool, update its location 
     if ([node.name isEqualToString:@"boat"]) { 
      node.position = CGPointMake(location.x, node.position.y); 
     } else if ([node.name isEqualToString:@"whirlpool"]) { 
      node.position = location; 
     } 
    } 
} 
+0

你可以發佈你的'touchesMoved'嗎? –

+0

@ChrisSlowik用代碼更新了帖子。 –

回答

2

我相信你的問題歸結爲「漩渦」是你的SKNode子類的一個孩子。因此,當您確定您確實觸摸了「漩渦」時,您將在其父母(SKNode子類)內移動它,並將SKFieldNode和父母留下。對原始代碼進行這種小調整應該可行......如果我正確理解問題。

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    // we don't want the player to be able to move the whirlpools after the button is pressed 
    if (_isRunning) { 
     return; 
    } 

    for (UITouch *touch in touches) { 
     CGPoint location = [touch locationInNode:self]; 
     SKNode *node = [self nodeAtPoint:location]; 
     // if the finger touches the boat or the whirlpool, update its location 
     if ([node.name isEqualToString:@"boat"]) { 
      node.position = CGPointMake(location.x, node.position.y); 
     } else if ([node.name isEqualToString:@"whirlpool"]) { 
      //move the SKNode subclass the whirlpool is a child of 
      node.parent.position = location; 
     } 
    } 
} 

希望有幫助。

0

哎呀,這裏的問題是要抓住節點的方式,你可能會被抓住,由於所有的孩子錯誤的節點。相反,採取這種做法:

我們已經知道,你繼承你的精靈,所以在你的子類,添加以下代碼:

//Whirlpool 
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    for (UITouch *touch in touches) { 
     CGPoint location = [touch locationInNode:self.parent];//Unless you are retaining the scene in the child, then use that 
     self.position = location; 
    } 
} 

然後:

//Boat 
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    for (UITouch *touch in touches) { 
     CGPoint location = [touch locationInNode:self.parent];//Unless you are retaining the scene in the child, then use that 
     self.position.x = location.x; 
    } 
} 

然後爲場景,這樣做:

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
    // we don't want the player to be able to move the whirlpools after the button is pressed 
    if (_isRunning) { 
     return; 
    } 
    //At this point it should call the children on touch events 
    [super.touchesMoved: touches withEvent:event]; 
}