ParallaxNode call addChild to add a sprite object crash

Hi every body, I get a bug when add an object to a ParallaxNode, below is my code.

ParallaxNode* layerMoveLeft = ParallaxNode::create();
this->addChild(layerMoveLeft);

// add enviroment
Sprite* enviroment = Sprite::createWithSpriteFrameName(“enviroment.png”);
float x = _visibleSize.width + enviroment->boundingBox().size.width;
    Vec2 pos = ccp(x,
        100
        );
// the enviroment is child of layer _layerMoveLeft, so set the position of enviroment on the  layerMoveLeft
enviroment->setPosition(layerMoveLeft->convertToNodeSpace(pos));
// set ZOrder for the enviroment
enviroment->setZOrder(2);
layerMoveLeft->addChild(enviroment);

I debug and run to the line layerMoveLeft->addChild(enviroment); it cause crash with message Assertion Failed … .exe File CCParallaxNode.cpp line 101.
Expression: 0

I don’t know how to fix this error, does any one have solution for this bug?

check out cpp-tests there are 3 Parallax examples there.

I try code similar with the examples in cpp-test
layerMoveLeft->addChild(enviroment, 3, Vec2(1.0f, 1.0f), Vec2(100, 100));
It not crash, now i get an others problem

  1. In onEnter i register onTouchBegan event to handle the touch event
    and when the player tuoch the screen i do some things in onTouchBegan method, but it when i touch the onTouchBegan method not called.

void HelloWorld::onEnter()
{
    if (!touchListener)
    {
        auto dispatcher = Director::getInstance()->getEventDispatcher();
        _touchListener = EventListenerTouchOneByOne::create();
        _touchListener->setSwallowTouches(true);
        _touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);

dispatcher->addEventListenerWithSceneGraphPriority(_touchListener, this);
    }
    CCLayer::onEnter();
}

void HelloWorld::onTouchesBegan(const std::vector<Touch*>& touches, Event *event)
{
    // do some things

}

So when the player touch on the screen nothing happen,

  1. The update method of an object not called
    I have some class that inheritance from Component example Hurdle class, the Hurdle have update method, at this method i do update the position of the Hurdle, but i debug the update method not called.

void Hurdle::update(float delta)
{
    // code to update the position of the Hurdle
}

In the cocos2d-x 2.2 it run OK. I don’t know what happen.

I’m not sure you should be putting the touch event on onEnter()

Also, whey are you wrapping the listener in an if conditional?

Why not put the listener in init() or similar?

I’ve change the onTouchBegan to

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
// do some things
    return true;
}
So now when the player touch on the screen, the onTouchBegan called.

But now i still have problem with the update method

void Hurdle::update(float delta)
{
    // code to update the position of the Hurdle
}

I think it should be called every 1/60 (Animation Interval) to update the position. But it never called.
I don’t have any solution, there are a lot of strange in cocos2dx 3.2.

are you making a call to scheduleUpdate() somewhere?

I make call scheduleUpdate(); at the constructors of the class, but i can not build, i get error message
Error    37    error C3861: ‘scheduleUpdate’: identifier not found

Show me…

I wonder to call scheduleUpdate(); what file or namespace should I include?
in my code i declare include #include "cocos2d.h" and USING_NS_CC;

But it not reconize the scheduleUpdate method.
The Hurdle class I inherit from Component class.

At the init method of HelloWorldScence class i add the Hurdle like this

this->addComponent(new Hurdle(this));

Again, show me your .h and .cpp so I can have a look. If scheduleUpdate() isn’t recognized what are you subclassing? Or what is the type of the object you are trying to run scheduleUpdate() on?

This is my Hurdle Class

Hurdle.h file

#ifndef __HURDLE_H__
#define __HURDLE_H__
#include <cocos2d.h>
#include "HelloWorldScene.h"
using namespace cocos2d;

// represent a Hurdle that blocks the character way
class Hurdle :
    public Component
{
public:
    Hurdle(void);
    Hurdle(HelloWorld* parent);
    ~Hurdle(void);
    virtual void update(float delta);
private:
    // the parent sence
    HelloWorld* _parent;
    // time to add the hurdle to the parent sence
    float _duration; 
    
};

