C++ Cocos2d-x多态性

C++ Cocos2d-x多态性,c++,polymorphism,cocos2d-x,virtual,C++,Polymorphism,Cocos2d X,Virtual,我目前正在将我的cocos2dx cpp游戏细分为一个更模块化的系统。我希望有一个层来接收所有的触摸,并将这些触摸指向受影响的CCSprite派生对象 派生对象存储在EntityManager(帮助我创建和管理实体)中的CCArray中 我面临的问题是,我似乎无法为派生的ccsprite访问正确的虚拟方法 以下是我的触摸层(称为TouchManager)的代码: 以及TouchableSprite基类: #include "cocos2d.h" #include "Touchable.h" c

我目前正在将我的cocos2dx cpp游戏细分为一个更模块化的系统。我希望有一个层来接收所有的触摸,并将这些触摸指向受影响的CCSprite派生对象

派生对象存储在EntityManager(帮助我创建和管理实体)中的CCArray中

我面临的问题是,我似乎无法为派生的ccsprite访问正确的虚拟方法

以下是我的触摸层(称为TouchManager)的代码:

以及TouchableSprite基类:

#include "cocos2d.h"
#include "Touchable.h"

class TouchableSprite : public Touchable
{
    //cocos2d::CCTouch* m_pTouch;
public:
    //virtual cocos2d::CCTouch* getTouch();
    //virtual void setTouch( cocos2d::CCTouch* touch );

    static TouchableSprite* createSpriteWithFile( const char* fileName );

    void resetPosition( float positionX = 0.0f , float positionY = 0.0f );


    virtual void onTouch( cocos2d::CCPoint location ) ;
    virtual void onMoved( cocos2d::CCPoint location ) ;
    virtual void onEnded( cocos2d::CCPoint location ) ;


    TouchableSprite(void);
    ~TouchableSprite(void);
};
通过简单的实现(TouchableSprite.cpp):

最后,这里是我的派生类(在本例中为ControlStickPrite):

使用简单的测试实现(跳过创建部件,因为它可以工作):

请帮我把它修好!我不太熟悉虚拟方法的使用,所以可能我错过了一些东西。我对C++和COCOS2DX编程也比较新。 提前谢谢

编辑:感谢@musikov修复了第一部分!我更新了上述代码以反映这些更改。我用std::vector替换了CCArray,以消除从CCObject*

现在,我面临的问题是,当触摸时,永远不会选择ControlStickSprite::onTouch();它始终是可触摸的Sprite::onTouch()。 添加了ControlStickSprite::create和EntityManager::createEntity方法:

我的ControlStickPrite::create()方法如下所示:

ControlStickSprite* ControlStickSprite::create( cocos2d::CCNode* parent )
{
    // auto parent = this->getParent();
    auto entityType = "control-stick";
    auto scale = 6.0f;
    auto rotation = 0.0f;
    auto positionX = RenderSystem::sharedRenderSystem()->getScreenWidth() * 0.9f ;
    auto positionY = RenderSystem::sharedRenderSystem()->getScreenHeight() * 0.25f ;


    auto sprite = EntityManager::sharedManager()->createEntity( 
        parent , 
        entityType , 
        scale , 
        rotation , 
        positionX , 
        positionY 
        );
    m_sprite = ( ControlStickSprite* )sprite;

    return m_sprite;
}
它利用了我的EntityManager:

cocos2d::CCNode* EntityManager::createEntity( cocos2d::CCNode* parent , const char* entityType , float scale , float rotation , float positionX , float positionY )
{
    std::string extension = ".png";
    std::string fileName = entityType + extension;
    auto entity = TouchableSprite::createSpriteWithFile( fileName.c_str() );

    entity->setRotation( rotation );
    entity->setScale( scale );
    entity->resetPosition( positionX , positionY );

    parent->addChild( entity );
    // add to VisibleEntities vector
    this->addEntity( entity , true );

    return entity;
}
void EntityManager::addEntity( cocos2d::CCNode* parent , TouchableSprite* entity )
{
    parent->addChild( entity );
    // add to VisibleEntities vector
    this->addEntity( entity , true );
}
我能想到的唯一一件事是createEntity()方法创建了一个TouchableSprite*,但返回了一个CCNode*,然后我将其转换为ControlStickSprite*。我又做错了吗?:)

谢谢你的帮助

您在TouchableSprite和ControlStickSprite中有错误的创建方法实现。 create方法创建Sprite实例并将其强制转换到TouchableSprite类。这是完全错误的:) 这就是为什么你的程序在setTouch方法调用时崩溃的原因——因为你在Sprite实例中调用了这个方法。 您需要更改创建方法:

添加了控制棒实施

ControlStickSprite.h

#include "cocos2d.h"
#include "RenderSystem.h"
#include "EntityManager.h"
#include "TouchableSprite.h"

class ControlStickSprite : public TouchableSprite
{
public:
    static ControlStickSprite* create();

    bool init();

    void onTouch( cocos2d::CCPoint location ) ;
    void onMoved( cocos2d::CCPoint location ) ;
    void onEnded( cocos2d::CCPoint location ) ;

    ControlStickSprite(void);
    ~ControlStickSprite(void);
};
ControlStickSprite.cpp

