Cocos2D v3 CCParallaxNode scrolling can't keep player in focus

140 Views Asked by At

I am very fresher to game development and I need to develop a game like NinjaJump.

I have created a CCParallaxNode to setup scrolling background and added CCPhysicsNode to setup Physics world. I have created player object as shown below.

// Add a sprite
    _sprite = [CCSprite spriteWithImageNamed:@"Icon.png"];
    _sprite.position  = ccp(self.contentSize.width/2,100);
    _sprite.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, _sprite.contentSize} cornerRadius:0.0];
    _sprite.physicsBody.friction = 0.0f;
    _sprite.physicsBody.collisionGroup = @"player";
    _sprite.physicsBody.collisionType = @"Player";
    //_sprite.physicsBody.collisionMask = 0;
    //[self addChild:_sprite];
    [foreground addChild:_sprite];

foreground is just a node added into CCScene to easily manage player in-focus.

// code for physics world
_physicsWorld = [CCPhysicsNode node];
    _physicsWorld.gravity = ccp(0,-100);
    _physicsWorld.debugDraw = YES;
    //_physicsWorld.collisionDelegate = self;
    [self addChild:_physicsWorld];

    _foreground = [CCNode node];
    //[self addChild: _foreground];
    [_physicsWorld addChild: _foreground];

To make player always visible we have implemented update method as

- (void) update:(CFTimeInterval)currentTime {
    // Calculate player y offset
    if (_player.position.y > 200.0f) {
        //_midgroundNode.position = CGPointMake(0.0f, -((_player.position.y - 200.0f)/4));
        _foreground.position = CGPointMake(0.0f, -(_player.position.y - 200.0f));
    }
}

I can't understand but the player scrolls off screen anyhow. The code is written in Cocos2d v3.

I have also setup a demo project to show what I implemented: https://www.dropbox.com/s/5s55d00kk80wun4/HumptyJump-Example.zip?dl=0

Any kind of help is appreciated. Thanks in advance.

2

There are 2 best solutions below

0
Paresh Thakor On BEST ANSWER

I have implemented 2 fixed views changing their positions while physics body goes down ;).

See the same in action

@interface TestScene () {
    CCNode *_background;
    CCNode *_foreground;

    NSArray *grounds; // Keeps track of each of the 2 views
    CCPhysicsNode *_physicsWorld;
}

@implementation TestScene

- (id)init {
    self = [super init];
    if (!self) return(nil);

    // Enable touch handling on scene node
    self.userInteractionEnabled = YES;

    // Physics world setup
    _physicsWorld = [CCPhysicsNode node];
    _physicsWorld.gravity = ccp(0,-100);
    _physicsWorld.debugDraw = YES;
    _physicsWorld.collisionDelegate = self;
    [self addChild:_physicsWorld];

    // Foreground node in which platforms are there and moves downwards as player goes up
    _foreground = [CCNode node];

    // Adding background images
    CCSprite *default1 = [CCSprite spriteWithImageNamed: @"Default.png"];
    [default1 setAnchorPoint: ccp(0, 0)];
    CCSprite *default2 = [CCSprite spriteWithImageNamed: @"Default.png"];
    [default2 setAnchorPoint: ccp(0, 0)];
    [default2 setPosition: ccp(0, default1.contentSize.height)];
    [_foreground addChild: default1];
    [_foreground addChild: default2];

    // Adding into array
    grounds = @[default1, default2];
    // Adding into physics world
    [_physicsWorld addChild: _foreground];

    // creating player
    _player = [CCSprite spriteWithImageNamed: @"Assets.atlas/Player.png"];
    [_player setPosition: ccp(160.0f, 160.0f)];
    _player.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, _player.contentSize} cornerRadius:0]; // 1
    _player.physicsBody.collisionGroup = @"playerGroup"; // 2
    _player.physicsBody.collisionType = @"player";
    //[_physicsWorld addChild:_player];
    [_foreground addChild: _player];

    // Multiple platforms can be added into body, they are static entities only
    PlatformNode *platform = (PlatformNode *)[PlatformNode node];
    [platform createPlatformAtPosition:CGPointMake(110, 50) ofType: PLATFORM_NORMAL];
    [_foreground addChild: platform];

    return self;
}

- (void) update:(CFTimeInterval)currentTime {
    // Take background and physics world down, 163 was Y position of the player
    _physicsWorld.position = ccp(_physicsWorld.position.x, 163 - _player.position.y);

    // loop the ground
    for (CCNode *ground in grounds) {
        // Get the world position
        CGPoint groundWorldPosition = [_physicsWorld convertToWorldSpace: ground.position];
        // Get screen position
        CGPoint groundScreenPosition = [self convertToNodeSpace: groundWorldPosition];
        NSLog(@"Positioning ground ---> world: (%f, %f) & screen: (%f, %f)", groundWorldPosition.x, groundWorldPosition.y, groundScreenPosition.x, groundScreenPosition.y, nil);
        if (groundScreenPosition.y <= -ground.contentSize.height) {
            ground.position = ccp(ground.position.x, ground.position.y + 2 * ground.contentSize.height);
            break;
        }
    }
}

-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    // Take the player upside
    [_player.physicsBody applyImpulse: ccp(0, 215)];
}

@end

This is how I coded the background :).

2
Shoaib On

I could not run your sample code but one thing, I can tell you for sure that there is no need of Physics Engine here.

You just keep your player at a particular height and just move your object right to left. Apply moving parallax background image and objects to give a feel that your character is moving upwards or downwards.

For reference you can see the games like Swing Drop, made on the same approach as above.