了解SpriteKit:移动Sprite

时间:2013-10-10 01:07:55

标签: ios objective-c ios7 sprite-kit

这是我的第一篇文章,我正在尝试使用Apple的SpriteKit框架。

我相信我对如何使用框架移动精灵有误解。我有一个简单的示例,我希望根据点击位置在简单的heroUPDOWNLEFT方向移动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

1 个答案:

答案 0 :(得分: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]
                                                  ]]];
    }
}
}