Below is my HelloWorld.h class:
class HelloWorld : public cocos2d::CCLayer
{
public:
HelloWorld();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
b2World* world;
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
virtual void draw();
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);
};
And in my HelloWorld.cpp class i have initialized My init method
bool HelloWorld::init(){
setTouchEnabled( true );
setAccelerometerEnabled( true );
scheduleUpdate();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
return true;
}
This code is working for me now! :)
The Targeted Delegate is for single touch events. Change your events to something like this:
virtual bool ccTouchBegan (CCTouch *pTouch, CCEvent *pEvent)
You can read up more about targeted and standard touch delegates on the iPhone side of the Cocos2D documentation at this Link
Writing the delegate in my initialisation method as per below solved the problem
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 1);
If you want to disable multiTouch capability you can use :
virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){}
virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){}
And so you need to:
bool init()
{
...
setTouchEnabled(true);
this->setTouchMode(ccTouchesMode::kCCTouchesOneByOne); // Important
}
If you omit last line you will need to override these (multiTouch mode):
void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
Related
Now I create a totally new SDI project
the view provides a function: GetDocument(), it helps me to get the current document's data
However, When I call the GetDocument() function,VC tells me some error occurs:Debug Assertion Failed
the following is my setting
class CHorse_programView : public CView
{
protected: // create from serialization only
CHorse_programView();
DECLARE_DYNCREATE(CHorse_programView)
// Attributes
public:
CHorse_programDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHorse_programView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CHorse_programView();
CHorse_programDoc * GetDoc()
{
CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
return (CHorse_programDoc *) pFrame->GetActiveDocument();
}
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CHorse_programView)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
and I want to call GetDocument() in this function
CHorse_programView::CHorse_programView()
{
GetDocument();
}
what's wrong
The CDocument and CView are not connected yet at CView construction time. You can move your code to OnInitialUpdate in the view to get full capability.
In the view's constructor, it hasn't been assigned to a document yet - that comes later.
I am working on my Cocos2d-x cpp project. I have successfully add touch event to move the background in Layer. Now I want to add CCMenuItemLabel to the Layer, but I find that CCMenuItemLabel doesn't work when I Touch it. How can I solve it?
I have add these functions in my Layer:
virtual void ccTouchesBegan (CCSet *pTouches, CCEvent *pEvent);
virtual void ccTouchesMoved (CCSet *pTouches, CCEvent *pEvent);
virtual void ccTouchesEnded (CCSet *pTouches, CCEvent *pEvent);
In MyLayer::init() function:
this->setTouchEnabled(true);
CCLabelTTF* test = CCLabelTTF::create("tesetdd","Arial",40);
CCMenuItemLabel* menuLabel = CCMenuItemLabel::create(test,this,menu_selector(GameWall::menuCall));
menuLabel->setPosition(ccp(winSize.width/2,winSize.height/2));
this->addChild(menuLabel,1);
Update:I have put CCMenuItemLabel into the CCMenu. But it still doesn't work.
CCLabelTTF* test = CCLabelTTF::create("tesetdd","Arial",40);
CCMenuItemLabel* menuLabel = CCMenuItemLabel::create(test,this,menu_selector(GameWall::menuCall));
menuLabel->setPosition(ccp(winSize.width/2,winSize.height/2));
CCMenu* menu = CCMenu::create(menuLabel,NULL);
menu->setPosition(CCPointZero);
this->addChild(menu,1);
Don't add CCMenuItems directly to layer. Add them to a CCMenu and add that CCMenu to your layer.
First, thanks for #Kreiri.
I have change my Touch Event function to
virtual bool ccTouchBegan (CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved (CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded (CCTouch *pTouch, CCEvent *pEvent);
and I add two more functions
virtual void onEnter();
virtual void registerWithTouchDispatcher();
and I move initial code to onEnter
CCLabelTTF* test = CCLabelTTF::create("tesetdd","Arial",40);
CCMenuItemLabel* menuLabel = CCMenuItemLabel::create(test,this,menu_selector(GameWall::menuCall));
menuLabel->setPosition(ccp(winSize.width/2,winSize.height/2));
CCMenu* menu = CCMenu::create(menuLabel,NULL);
menu->setPosition(CCPointZero);
this->addChild(menu,1);
add three more code to onEnter():
this->setTouchEnabled(true);
registerWithTouchDispatcher();
menu->registerWithTouchDispatcher();
While registerWithTouchDispatcher() :
void GameWall::registerWithTouchDispatcher(){
//registe the single point touch,and take over all touch event
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,kCCMenuHandlerPriority,true);
}
Finally, don't forget to romoveDelegate() in onExit():
void GameWall::onExit(){
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
Let me explain, check the document registerWithTouchDispatcher() says If isTouchEnabled, this method is called onEnter. and Override it to change the way CCLayer receives touch events. And same with CCMenu.
I have a Balloon class (see this) that inherits from CCSprite. I have given it properties like balloonSpeed and balloonStrength. I seem to be having problems in it, though.
What I want to do is that when I make an instance of the Balloon class, I want it to do the following:
Give it a texture (a PNG file of a balloon).
Set properties like balloonSpeed and balloonStrength.
Add actions to make it move and accept touch input.
When the object is touched, I want to:
Count if # of taps = balloonStrength. if so, destroy Balloon.
I have done a simpler version of this where a Balloon object is destroyed when it is touched. I want to apply OOP and custom classes here but I can't seem to get the right way of doing it.
Thanks in advance.
then the h file should looks like below:
#include "cocos2d.h"
using namespace cocos2d;
class Balloon : public cocos2d::CCSprite, public CCTargetedTouchDelegate {
public:
float balloonSpeed;
int balloonStrength;
int numberOfTaps;
virtual void onEnter();
virtual void onExit();
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
};
and in your touch method:
bool Balloon::ccTouchBegan(CCTouch* touch, CCEvent* event){
CCPoint touchLocation = this->getParent()->convertTouchToNodeSpace(touch);
if (CCRect::CCRectContainsPoint(this->boundingBox(), touchLocation)) {
this->numberOfTaps++;
if(this->balloonStrength == this->numberOfTaps){
this->removeFromParentAndCleanup(true);
}
}
return true;
}
you can use it after you add the blueBalloon as a child of a layer or node as below:
blueBalloon->balloonSpeed = 2.0f;
blueBalloon->numberOfTaps = 0;
blueBalloon->balloonStrength = 5;
I'm new to the cocos2d(-x) world.
I'd like to detect a touch to a sprite, and tutorials/examples seem to suggest using layer to detect touch and find the approapriate sprite with bounding box.
Is subclassing sprite to allow touch detection generally a bad idea?
Note: This answer might be outdated. I answered this at 2012.
It is not a bad idea. Here is how I do it:
header file:
#include "cocos2d.h"
using namespace cocos2d;
class TouchableSprite : public cocos2d::CCSprite, public CCTargetedTouchDelegate {
public:
virtual void onEnter();
virtual void onExit();
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
};
cpp file:
#include "TouchableSprite.h"
void TouchableSprite::onEnter(){
// before 2.0:
// CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);
// since 2.0:
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
CCSprite::onEnter();
}
void TouchableSprite::onExit(){
// before 2.0:
// CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
// since 2.0:
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCSprite::onExit();
}
bool TouchableSprite::ccTouchBegan(CCTouch* touch, CCEvent* event){
//do whatever you want here
return true;
}
void TouchableSprite::ccTouchMoved(CCTouch* touch, CCEvent* event){
//do what you want
}
void TouchableSprite::ccTouchEnded(CCTouch* touch, CCEvent* event){
//do your job here
}
In cocos2d-x 3.0 alpha you can try this:
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [&](Touch* touch, Event* event){
if (this->getBoundingBox().containsPoint(this->convertTouchToNodeSpace(touch))) {
return true;
}
return false;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
it is better and much more clear to handle touches in one place. but i think, no one can bar you to do this
You do not need to subclass sprites to detect touch.
Here, Follow this LINK its a nice place to get started with Cocos2d
I make a simple window with wxwidgets. How can I change the border?
Also how can I call the destroy function(OnClose) with the right arrow button press?
#include <wx/wx.h>
class _Frame: public wxFrame
{
public:
_Frame(wxFrame *frame, const wxString& title);
private:
void OnClose(wxCloseEvent& event);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(_Frame, wxFrame)
END_EVENT_TABLE()
_Frame::_Frame(wxFrame *frame, const wxString& title)
: wxFrame(frame, -1, title)
{}
void _Frame::OnClose(wxCloseEvent &event)
{
Destroy();
}
class _App : public wxApp
{
public:
virtual bool OnInit();
};
IMPLEMENT_APP(_App);
bool _App::OnInit()
{
_Frame* frame = new _Frame(0L, _("wxWidgets Application Template"));
frame->Show();
return true;
}
To close the window on right-arrow you need to trap EVT_CHAR or EVT_KEY_DOWN like so:
header file:
void OnChar(wxKeyEvent& event);
source file:
void _Frame::OnChar(wxKeyEvent& event)
{
if (event.GetKeyCode() == WXK_RIGHT)
{
wxCommandEvent close(wxEVT_CLOSE_WINDOW);
AddPendingEvent(close);
}
event.Skip();
}
BEGIN_EVENT_TABLE(_Frame, wxFrame)
EVT_CHAR(_Frame::OnChar)
END_EVENT_TABLE()
Changing the border (by setting a different wxBORDER_XXX style) doesn't work for all windows/under all platforms after the initial window creation so you'd better recreate the window if you really, really need to do this.