2013-10-10 162 views
6

這是我的第一篇文章,我嘗試使用Apple的SpriteKit框架。瞭解SpriteKit:移動精靈

我相信我對如何使用框架移動子畫面存在誤解。我有一個簡單的示例,其中我想根據水龍頭位置將「hero」移動到簡單的UP,DOWN,LEFT,RIGHT方向,分別位於「英雄」位置。一旦英雄擊中block,「英雄」應該停止。

出於測試目的,我只是試圖點擊上方的「英雄」擊中屏幕頂部的塊牆。然後發生碰撞後,點擊「英雄」下方。我期待着「英雄」走向最下面的一排牆;然而,「英雄」似乎繼續向上移動並穿過頂部牆壁。我確信我正在犯一個根本性的缺陷,我會很感激任何幫助。

感謝

下面是示例場景我寫道:

static inline CGPoint CGPointSubtract(const CGPoint a, const CGPoint b) 
{ 
    return CGPointMake(a.x - b.x, a.y - b.y); 
} 

typedef enum DIRECTION_e 
{ 
    UP, 
    DOWN, 
    LEFT, 
    RIGHT 
} DIRECTION_t; 

typedef NS_OPTIONS(uint32_t, CNPhysicsCategory) 
{ 
    PhysicsCategoryBlock = 1 << 0, 
    PhysicsCategoryHero = 1 << 1 
}; 

@interface LevelScene() 
    @property (nonatomic) SKSpriteNode * hero; 
    @property (nonatomic) BOOL inMotion; 
@end 

@implementation LevelScene 

-(id) initWithSize:(CGSize)size 
{ 
    if (self = [super initWithSize:size]) 
    { 
     self.physicsWorld.gravity = CGVectorMake(0,0); 

     self.physicsWorld.contactDelegate = self; 

     [self createLevel]; 
     [self createHero]; 

     self.inMotion = NO; 
    } 
    return self; 
} 

- (void) createHero 
{ 
    [self addHeroAtRow:5 column:2]; 
} 

- (void) createLevel 
{ 
    self.backgroundColor = [SKColor blackColor]; 
    self.scaleMode = SKSceneScaleModeAspectFit; 

    [self addBlockAtRow:1 column:1]; 
    [self addBlockAtRow:1 column:2]; 
    [self addBlockAtRow:1 column:3]; 

    [self addBlockAtRow:10 column:1]; 
    [self addBlockAtRow:10 column:2]; 
    [self addBlockAtRow:10 column:3]; 
} 

- (void) addBlockAtRow:(NSInteger)row column:(NSInteger)column 
{ 
    SKSpriteNode *block = [[SKSpriteNode alloc] initWithColor:[SKColor brownColor]  size:CGSizeMake(64,64)]; 
    block.position = CGPointMake(32 + (column * 64), 32 + ((11-row) * 64)); 
    block.name = @"block"; 

    block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size]; 

    block.physicsBody.dynamic   = NO; 
    block.physicsBody.categoryBitMask = PhysicsCategoryBlock; 
    block.physicsBody.collisionBitMask = PhysicsCategoryBlock | PhysicsCategoryHero; 
    block.physicsBody.contactTestBitMask = PhysicsCategoryBlock | PhysicsCategoryHero; 

    [self addChild:block]; 
} 

- (void) addHeroAtRow:(NSInteger)row column:(NSInteger)column 
{ 
    self.hero = [[SKSpriteNode alloc] initWithColor:[SKColor redColor] size:CGSizeMake(64,64)]; 
    self.hero.position = CGPointMake(32 + (column * 64), 32 + ((11-row) * 64)); 
    self.hero.name = @"hero"; 
    self.hero.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.hero.size.width/2, self.hero.size.height/2)]; 
    self.hero.physicsBody.usesPreciseCollisionDetection = YES; 

    self.hero.physicsBody.dynamic   = YES; 
    self.hero.physicsBody.categoryBitMask = PhysicsCategoryHero; 
    self.hero.physicsBody.collisionBitMask = PhysicsCategoryHero | PhysicsCategoryBlock; 
    self.hero.physicsBody.contactTestBitMask = PhysicsCategoryHero | PhysicsCategoryBlock; 

    [self addChild:self.hero]; 

    NSLog(@"ADDING HERO: %f, %f", self.hero.position.x, self.hero.position.y); 
} 

