Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding SpriteKit : Moving Sprites

This is my first post and I am trying to use Apple's SpriteKit framework.

I believe I have a misunderstanding of how to move sprites using the framework. I have a simple example where I would like to move a hero in a simple UP, DOWN, LEFT, RIGHT direction based on the a tap location, respective to the "hero" location. Once the hero hits a block the "hero" should stop.

For testing purposes I am just trying to tap above the "hero" hit the wall of blocks on the top of the screen. Then after the collision occurs, tap below the "hero". I was expecting the "hero" to move toward the wall of blocks on the bottom row; however it seem that the "hero" continues to move UP and through the top wall. I am sure I am making a fundamental flaw, I would appreciate any help.

Thanks

Here is the sample scene I wrote:

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
like image 962
some programmer Avatar asked Oct 10 '13 01:10

some programmer


People also ask

Is SpriteKit easy?

SpriteKit is easy to learn because it is a well-designed framework and it is even easier if you have experience with Swift. Even for a beginner, if you want to create your first game, 2D games is without a doubt the best way to transit in this new world.

How do I move a node in SpriteKit?

Swipe diagonally to move node in SpriteKit.

Is SpriteKit still supported?

SpriteKit is supported on iOS, macOS, tvOS, and watchOS, and it integrates well with frameworks such as GameplayKit and SceneKit.

What is the difference between SceneKit and SpriteKit?

SceneKit and SpriteKit are very similar to each other. SceneKit is a little harder to learn but it's pretty simple. SceneKit would be the only way to have a 3D model(With the options you provided). You can have a SpriteKit scene over top of the SceneKit scene to display labels that stay put.


1 Answers

Here try this, you need to remove/disable your touches ended as well

-(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]
                                                  ]]];
    }
}
}
like image 89
DogCoffee Avatar answered Sep 18 '22 16:09

DogCoffee