#endif // __HURDLE_H__

Hurdle.CPP file

#include "Hurdle.h"
#include "Common.h"

Hurdle::Hurdle(void)
{
    this->setName("Hurdle");
    _duration = 0;
    /*_parent = (HelloWorld*)getOwner();
    if (_parent == NULL) return;
    _parent->addHurdle();*/
}

Hurdle::Hurdle(HelloWorld* parent)
{
    this->setName("Hurdle");
    _duration = 0;
    _parent = parent;
    if (_parent == NULL) return;
    _parent->addHurdle();
    //scheduleUpdate();
    //this->schedule(schedule_selector(Hurdle::update));
}

void Hurdle::update(float delta)
{
    _parent = (HelloWorld*)getOwner();
    //_parent = (HelloWorld*)getParent();
    if (_parent == NULL) return;
    if (!_parent->getGameStart())
        return;
    _duration+= delta;
    float timeToAddHurdle = kTimeToAddHurdle;
    
    if (_duration >= timeToAddHurdle )
    {
        _duration = 0;
        _parent->addHurdle();
    }
}

Hurdle::~Hurdle(void)
{
}

addHurdle() method of HelloWorld class

void HelloWorld::addHurdle()
{

    // using random to calculation the variance in position between Hurdles
    int r = rand();
    r = r % 5;
    int deviationRatio = kDeviationRatio;
    float dy = r * deviationRatio;

    // variance some time upward, sometime downward
    r = rand();
    r = r % 2;
    if (r == 0) dy = -dy;
    
    // add two hurdle, hurdle 1 on the top and the hurdle 2 on the bottom, the distance between them is kDistanceBetweenHurdle1And2
    Sprite* hurdle1 = Sprite::createWithSpriteFrameName(kHurdle1);
    
    Vec2 pos = Vec2(
        _visibleSize.width + hurdle1->boundingBox().size.width / 2,
        _visibleSize.height / 2 + hurdle1->boundingBox().size.height / 2 + distanceBetweenHurdle1And2 / 2 + kGroundHeight / 2 + dy
        );
   
    Sprite* hurdle2 = Sprite::createWithSpriteFrameName(kHurdle2);

    hurdle1->addComponent(new CollisionDetect(_character, true));
    hurdle2->addComponent(new CollisionDetect(_character, false));

    _layerMoveLeft->addChild(hurdle1, 3, Vec2(1.0f, 1.0f), Vec2(
        _visibleSize.width + hurdle1->getBoundingBox().size.width / 2,
        _visibleSize.height / 2 + hurdle1->getBoundingBox().size.height / 2 + distanceBetweenHurdle1And2 / 2 + kGroundHeight / 2 + dy
        ));
    _layerMoveLeft->addChild(hurdle2, 3, Vec2(1.0f, 1.0f), Vec2(
        _visibleSize.width + hurdle1->getBoundingBox().size.width / 2,
        _visibleSize.height / 2 - hurdle2->getBoundingBox().size.height / 2 - distanceBetweenHurdle1And2 + kGroundHeight / 2 + dy
        ));
}

Code to add Hurdle component to the Game sence

Hurdle *hurdle = new Hurdle(this)
this->addComponent(hurdle);

The CollisionDetect class inherit from Component and also have an update method to detect the collision between character and hurdle.

Problem is the update method of Hurdle class, CollisionDetect class, … never called, in the Cocos2dx 2.4 version it run ok. but it have problem when open proj.wp8-xaml so i would like to upgrade to version 3.2.

what is Component?

is it a cocos2d::Component?

if so, you should switch to cocos2d::Node

If you review the API document for cocos2d::Component I think you will see by the inheritance diagram that this is not a class you want to be using for your purposes: http://www.cocos2d-x.org/reference/native-cpp/V3.2/d9/d7f/classcocos2d_1_1_component.html

