Thursday, May 7, 2015

Cocos2dx: Replacing a Scene

In HelloWorld.h:

class HelloWorld : public cocos2d::Layer
{
public:
    
    static cocos2d::Scene* createScene();

    virtual bool init();
    
    CREATE_FUNC(HelloWorld);
    

    void Play(Ref *pSender);   

};


In HelloWorld.cpp:

#include "NewScene.h"
bool HelloWorld::init()
{

    if ( !Layer::init() )
    {
        return false;
    }
    
    
    auto menu_item_1 = MenuItemFont::create("Play", CC_CALLBACK_1(HelloWorld::Play, this));
    
    
    auto *menu = Menu::create(menu_item_1,NULL);
    menu->alignItemsVerticallyWithPadding(40);
    this->addChild(menu);
    
    return true;
}

void HelloWorld::Play(cocos2d::Ref *pSender){
    CCLOG("Play");
    auto scene = NewScene::createScene();
    Director::getInstance()->replaceScene(scene);
}


In NewScene.h:

class NewScene : public cocos2d::Layer
{
public:

    static cocos2d::Scene* createScene();

    virtual bool init();
    
    CREATE_FUNC(NewScene);
    
    
    void GoBack(Ref *pSender);
   
};


In NewScene.cpp:

#include "HelloWorldScene.h"
bool NewScene::init()
{
    
    if ( !Layer::init() )
    {
        return false;
    }
    


    auto menu_item_1 = MenuItemFont::create("Go Back", CC_CALLBACK_1(NewScene::GoBack, this));
   
    
    auto *menu = Menu::create(menu_item_1,NULL);
    menu->alignItemsVerticallyWithPadding(40);
    this->addChild(menu);
   
    
    return true;
}

void NewScene::GoBack(cocos2d::Ref *pSender){
    auto scene = HelloWorld::createScene();
    Director::getInstance()->replaceScene(scene);
}

Cocos2dx: Pushing and Popping Scenes

In HelloWorld.h:

//The default scene
class HelloWorld : public cocos2d::Layer
{
public:
    
    static cocos2d::Scene* createScene();
   
    virtual bool init();
    

    CREATE_FUNC(HelloWorld);
     
    //Play button will push  NewScene to the stack
    void Play(Ref *pSender);
   

};


In HelloWorld.cpp:
#include "NewScene.h"

bool HelloWorld::init()
{
   
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto menu_item_1 = MenuItemFont::create("Play"
                     CC_CALLBACK_1(HelloWorld::Play, this));
    
    auto *menu = Menu::create(menu_item_1,NULL);
    menu->alignItemsVerticallyWithPadding(40);
    this->addChild(menu);
    
    return true;
}

void HelloWorld::Play(cocos2d::Ref *pSender){
    CCLOG("Play");
    auto scene = NewScene::createScene();
    Director::getInstance()->pushScene(scene);
}


In NewScene.h:

//The scene that is pushed onto the stack
class NewScene : public cocos2d::Layer
{
public:
    
    static cocos2d::Scene* createScene();
    virtual bool init();

    CREATE_FUNC(NewScene);
 
   //GoBack button will pop this scene from the top of the stack
   void GoBack(Ref *pSender);
   
};

In NewScene.cpp:

bool NewScene::init()
{
   
    if ( !Layer::init() )
    {
        return false;
    }
    

    auto menu_item_1 = MenuItemFont::create("Go Back", CC_CALLBACK_1(NewScene::GoBack, this));
   
    auto *menu = Menu::create(menu_item_1,NULL);
    menu->alignItemsVerticallyWithPadding(40);
    this->addChild(menu);
   
    
    return true;
}

void NewScene::GoBack(cocos2d::Ref *pSender){
    Director::getInstance()->popScene();
}

Wednesday, May 6, 2015

Cocos2dx: Menus

In .h:

class HelloWorld : public cocos2d::Layer
{
public:
   
    static cocos2d::Scene* createScene();
    virtual bool init();
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);


    // The menu items:
    void Play(Ref *pSender);
    void Highscores(Ref *pSender);
    void Settings(Ref* pSender);
    void ImageButton(Ref *pSender);
   

};


Implementation:

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    auto menu_item_1 = MenuItemFont::create("Play",
                       CC_CALLBACK_1(HelloWorld::Play, this));
    auto menu_item_2 = MenuItemFont::create("Highscores",
                       CC_CALLBACK_1(HelloWorld::Highscores, this));
    auto menu_item_3 = MenuItemFont::create("Settings",
                       CC_CALLBACK_1(HelloWorld::Settings, this));
    auto menu_item_4 = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",                    
                       CC_CALLBACK_1(HelloWorld::ImageButton, this));
    
  
    auto *menu = Menu::create(menu_item_1,menu_item_2,menu_item_3,menu_item_4,NULL);
    menu->alignItemsVerticallyWithPadding(visibleSize.height/4);
    this->addChild(menu);
    
    return true;
}

void HelloWorld::Play(cocos2d::Ref *pSender){
    CCLOG("Play");
}

void HelloWorld::Highscores(cocos2d::Ref *pSender){
    CCLOG("Highscores");
}

void HelloWorld::Settings(cocos2d::Ref *pSender){
    CCLOG("Settings");
}

void HelloWorld::ImageButton(cocos2d::Ref *pSender){
    CCLOG("IMAGE BUTTON");
}


Alternatively, you can do this instead of menu->alignItemsVerticallyWithPadding(40) :


    menu_item_1->setPosition(Point(visibleSize.width/2,(visibleSize.height/5)*4));
    menu_item_2->setPosition(Point(visibleSize.width/2,(visibleSize.height/5)*3));
    menu_item_3->setPosition(Point(visibleSize.width/2,(visibleSize.height/5)*2));
    menu_item_4->setPosition(Point(visibleSize.width/2,(visibleSize.height/5)*1));

Cocos2dx: Detecting Multiple Touches


In .h file:

class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    virtual bool init();
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
    
    void onTouchesBegan(const std::vector<cocos2d::Touch*> &touches, cocos2d::Event *event);
    void onTouchesMoved(const std::vector<cocos2d::Touch*> &touches, cocos2d::Event *event);
    void onTouchesEnded(const std::vector<cocos2d::Touch*> &touches, cocos2d::Event *event);

};


Implementation:

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    auto listener = EventListenerTouchAllAtOnce::create();

    //Using CC_CALLBACK_2 because onTouchesXXX receives 2 params
    listener->onTouchesBegan = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);
    listener->onTouchesMoved = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);
    listener->onTouchesEnded = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    return true;
}

void HelloWorld::onTouchesBegan(const std::vector<cocos2d::Touch*> &touches, 
                                cocos2d::Event* event){
    CCLOG("MULTI TOUCH BEGAN");
}

void HelloWorld::onTouchesMoved(const std::vector<cocos2d::Touch*> &touches, 
                                cocos2d::Event* event){
    CCLOG("MULTI TOUCHES HAVE MOVED");
}

void HelloWorld::onTouchesEnded(const std::vector<cocos2d::Touch*> &touches, 
                                cocos2d::Event* event){
    CCLOG("MULTI TOUCHES HAVE ENDED");

}

Cocos2dx: Detecting Single Touches

Create the following in the .h file:

class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    virtual bool init();
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
    
    bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event);
    void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event);
    void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event);

};


Create the following in the implementation file:

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
   
    if ( !Layer::init() )
    {
        return false;
    }
    
    
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    return true;
}

bool HelloWorld::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event){
    CCLOG("onTouchBegan x = %f, y = %f", touch->getLocation().x,
                                         touch->getLocation().y);
    return true;
}

void HelloWorld::onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event){
    CCLOG("onTouchMoved x = %f, y = %f", touch->getLocation().x,
                                         touch->getLocation().y);
   
}

void HelloWorld::onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event){
    CCLOG("onTouchEnded x = %f, y = %f", touch->getLocation().x,
                                         touch->getLocation().y);
    
}


Alternatively, you can do this:

Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, this);

instead of:

_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

Cocos2dx: Playing Background Music



bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    
    const char* music = "audio/game_music.mp3";
    CocosDenshion::SimpleAudioEngine::getInstance()->preloadBackgroundMusic(music);
    CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic(music);
    CocosDenshion::SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(0.1);
    this->schedule(schedule_selector(HelloWorld::StopSound), 3);
    this->schedule(schedule_selector(HelloWorld::ResumeSound), 10);
    return true;
}

void HelloWorld::ResumeSound(float dt){
    CocosDenshion::SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}

void HelloWorld::StopSound(float dt){
    
    CocosDenshion::SimpleAudioEngine::getInstance()->pauseBackgroundMusic();

}

Cocos2dx: Pausing a sound after finite seconds

This is one way to play loop a sound and then pausing it after 15 secs. See green comments for explanation.

#include <SimpleAudioEngine.h>

bool HelloWorld::init()
{
   
    if ( !Layer::init() )
    {
        return false;
    }
    
    
   
    const char* sound = "audio/CanBomb.mp3";
    
    //create the sound and play loop it
    auto audio=CocosDenshion::SimpleAudioEngine::getInstance();
    audio->preloadEffect(sound);
    int soundId = audio->playEffect(sound,true);//true: looping sound
  
    //create the action to delay 15 secs
    auto actionDelay = DelayTime::create(15);
    
    //create the action to pause sound
    auto callbackAudio = CallFunc::create([](){
        CocosDenshion::SimpleAudioEngine::getInstance()->pauseEffect(soundId);
    });

    //create sequence putting in delay and pause action created above
    auto actionSequence = Sequence::create(actionDelay,callbackAudio, NULL);

    //run the action
    this->runAction(actionSequence);
    
    return true;
}


This is another way to do it:

#include <SimpleAudioEngine.h>

bool HelloWorld::init()
{
   
    if ( !Layer::init() )
    {
        return false;
    }
    
    
   
    const char* sound = "audio/CanBomb.mp3";
    
    //create the sound and play loop it
    auto audio=CocosDenshion::SimpleAudioEngine::getInstance();
    audio->preloadEffect(sound);
    int soundId = audio->playEffect(sound,true);//true: looping sound

    this->schedule(schedule_selector(HelloWorld::StopSound), 15);
    
    return true;
}

//Declare it in header file as well:
void HelloWorld::StopSound(float dt){
    
    CocosDenshion::SimpleAudioEngine::getInstance()->pauseEffect(soundId);

}

-----------------------------------------------------------------------

//The header file
class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
    
   
    
    void StopSound(float dt);

};