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