Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving a camera in SpriteKit

Tags:

ios

sprite-kit

//UPDATE The updated code has been added that works as I expected. See didSimulatePhysics method in the updated code below. In my case, I only care about moving a character left or right on the x axis where 0 on the x axis is the absolute left and right on the x axis is a configurable value. The Apple adventure game really helped a lot too.

//ORIGINAL POST BELOW

I'm working with Apple SpriteKit and I'm struggling to implement a camera as I would like it to behave. What I've done in the code is load a sprite character, two buttons, and a red box that is off to the right outside of the view at the start. What I'd like to be able to do is move the character with the buttons, and once the player reaches the middle or end of the screen, the camera will then re-adjust to uncover what couldn't be seen in the view. So moving to the right should eventually show the red box that is off outside of the view initially once the player gets there. However, with the code I'm using below, I'm unable to get the camera to follow and adjust the coordinates to the main character at all. I've looked at Apple's advanced scene processing doc as well as a few other stack overflow posts but can't seem to get it right. If anyone could offer some advice it would be appreciated.

enter image description here

#define cameraEdge 150

-(id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        /* Setup your scene here */
        //320 568
        
    
        self.backgroundColor = [SKColor whiteColor];
        
        myWorld = [[SKNode alloc] init];
        [self addChild:myWorld];
        
        mainCharacter = [SKSpriteNode spriteNodeWithImageNamed:@"0"];
        mainCharacter.physicsBody.dynamic = YES;
        mainCharacter.name = @"player";
       
        mainCharacter.position = CGPointMake(20, 20);
        
        CGRect totalScreenSize = CGRectMake(0, 0, 800, 320);
        
        SKSpriteNode *box = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(60, 60)];
        
          SKSpriteNode *boxTwo = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(60, 60)];
           SKSpriteNode *boxThree = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(60, 60)];
        boxThree.position = CGPointMake(40, 50);
        
        [myWorld addChild:boxThree];
        
        boxTwo.position = CGPointMake(1100, 50);
        
        box.position = CGPointMake(650, 50);
        
        [myWorld addChild:box];
        [myWorld addChild:boxTwo];
        
       
       self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:totalScreenSize];
        
        self.physicsWorld.gravity = CGVectorMake(0, -5);
        mainCharacter.name = @"mainCharacter";
  
   
        mainCharacter.physicsBody.linearDamping = 0;
        mainCharacter.physicsBody.friction = 0;
        mainCharacter.physicsBody.restitution = 0;
        mainCharacter.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:mainCharacter.size];
        
       [myWorld addChild:mainCharacter];
      
        [self addChild:[self buildLeftButton]];
        [self addChild:[self buildRightButton]];

    }
    
    return self;
}

- (void)didSimulatePhysics
{
    SKSpriteNode *hero = mainCharacter;
    
    if(hero)
    {
        CGPoint heroPosition = hero.position;
        CGPoint worldPosition = myWorld.position;
        
        NSLog(@"%f", heroPosition.x);
        
        CGFloat xCoordinate = worldPosition.x + heroPosition.x;
        
        if(xCoordinate < cameraEdge && heroPosition.x > 0)
        {
            worldPosition.x = worldPosition.x - xCoordinate + cameraEdge;
            self.worldMovedForUpdate = YES;
        }
        
        else if(xCoordinate > (self.frame.size.width - cameraEdge) && heroPosition.x < 2000)
        {
            worldPosition.x = worldPosition.x + (self.frame.size.width - xCoordinate) - cameraEdge;
            self.worldMovedForUpdate = YES;
        }
        
        myWorld.position = worldPosition;
    }
}

-(SKSpriteNode *)buildLeftButton
{
    SKSpriteNode *leftButton = [SKSpriteNode spriteNodeWithImageNamed:@"left"];
    leftButton.position = CGPointMake(20, 20);
    leftButton.name = @"leftButton";
    leftButton.zPosition = 1.0;
    return leftButton;
}

-(SKSpriteNode *)buildRightButton
{
    SKSpriteNode *leftButton = [SKSpriteNode spriteNodeWithImageNamed:@"right"];
    leftButton.position = CGPointMake(60, 20);
    leftButton.name = @"rightButton";
    leftButton.zPosition = 1.0;
    return leftButton;
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];
    
    if([node.name isEqualToString:@"leftButton"])
    {
             [mainCharacter.physicsBody applyImpulse:CGVectorMake(-120, 0)];
    }
    
    else if([node.name isEqualToString:@"rightButton"])
    {
       [mainCharacter.physicsBody applyImpulse:CGVectorMake(120, 10)];
    }
}
like image 733
zic10 Avatar asked May 25 '14 01:05

zic10


1 Answers

If you want the view to always be centered on your player's position, modify your code with these points in mind:

1) Create a SKNode and call it myWorld, worldNode or any other name like that.

2) Add the worldNode [self addChild:worldNode];

3) Add all other nodes to the worldNode, including your player.

4) In the didSimulatePhysics method, add this code:

worldNode.position = CGPointMake(-(player.position.x-(self.size.width/2)), -(player.position.y-(self.size.height/2)));

Your view will now always be centered on your player's position.

Update May 2015:

If you are using a map created with Tiled Map Editor, you can use the free SKAToolKit framework. Features include player camera auto follow, test player, test HUD and sprite buttons.

like image 68
sangony Avatar answered Sep 24 '22 13:09

sangony