Yes it is a cocos2d::Component, you said i sould switch to cocos2d::Node but if i switch to cocos2d::Node i think i cannot pass it as an object of addComponent method, these Component used to do some task example collision detect, …

Example

Sprite* hurdle1 = Sprite::createWithSpriteFrameName(kHurdle1);
hurdle1->addComponent(new CollisionDetect(_character, true));

If you need to use Component then my advice of ScheduleUpdate() isn’t appropriate (now that you posted code) as Component doesn’t implement this.

I switch Hurdle, MoveLeft, CollisionDetect and others classes to inherit from cocos2d::Node and call scheduleUpdate(); the update method of Hurdle, MoveLeft and others class are called.

But now i have another problems.

The method addHurdle

void HelloWorld::addHurdle()
{

// using random to calculation the variance in position between Hurdles
    int r = rand();
    r = r % 5;
    int deviationRatio = kDeviationRatio;
    float dy = r * deviationRatio;

// variance some time upward, sometime downward
    r = rand();
    r = r % 2;
    if (r == 0) dy = -dy;

// add two hurdle, hurdle 1 on the top and the hurdle 2 on the bottom, the distance between them is kDistanceBetweenHurdle1And2
    Sprite* hurdle1 = Sprite::createWithSpriteFrameName(kHurdle1);

Vec2 pos = Vec2(
        _visibleSize.width + hurdle1->boundingBox().size.width / 2,
        _visibleSize.height / 2 + hurdle1->boundingBox().size.height / 2 + distanceBetweenHurdle1And2 / 2 + kGroundHeight / 2 + dy
        );

Sprite* hurdle2 = Sprite::createWithSpriteFrameName(kHurdle2);

hurdle1->addComponent(new CollisionDetect(_character, true));
    hurdle2->addComponent(new CollisionDetect(_character, false));

_layerMoveLeft->addChild(hurdle1, 3, Vec2(1.0f, 1.0f), Vec2(
        _visibleSize.width + hurdle1->getBoundingBox().size.width / 2,
        _visibleSize.height / 2 + hurdle1->getBoundingBox().size.height / 2 + distanceBetweenHurdle1And2 / 2 + kGroundHeight / 2 + dy
        ));
    _layerMoveLeft->addChild(hurdle2, 3, Vec2(1.0f, 1.0f), Vec2(
        _visibleSize.width + hurdle1->getBoundingBox().size.width / 2,
        _visibleSize.height / 2 - hurdle2->getBoundingBox().size.height / 2 - distanceBetweenHurdle1And2 + kGroundHeight / 2 + dy
        ));
}

I aim to interval add two opposite hurdles, between them have a gap.
These two hurdle will move from right edge of screen to the left.

The first pair of hurdles start from right edge of screen, the next pair it not start from the right edge of screen, the start position of next pair is near with the current position of the previous pair. I mean if the previous pair moved to the middle of screen, the next pair start at the middle too. It must be start from the right edge.

Maybe i don’t have experience about ParallaxNode and Vec2.

void ParallaxNode::addChild(Node *child, int z, const Vec2& ratio, const Vec2& offset)

I found the solution, when add a Node to ParallaxNode, i should convert the position to the node space by call convertToNodeSpace method

_layerMoveLeft->addChild(hurdle1, _layerMoveLeft->getChildrenCount(), Vec2(0.5f,
        0.5f
        ), _layerMoveLeft->convertToNodeSpace(Vec2(
        _visibleSize.width + dy,
        _visibleSize.height / 2 + hurdle1->getBoundingBox().size.height / 2 + distanceBetweenHurdle1And2 / 2 + kGroundHeight / 2 + dy
        )));
    _layerMoveLeft->addChild(hurdle2, _layerMoveLeft->getChildrenCount(), Vec2(0.5f,
        0.5f
        ), _layerMoveLeft->convertToNodeSpace(Vec2(
        _visibleSize.width + dy,
        _visibleSize.height / 2 - hurdle2->getBoundingBox().size.height / 2 - distanceBetweenHurdle1And2 + kGroundHeight / 2 + dy
        )));