繁体   English   中英

Cocos2d-x多态性

[英]Cocos2d-x Polymorphism

我目前正在将cocos2dx-cpp游戏细分为一个更具模块化的系统。 我希望有一层可以接收所有Touch,并将这些Touch定向到受影响的CCSprite派生的对象。

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

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

这是我的Touch层(称为TouchManager)中的代码:

void TouchManager::ccTouchesBegan( cocos2d::CCSet* pTouches , cocos2d::CCEvent* pEvents )
{
    cocos2d::CCSetIterator i;
    cocos2d::CCTouch* touch;
    cocos2d::CCPoint tap;

    auto entities = EntityManager::sharedManager()->getVisibleEntities();

    for ( i = pTouches->begin() ; i != pTouches->end() ; ++i )
    {
        touch = ( cocos2d::CCTouch* ) ( *i );
        if ( touch )
        {
            tap = touch->getLocation();

            for ( unsigned int entityIndex = 0 ; entityIndex < entities->size() ; ++entityIndex )
            {
                auto entity = entities->at( entityIndex );
                // OLD: auto entity = ( TouchableSprite* )entities->objectAtIndex( entityIndex );
                if ( entity->boundingBox().containsPoint( tap ) )
                {
                    entity->setTouch( touch );
                    entity->onTouch( tap );
                }
            }
        }
    }
}  

我想让TouchManager检测到已被触摸的实体,并将Touch发送给它。 但是有一个我的问题:它可以检测到触摸,但不能进一步发送。 要么我崩溃了,要么什么都没有。

我创建了一个Touchable接口类:

#include "cocos2d.h"

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

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

};

以及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):

#include "TouchableSprite.h"


TouchableSprite::TouchableSprite(void)
{
}


TouchableSprite::~TouchableSprite(void)
{
}

TouchableSprite* TouchableSprite::createSpriteWithFile( const char* fileName )
{
    auto sprite = new TouchableSprite();

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

    CC_SAFE_DELETE( sprite );

    // should not reach this point
    return NULL;
}

void TouchableSprite::resetPosition( float positionX , float positionY )
{
    this->setPosition( ccp( positionX , positionY ) );
}

void TouchableSprite::onTouch( cocos2d::CCPoint location )
{
}

void TouchableSprite::onMoved( cocos2d::CCPoint location )
{
}

void TouchableSprite::onEnded( cocos2d::CCPoint location )
{
}

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

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

class ControlStickSprite : public TouchableSprite
{
    ControlStickSprite* m_sprite;

public:
    cocos2d::CCNode* create( cocos2d::CCNode* parent ); 

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

    ControlStickSprite(void);
    ~ControlStickSprite(void);
};

通过简单的测试实现(跳过“创建”部分,因为它可以工作):

void ControlStickSprite::onTouch( cocos2d::CCPoint location )
{
    this->setScale( 0.5f );
}

void ControlStickSprite::onMoved( cocos2d::CCPoint location )
{
    this->setPosition( location );
}

void ControlStickSprite::onEnded( cocos2d::CCPoint location )
{
}

请帮我使这个工作! 我对虚拟方法的使用不太熟悉,所以也许我错过了一些东西。 我还是C ++和cocos2dx编程的新手。

提前致谢!

编辑:感谢@musikov修复了第一部分! 我更新了上面的代码以反映所做的更改。 我用std :: vector <TouchableSprite *>替换了CCArray,从而消除了从CCObject *进行强制转换的需要。

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

我的ControlStickSprite :: 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;
}

我唯一能想到的是createEntity()方法创建了一个TouchableSprite *,但是返回了CCNode *,然后我将其转换为ControlStickSprite *。 我又做错了吗? :)

感谢你的帮助!

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

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;
}

添加了控制杆实施

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;
}

EntityManager:

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

如果决定使用此解决方案,请记住在ControlStickSprite :: create()之后调用EntityManager :: addEntity(parent,entity)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM