• 能不能播放ogg, 主要取决于你用的音频库是否有ogg的解码器。 ogg 是谷歌的格式,所以几乎所有的android手机都支持这种格式, cocos2d-x 用windows 默认播放器,所以要装解码器。网上搜索一下 K-Lite Mega Codec ...

    能不能播放ogg, 主要取决于你用的音频库是否有ogg的解码器。

    ogg 是谷歌的格式,所以几乎所有的android手机都支持这种格式, cocos2d-x 用windows 默认播放器,所以要装解码器。网上搜索一下 K-Lite Mega Codec Pack。 下载安装后。打开windows Medio Player 是否能播放ogg 音频文件。 如果没问题,接下来还需要改cocos2dx 音频相关的代码。、、

    找打micPlayer.cpp.修改open()函数相关的代码,cpp文件位于 cocos2d/cocos/audio/win32 目录


    void MciPlayer::Open(const char* pFileName, UINT uId)
    {
    //     WCHAR * pBuf = NULL;
        do 
        {
            BREAK_IF(! pFileName || ! _wnd);
            int nLen = (int)strlen(pFileName);
            BREAK_IF(! nLen);
    //         pBuf = new WCHAR[nLen + 1];
    //         BREAK_IF(! pBuf);
    //         MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, pBuf, nLen + 1);
    
            strExt = cocos2d::FileUtils::getInstance()->getFileExtension(pFileName);
    
            Close();
    
            MCI_OPEN_PARMS mciOpen = {0};
            MCIERROR mciError;
    		//mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID; //这是原来的代码
    		mciOpen.lpstrDeviceType = TEXT("MPEGVideo");	//修改后的代码
    		WCHAR* fileNameWideChar = new WCHAR[nLen + 1];
    		BREAK_IF(! fileNameWideChar);
    		MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, fileNameWideChar, nLen + 1);
            mciOpen.lpstrElementName = fileNameWideChar;
    
           // mciError = mciSendCommand(0,MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen)); //原来的代码
    		mciError = mciSendCommandW(0, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_OPEN_TYPE, reinterpret_cast<DWORD_PTR>(&mciOpen)); //修改后的代码
    		CC_SAFE_DELETE_ARRAY(mciOpen.lpstrElementName);
            BREAK_IF(mciError);
    
            _dev = mciOpen.wDeviceID;
            _soundID = uId;
            _playing = false;
        } while (0);
    }

    上面的代码修改2处,一处是

    micOpen.lpstrDeviceType = TEXT("MEPGVideo");

    另外一处是

    micError = mciSendCommandW(0,MCI_OPEN,MCI_OPEN_ELEMENT|MCI_OPEN_TYPE,reinterpret_cast<DWORD_PTR>(&mciOpen))

    修改完之后,重新编译libcocos2d 库就可以播放了

    展开全文
  • 本文原创:转载请注明地址:一、coco2dx-3.0环境搭建这个网上很多参考教程也属于基础部分我就不再敷述,这里给大家提供csdn博客上的大家可以参考一下,我大概看了一下比较全面了;参考地址:...

    本文原创:转载请注明地址:http://blog.csdn.net/zp522123428/article/details/29357851

    一、coco2dx-3.0环境搭建


    这个网上很多参考教程也属于基础部分我就不再敷述,这里给大家提供csdn博客上的大家可以参考一下,我大概看了一下比较全面了;

    参考地址:http://blog.csdn.net/aa4790139/article/details/8086635


    二、coco2dx-3.0下创建项目

    1、进入coco2dx-3.0的目录下,检查环境。--》在doc下执行setup.py



    如果环境正确会显示如下内容:



    2、创建工程

    在doc下执行如下语句即可:

    cocos new FlappyBird -p com.zz.hello -l cpp -d f:\cocos2d-x-3.0\project

    FlappyBird为工程名称

    com.zz.hello为包路径

    f:\cocos2d-x-3.0\project为创建工程路径(一定是在3.0文件夹下,不然会有莫名其妙的错误哦)


    3、执行完成之后会在对应路径下有相应的工程工程目录大概入下:



    三、编码

    新建一个Scene类

    1. #include "cocos2d.h"  
    2. #include "Obstacle.h"  
    3.   
    4. class FlyBirdGame :public cocos2d::Layer  
    5. {  
    6. public:  
    7.     static cocos2d::Scene* createScene();  
    8.     virtual bool init();  
    9.     CREATE_FUNC(FlyBirdGame);  
    10.     void initUI();  
    11.     void gameStart(Object* pSender);   
    12.     void update(float time);  
    13.     Obstacle* obstacle;  
    14. };  

    1. #include "cocos2d.h"  
    2. #include "FlyBirdGame.h"  
    3. #include "resource.h";   
    4.   
    5. USING_NS_CC;  
    6.   
    7. Scene* FlyBirdGame::createScene()  
    8. {  
    9.     auto scene = Scene::create();  
    10.     auto layer = FlyBirdGame::create();  
    11.     scene->addChild(layer);  
    12.     return scene;  
    13. }  
    14.   
    15. bool FlyBirdGame::init()  
    16. {  
    17.     if (!Layer::init())  
    18.     {  
    19.         return false;  
    20.     }  
    21.     initUI();  
    22.     return true;  
    23. }  

    initUI里是一些UI初始化方法:

    1.        // win size  
    2. auto winSize = Director::getInstance()->getVisibleSize();  
    3.   
    4. // game bg  
    5. auto bg = Sprite::create(bird_bg);  
    6. bg->setPosition(winSize.width / 2, winSize.height / 2);  
    7. bg->setScale(winSize.width / bg->getContentSize().width, winSize.height / bg->getContentSize().height);  
    8. this->addChild(bg);  
    9.   
    10. // start btn  
    11. auto startBtn = MenuItemImage::create(bird_start_btn, bird_start_btn_pressed, CC_CALLBACK_1(FlyBirdGame::gameStart, this));  
    12. auto menu = Menu::create(startBtn, NULL);  
    13. menu->setTag(100);  
    14. this->addChild(menu);  
    15.   
    16. // hero  
    17. auto hero = Sprite::create(bird_hero);  
    18. hero->setPosition(winSize.width / 5, winSize.height*0.8);  
    19. hero->setVisible(false);  
    20. hero->setTag(200);  
    21. this->addChild(hero);  

    开始游戏按钮绑定的gameStart方法:

    1. void FlyBirdGame::gameStart(Object* pSender)  
    2. {  
    3.     auto btn = this->getChildByTag(100);  
    4.     btn->setVisible(false);  
    5.     auto hero = this->getChildByTag(200);   
    6.     Size win = Director::getInstance()->getWinSize();  
    7.     obstacle->gameStart = true;  
    8. }  

    隐藏开始按钮,显示小鸟,水管开始移动

    还有更新方法:

    1. scheduleUpdate();  
    2. void FlyBirdGame::update(float time)  
    3. {  
    4.     obstacle->update();  
    5. }  

    =======================================

    水管类:Obstacle.cpp

    update方法里判断游戏是游戏是否开始


    1. void Obstacle::update()  
    2. {  
    3.     if (gameStart == false)  
    4.         return;  
    5.     addCount++;  
    6.     if (addCount == 60)  
    7.     {  
    8.         addOne(0);  
    9.         addCount = 0;  
    10.     }  
    11.     for (int i = obstacleList->count() - 1; i >= 0; i--)  
    12.     {  
    13.         auto s = (Sprite*)obstacleList->getObjectAtIndex(i);  
    14.         s->setPositionX(s->getPositionX() - 3);  
    15.         if (s->getPositionX() < -s->getContentSize().width / 2)  
    16.         {  
    17.             obstacleList->removeObjectAtIndex(i);  
    18.             this->removeChild(s);  
    19.         }  
    20.     }  
    21. }  
    水管类的更新方法里,每60帧(1秒)添加一对水管

    并且遍历水管列表

    出边界的化销毁

    接下来是addOne方法:添加水管方法:

    1. void Obstacle::addOne(int offsetX)  
    2. {  
    3.     Size size = Director::getInstance()->getWinSize();  
    4.     auto sprite = Sprite::create(bird_obstacle_up);  
    5.     Size spriteSize = sprite->getContentSize();  
    6.     obstacleList->addObject(sprite);  
    7.     this->addChild(sprite);  
    8.     auto sprite2 = Sprite::create(bird_obstacle_down);  
    9.     Size spriteSize2 = sprite->getContentSize();  
    10.     obstacleList->addObject(sprite2);  
    11.     this->addChild(sprite2);  
    12.     // set positon  
    13.     int maxUpY = size.height + spriteSize.height / 4;  
    14.     int minUpY = size.height - spriteSize.height / 4;  
    15.     int y1 = CCRANDOM_0_1()*(maxUpY - minUpY) + minUpY;  
    16.     int maxDownY = spriteSize.height / 4;  
    17.     int minDownY = -spriteSize.height / 4;  
    18.     int y2 = CCRANDOM_0_1()*(maxDownY - minDownY) + minDownY;  
    19.     if (y1 - y2 - spriteSize.height < 160)  
    20.     {  
    21.         y2 = y1 - spriteSize.height - 160;  
    22.     }  
    23.     sprite->setPosition(ccp(size.width + spriteSize.width / 2 + offsetX, y1));  
    24.     sprite2->setPosition(ccp(size.width + spriteSize2.width / 2 + offsetX, y2));  
    25. }  
    这段代码比较凌乱,就是找到水管上下位置的范围

    然后随机一下,并且保证上下连个水管有个最小的距离

    效果如下:



    =============================

    此时的游戏还没触摸和碰撞逻辑

    马上添加:(刚才抽空玩了把魔方:五阶的我只能搞定一个面,虽然有官方规律但是那样好像比的是记忆力)

    听说cocos2dx3.0的事件监听方式改变了

    先在FlyBirdGame.h里声明俩方法:

    1. void onTouchesEnded(const vector<Touch*>& touches, Event* event);  
    2. void onTouchesBegan(const vector<Touch*>& touches, Event* event);  

    在cpp文件的初始化里绑定事件:

    1. // touch  
    2. auto dispatcher = Director::getInstance()->getEventDispatcher();  
    3. auto listener = EventListenerTouchAllAtOnce::create();  
    4. listener->onTouchesEnded = CC_CALLBACK_2(FlyBirdGame::onTouchesEnded, this);  
    5. listener->onTouchesBegan = CC_CALLBACK_2(FlyBirdGame::onTouchesBegan, this);  
    6. dispatcher->addEventListenerWithSceneGraphPriority(listener, this);  

    在两个事件方法里改变标记位,在小鸟的update方法里根据这个标记位来改变高度


    =============================

    碰撞检测:

    记得cocos2dx3.0以前都是自己写一个根据CCSprite获取CCRect的方法

    现在直接用 Sprite的getBoundingBox()方法

    不过如果有特殊需求还得自己写,比如想扩大或缩小碰撞区域

    在FlyBirdGame.cpp文件里

    update算主逻辑方法:

    1. void FlyBirdGame::update(float time)  
    2. {  
    3.     auto winSize = Director::getInstance()->getVisibleSize();  
    4.     auto hero = this->getChildByTag(TAG_HERO);  
    5.     Rect rHero = ((Sprite*)hero)->getBoundingBox();  
    6.   
    7.     switch (GAME_STATUS)  
    8.     {  
    9.     case GAME_STATUS_PLAYING:  
    10.         obstacle->update();  
    11.         // update bird positionY  
    12.         if (isFlying&&hero->getPositionY() < winSize.height)  
    13.         {  
    14.             hero->setPositionY(hero->getPositionY() + v);  
    15.         }  
    16.         else if (hero->getPositionY()>0)  
    17.         {  
    18.             hero->setPositionY(hero->getPositionY() - v);  
    19.         }  
    20.         //check collision  
    21.         for (int i = 0; i < obstacle->obstacleList->count(); i++)  
    22.         {  
    23.             Sprite* obstacleRect = (Sprite*)obstacle->obstacleList->getObjectAtIndex(i);  
    24.             bool pia = rHero.intersectsRect(obstacleRect->getBoundingBox());  
    25.             if (pia == true)  
    26.             {  
    27.                 GAME_STATUS = GAME_STATUS_GAME_OVER;  
    28.                 break;  
    29.             }  
    30.         }  
    31.         break;  
    32.     case GAME_STATUS_GAME_OVER:  
    33.         CCLog("over");  
    34.         this->getChildByTag(TAG_OVER)->setVisible(true);  
    35.         break;  
    36.     case GAME_STATUS_RESTART:  
    37.         //reset game  
    38. <span style="white-space: pre;">        </span>obstacle->removeAllChildren();  
    39.         obstacle->obstacleList->removeAllObjects();  
    40.         // reset hero  
    41.         hero->setPosition(winSize.width / 5, winSize.height*0.8);  
    42.         // show btn  
    43.         auto btn = this->getChildByTag(TAG_START_BTN);  
    44.         btn->setVisible(true);  
    45.         // show logo  
    46.         auto logo = this->getChildByTag(TAG_LOGO);  
    47.         logo->setVisible(true);  
    48.         break;  
    49.     }  
    50. }  

    根据游戏状态处理。

    碰撞检测方法:intersectsRect

    bool pia = rHero.intersectsRect(obstacleRect->getBoundingBox());
    if (pia == true)
    {
    GAME_STATUS = GAME_STATUS_GAME_OVER;
    break;
    }


    游戏状态定义在 resource.h 文件里

    1. static const int GAME_STATUS_START = 10;  
    2. static const int GAME_STATUS_PLAYING = 20;  
    3. static const int GAME_STATUS_GAME_OVER = 30;  
    4. static const int GAME_STATUS_RESTART = 40;  


    整个游戏流程已经通了:开始,游戏,结束,重新开始

    接下来可以优化很多很多东西

    ===================================================

    真搞不懂为什么和弦要那么别扭的按法

    相较之下

    还是代码简单

    继续优化

    添加小鸟动画:


    添加到resource.h 文件中等待使用

    也可以直接在cpp文件中用不过骨头习惯了资源统一管理

    1. Animation* an = Animation::create();  
    2. an->addSpriteFrameWithFileName(bird_hero);  
    3. an->addSpriteFrameWithFileName(bird_hero2);  
    4. an->addSpriteFrameWithFileName(bird_hero3);  
    5. an->setDelayPerUnit(0.5f / 3.0f);  
    6. an->setLoops(-1);  
    7. Animate* anim = Animate::create(an);  
    8. hero->runAction(anim);  

    F5运行看效果,确实生动一点了

    =========================================================

    分辨率问题:

    在AppDelegate.cpp入口方法中加入:

    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionExactFit);

    其中320,480是游戏設計時的分辨率。

    后面参数介绍如下“:

    1. //kResolutionExactFit x,y都拉伸,使铺满屏幕  
    2. //kResolutionNoBorder 一个方向铺满屏幕,另外一个方向超出屏幕  
    3. //kResolutionShowAll  854 * 480 的设计区域全部可见,但是可能留有黑边(如在960 * 640的屏幕上)  
    =============================================================

    分数的显示:

    之前的几个demo都是使用本办法显示的特殊数字:一排图片然后根据每位上的数字决定显示哪个图片

    本来打算自己封装个方法,再一看,有更简单的:

    从自带的demo里找点合适的字体资源,拷贝到fonts文件夹下

    记住把fnt和对应的png都拷贝过来

    然后

    1. auto label1 = LabelBMFont::create("123456""fonts/futura-48.fnt");  
    2. addChild(label1);  
    3. label1->setPosition(Point(win.width / 2, win.height / 2));  


    ================================================

    分数显示ok了,下面看下分数逻辑

    当小鸟的坐标等于柱子的坐标时,score+1(因为是上下俩柱子对象,所以除以2显示)

    别忘记判断时要让小鸟飞过柱子,而不是跟柱子纵轴对齐

    相关代码在检测碰撞时添加:

    1. //check collision  
    2. for (int i = 0; i < obstacle->obstacleList->count(); i++)  
    3. {  
    4.     Sprite* obstacleSprite = (Sprite*)obstacle->obstacleList->getObjectAtIndex(i);  
    5.     bool pia = rHero.intersectsRect(obstacleSprite->getBoundingBox());  
    6.     if (pia == true)  
    7.     {  
    8.         GAME_STATUS = GAME_STATUS_GAME_OVER;  
    9.         break;  
    10.     }  
    11.     int oPosX = obstacleSprite->getPositionX() + obstacleSprite->getContentSize().width / 2;  
    12.     int heroX = hero->getPositionX() - hero->getContentSize().width;  
    13.     if (oPosX == heroX)  
    14.     {  
    15.         score++;  
    16.         auto scoreSprite = (LabelBMFont*)this->getChildByTag(TAG_SCORE);  
    17.         String* s = String::createWithFormat("%d", score / 2);  
    18.         scoreSprite->setString(s->getCString());  
    19.     }  
    20. }  


    ======================================================

    增加下游戏难度

    之所以死不了是因为小鸟的速度改变的很均匀

    因为触摸事件只改变速度 不改变加速度

    1. // update bird positionY  
    2. if (hero->getPositionY() > 0 && hero->getPositionY() < winSize.height)  
    3. {  
    4.     velocity -= gravity;  
    5.     hero->setPositionY(hero->getPositionY() + velocity);  
    6. }  
    7. //if (isFlying&&hero->getPositionY() < winSize.height)  
    8. //{  
    9. //  hero->setPositionY(hero->getPositionY() + velocity);  
    10. //}  
    11. //else if (hero->getPositionY()>0)  
    12. //{  
    13. //  hero->setPositionY(hero->getPositionY() - velocity);  
    14. //}  
    15. //check collision  

    将之前的速度改变方式修改一下,每次点击给一个向上的速度,然后重力向下,这样就类似原游戏的跳跃感了

    至于数值可以继续微调来加大游戏难度


    ====================================================

    如果要在捕捉返回键可在init方法内加

    //注册捕捉监听
    auto listenerkeyPad = EventListenerKeyboard::create();
    listenerkeyPad->onKeyReleased = CC_CALLBACK_2(FlyBirdGame::onKeyReleased, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerkeyPad, this);


    然后定义一个返回键响应方法(我这里是做的直接退出的响应,但让你可以改成别的响应,如提示退出等等)

    //捕捉监听
    void FlyBirdGame::onKeyReleased(EventKeyboard::KeyCode keycode, cocos2d::Event *event)
    {
    if (keycode == EventKeyboard::KeyCode::KEY_BACKSPACE)  //返回
    {
    CCLOG("back up");
    int iManSceneTag = CCDirector::sharedDirector()->getRunningScene()->getTag();//如果是主场景,则退出;
    CCDirector::sharedDirector()->end();
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
    #endif
    }
    else if (keycode == EventKeyboard::KeyCode::KEY_MENU)
    {


    }
    }


    ===========================================上面的主场景中没有加入声音=======下面把声音部分加进去============

    没声音确实有点尴尬:


    3.0加入背景音乐没多大变化

    #include "SimpleAudioEngine.h"
    //添加命名空间;
    using namespace cocos2d::extension;



          //音效----ogg的在win32下是没效果的在真机上就有了。
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic("music/bg.ogg");
    SimpleAudioEngine::sharedEngine()->playBackgroundMusic("music/bg.ogg", true);//播放背景音乐
    //    设置默认音量 、、这个可以不设置有默认值的
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(1);
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(1);
    //              暂停背景音乐、、刚刚进来是没播放背景音乐的当然你可以不要这句进来就开始播放
    SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();


    在判断失败的地方加入音效:

    SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
    SimpleAudioEngine::sharedEngine()->playEffect("music/shibai.ogg");


    在你想要音效的地方都可以加上;

    ==============================华丽的分割线=========================

    ===============到这里在win32下基本能运行了。大概逻辑也清晰了=======================

    ===============接下来看看android下======================

    1、第一步当然是要编译一下咯可直接在doc下编译。或者你想高大上在cygwin下也一样哈哈

    进入proj.android下执行python build_native.py如下图(我的是编译过的所以没那么多,最开始编译会比较慢)没报错大功告成(报错的话具体问题具体问谷哥和度娘了)

    ()

    2、在eclipse下导入工程下面的project.android



    然后就可以run了


    效果图当然我是换了一下背景和bird哈哈你们也可以换自己喜欢的人物