bool ControlStickSprite::init()
{
    auto entityType = "control-stick";
    std::string extension = ".png";
    std::string fileName = entityType + extension;

    if (initWithFile( fileName.c_str() )) {
        // auto parent = this->getParent();
        auto scale = 6.0f;
        auto rotation = 0.0f;
        auto positionX = RenderSystem::sharedRenderSystem()->getScreenWidth() * 0.9f ;
        auto positionY = RenderSystem::sharedRenderSystem()->getScreenHeight() * 0.25f ;

        sprite->setRotation( rotation );
        sprite->setScale( scale );
        sprite->resetPosition( positionX , positionY );

        return true;
    }
    return false;
}

ControlStickSprite* ControlStickSprite::create()
{
    auto sprite = new ControlStickSprite();

    if ( sprite && sprite->init() )
    {
        sprite->autorelease();

        return sprite;
    }

    CC_SAFE_DELETE( sprite );

    // should not reach this point
    return NULL;
}
实体管理器:

cocos2d::CCNode* EntityManager::createEntity( cocos2d::CCNode* parent , const char* entityType , float scale , float rotation , float positionX , float positionY )
{
    std::string extension = ".png";
    std::string fileName = entityType + extension;
    auto entity = TouchableSprite::createSpriteWithFile( fileName.c_str() );

    entity->setRotation( rotation );
    entity->setScale( scale );
    entity->resetPosition( positionX , positionY );

    parent->addChild( entity );
    // add to VisibleEntities vector
    this->addEntity( entity , true );

    return entity;
}
void EntityManager::addEntity( cocos2d::CCNode* parent , TouchableSprite* entity )
{
    parent->addChild( entity );
    // add to VisibleEntities vector
    this->addEntity( entity , true );
}

请记住在ControlStickSprite::create()之后调用EntityManager::addEntity(父级,实体),如果您决定使用此解决方案,请解释一下“不再发送”的含义?它不符合你的条件?(entity->boundingBox().containsPoint(点击))感谢您的回复musikov:)它通过了条件(boundingBox().containsPoint(点击)),但在entity->onTouch(点击)和(如果我在entity->setTouch(触摸)处注释该行)时崩溃。它实际上从未到达我的派生类(ControlStickSprite::onTouch)。在这个版本的代码中,我只是得到一个运行时“访问冲突”,所以我认为编译器选择正确的onTouch方法有问题。。。再次感谢!是的,你做错了。。。你最好阅读C++中的多态性理论:以后我会发布一个答案,你怎么解决你的问题。哇!你太棒了!非常感谢。我现在明白我做错了什么,更喜欢你给我看的东西!:)一切都很好@穆斯科夫++:)谢谢你,穆斯科夫!你是对的:当我在create方法中将CCSprite更改为TouchableSprite时,它就停止崩溃了。:)现在我需要弄清楚为什么我的多态性不起作用。。。当我运行这个程序并单击或轻触其中一个精灵时,只会调用“TouchableSprite”onTouch方法,而不会调用ControlStickSprite方法。@Novatex多态性有什么问题?您是否更改了ControlStickSprite中的更改方法?@Novatex向我展示您的ControlStickSprite创建方法谢谢!我在下面添加了一个答案:)另外,我将CCArray更改为std::vector因为我认为这样可以减少从数组中获取项目时的施法需要。@Novatex您最好删除您的答案,因为这不是一个答案,而是一个问题。使用“编辑”按钮将创建方法添加到原始问题
TouchableSprite* TouchableSprite::createSpriteWithFile( const char* fileName )
{
    auto sprite = new TouchableSprite();

    if ( sprite && sprite->initWithFile( fileName ) )
    {
        sprite->autorelease();
        return sprite;
    }

    CC_SAFE_DELETE( sprite );

    // should not reach this point
    return NULL;
}
#include "cocos2d.h"
#include "RenderSystem.h"
#include "EntityManager.h"
#include "TouchableSprite.h"

class ControlStickSprite : public TouchableSprite
{
public:
    static ControlStickSprite* create();

    bool init();

    void onTouch( cocos2d::CCPoint location ) ;
    void onMoved( cocos2d::CCPoint location ) ;
    void onEnded( cocos2d::CCPoint location ) ;

    ControlStickSprite(void);
    ~ControlStickSprite(void);
};
bool ControlStickSprite::init()
{
    auto entityType = "control-stick";
    std::string extension = ".png";
    std::string fileName = entityType + extension;

    if (initWithFile( fileName.c_str() )) {
        // auto parent = this->getParent();
        auto scale = 6.0f;
        auto rotation = 0.0f;
        auto positionX = RenderSystem::sharedRenderSystem()->getScreenWidth() * 0.9f ;
        auto positionY = RenderSystem::sharedRenderSystem()->getScreenHeight() * 0.25f ;

        sprite->setRotation( rotation );
        sprite->setScale( scale );
        sprite->resetPosition( positionX , positionY );

        return true;
    }
    return false;
}

ControlStickSprite* ControlStickSprite::create()
{
    auto sprite = new ControlStickSprite();

    if ( sprite && sprite->init() )
    {
        sprite->autorelease();

        return sprite;
    }

    CC_SAFE_DELETE( sprite );

    // should not reach this point
    return NULL;
}
void EntityManager::addEntity( cocos2d::CCNode* parent , TouchableSprite* entity )
{
    parent->addChild( entity );
    // add to VisibleEntities vector
    this->addEntity( entity , true );
}