- (void)didBeginContact:(SKPhysicsContact *)contact 
{ 
    if (contact.bodyA.categoryBitMask == PhysicsCategoryBlock && contact.bodyB.categoryBitMask == PhysicsCategoryHero) 
    { 
     [self.hero removeAllActions]; 
     self.hero.position = contact.bodyB.node.position; 
     NSLog(@"COLLISION: %f, %f", self.hero.position.x, self.hero.position.y); 
     self.inMotion = NO; 
    } 
    else if (contact.bodyB.categoryBitMask == PhysicsCategoryBlock && contact.bodyA.categoryBitMask == PhysicsCategoryHero) 
    { 
     [self.hero removeAllActions]; 
     self.hero.position = contact.bodyA.node.position; 
     NSLog(@"COLLISION: %f, %f", self.hero.position.x, self.hero.position.y); 
     self.inMotion = NO; 
    } 
} 


- (void) moveHeroTowardDirection:(DIRECTION_t)direction 
{ 
    CGPoint location; 

    switch (direction) 
    { 
     case UP: 
     { 
      location = CGPointMake(self.hero.position.x, self.hero.position.y + 600); 
     } 
      break; 

     case DOWN: 
     { 
      location = CGPointMake(self.hero.position.x, self.hero.position.y + -600); 
     } 
      break; 

     case LEFT: 
     { 
      location = CGPointMake(self.hero.position.x + -600, self.hero.position.y); 
     } 
      break; 

     case RIGHT: 
     { 
      location = CGPointMake(self.hero.position.x + 600, self.hero.position.y); 
     } 
      break; 

     default: return; 
    } 

    NSLog(@"MOVE POSITION: %f, %f", location.x, location.y); 

    SKAction *action = [SKAction moveTo:location duration:10]; 
    [self.hero runAction:action]; 
} 

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    if (self.inMotion) 
     return; 

    self.inMotion = YES; 

    UITouch *touch = [touches anyObject]; 
    CGPoint touchLocation = [touch locationInView:self.view]; 
    CGPoint diff = CGPointSubtract(self.hero.position, touchLocation); 

    NSLog(@"TOUCH POSITION: %f, %f", touchLocation.x, touchLocation.y); 
    NSLog(@"HERO POSITION: %f, %f", self.hero.position.x, self.hero.position.y); 
    NSLog(@"DIFF POSITION: %f, %f", diff.x, diff.y); 

    // 
    // Magnitude to find out which direction is dominate 
    // 
    if (abs(diff.x) > abs(diff.y)) 
    { 
     if (touchLocation.x > self.hero.position.x) 
     { 
      NSLog(@"LEFT"); 
      [self moveHeroTowardDirection:LEFT]; 
     } 
     else 
     { 
      NSLog(@"RIGHT"); 
      [self moveHeroTowardDirection:RIGHT]; 
     } 
    } 
    else 
    { 
     if (touchLocation.y < self.hero.position.y) 
     { 
      NSLog(@"UP"); 
      [self moveHeroTowardDirection:UP]; 
     } 
     else 
     { 
      NSLog(@"DOWN"); 
      [self moveHeroTowardDirection:DOWN]; 
     } 
    } 
} 

@end 
+0

這將幫助HTTP: //stackoverflow.com/questions/19172140/skaction-move-forward/19172574#19172574 – DogCoffee

+0

@Smick精彩。謝謝 –

+0

@Smick我想給你信用的答案。什麼是最好的方式來做到這一點?對不起,我是新來的。 –

回答

5

這裏試試這個,你需要刪除/禁用觸摸結束以及

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

for (UITouch *touch in touches) { 

    for (UITouch *touch in touches) { 

     CGPoint location = [touch locationInNode:self]; 

     CGPoint diff = CGPointMake(location.x - self.hero.position.x, location.y - self.hero.position.y); 

     CGFloat angleRadians = atan2f(diff.y, diff.x); 

     [self.hero runAction:[SKAction sequence:@[ 
                [SKAction rotateToAngle:angleRadians duration:1.0], 
                [SKAction moveByX:diff.x y:diff.y duration:3.0] 
                ]]]; 
    } 
} 
}