[英]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.