从零开始教你制作cocos2dx-3.0 版本FlappyBird(可上架版本)(包括添加广告等)完整制作过程

本文原创:转载请注明地址: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类

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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. };  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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初始化方法:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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方法:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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. }  

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

还有更新方法:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. scheduleUpdate();  
  2. void FlyBirdGame::update(float time)  
  3. {  
  4.     obstacle->update();  
  5. }  

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

水管类:Obstacle.cpp

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


[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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方法:添加水管方法:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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里声明俩方法:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void onTouchesEnded(const vector<Touch*>& touches, Event* event);  
  2. void onTouchesBegan(const vector<Touch*>& touches, Event* event);  

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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算主逻辑方法:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 文件里

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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文件中用不过骨头习惯了资源统一管理

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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是游戏設計時的分辨率。

后面参数介绍如下“:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //kResolutionExactFit x,y都拉伸,使铺满屏幕  
  2. //kResolutionNoBorder 一个方向铺满屏幕,另外一个方向超出屏幕  
  3. //kResolutionShowAll  854 * 480 的设计区域全部可见,但是可能留有黑边(如在960 * 640的屏幕上)  
=============================================================

分数的显示:

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

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

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

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

然后

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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显示)

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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. }  


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

增加下游戏难度

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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哈哈你们也可以换自己喜欢的人物


==========================加入广告==================

四、激动人心的时刻来了,不加入广告没钱啊。。。。当然你要是高富帅就看到这里吧。下面的不用看了哈哈。。


广告平台都大同小异===至于怎么选择-----建议选大的(靠谱点,要不有钱收不到就悲剧了)


我用的是万普的(不管网上怎么说,这个是我到目前收到过钱的哈哈)http://www.waps.cn/?f=522123428   (这个地址是我的推荐地址哈哈、、)

简单的就看下面红色的那部分就可以了;

这么小个游戏也没必要加那么多广告哈?哈哈

这种一般我就加个迷你广告,添加简单。。也不影响游戏用户体验(下图上面那条就是广告滚动的。哈哈)


下载广告的sdk里面其实有说明:

解压包中libs 目录下的AppOffer_2.0.6.jar 放入工程指定的libs 目录。4.添加配置信息
4.1 配置用户权限
请将下面权限配置代码复制到 AndroidManifest.xml 文件中 :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_TASKS" />
4.2 添加相关类(可选)
将Demo中src目录下的cn.waps.extend 包拷贝到Android项目中对应的文件夹下:
5.调用初始化接口
5.1在主Acitivity的onCreate方法中添加代码
//方式①:通过代码设置APP_ID和APP_PID
AppConnect.getInstance(APP_ID, APP_PID,this);
APP_ID为应用标识,该值由万普后台添加应用后自动生成,点击“应用详情”获取。
APP_PID为分发渠道标识,使用规则请参见本文档附表《常用渠道编码表》。
除了使用以上方法,还可以在AndroidManifest内添加配置来设置APP_ID 和APP_PID:
<meta-data android:name="APP_ID" android:value="应用标识" />
<meta-data android:name="APP_PID" android:value="分发渠道标识" />
//方式②:通过 AndroidManifest 文件读取 APP_ID 和 APP_PID
AppConnect.getInstance(this);
注意:上传到万普平台官方合作商店(机锋、N 多、木蚂蚁、优亿、联想、MM、十字猫等)的,
需要采用方式②初始化,并需要严格按照《常用渠道编码表》的要求设置对应的APP_PID 标识,
才能快速通过商店审核;而对于其他可能会限制第三方广告SDK 的应用商店,需要采用方式①
初始化,并结合万普“在线参数”功能进行广告显示控制,在通过商店审核并正常发布之后再开
启广告。
5.2根据添加的广告形式还需要添加
// 预加载自定义广告内容(仅在使用了自定义广告、抽屉广告或迷你广告的情况,才需要添加)AppConnect.getInstance(this).initAdInfo();
// 预加载插屏广告内容(仅在使用到插屏广告的情况,才需要添加)
AppConnect.getInstance(this).initPopAd(this);
// 预加载功能广告内容(仅在使用到功能广告的情况,才需要添加)
AppConnect.getInstance(this).initFunAd(this);
5.3在程序退出的处理方法中添加代码
AppConnect.getInstance(this).close();
6.混淆配置
如果应用进行了混淆编译,需要在混淆的配置文件中加入以下代码,避免SDK 被二次混淆编译,才能确保
SDK 功能正常使用。如果开发者使用了定制名的 SDK,也需要对相应的包名加入类似代码:
-keep public class cn.waps.** {*;}
-keep public interface cn.waps.** {*;}
//对于使用 4.0.3 以上 android-sdk 进行项目编译时产生异常的情况时,加入以下内容
-dontwarn cn.waps.**

 添加广告
1.迷你广告调用
迷你广告是以View 的形式显示在某个Activity中。可以通过 xml布局的方式添加(请参考demo中的添加方
式)。如果通过代码方式添加的话,请参考下面代码。在 cocos2dx 生成的 android 项目中的 Activity 的
onCreate()函数中添加如下代码:
// 迷你广告
LinearLayout adMiniLayout = new LinearLayout(this);
adMiniLayout.setOrientation(LinearLayout.VERTICAL);
FrameLayout.LayoutParams lp_mini = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
// 设置adMiniLayout的悬浮位置,具体的位置开发者根据需要设置
lp_mini.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
this.addContentView(adMiniLayout, lp_mini);
LinearLayout miniLayout = new LinearLayout(this);
adMiniLayout.addView(miniLayout);
// 添加迷你广告
AppConnect.getInstance(this).showMiniAd(this, miniLayout, 10);注意:添加迷你广告这段代码的时候,请添加在setContentView()后面。
2.互动广告调用
互动广告是以View 的形式显示在某个Activity中。可以通过 xml布局的方式添加(请参考demo中的添加方
式)。如果通过代码方式添加的话,请参考下面代码。在 cocos2dx 生成的 android 项目中的 Activity 的
onCreate()函数中添加如下代码:
// 互动广告
LinearLayout adBannerLayout = new LinearLayout(this);
adBannerLayout.setOrientation(LinearLayout.VERTICAL);
FrameLayout.LayoutParams lp_banner = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
// 设置adBannerLayout的悬浮位置,具体的位置开发者根据需要设置
lp_banner.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
this.addContentView(adBannerLayout, lp_banner);
LinearLayout bannerLayout = new LinearLayout(this);
adBannerLayout.addView(bannerLayout);
// 添加互动广告
AppConnect.getInstance(this).showBannerAd(this, bannerLayout);
注意:添加互动广告这段代码的时候,请添加在setContentView()后面。

3.插屏、退屏、功能等广告的调用
3.1 Android中的代码添加
步骤一:首先让主Activity实现UpdatePointsNotifier接口并实现里面的方法:
public class WapsCocos2dxDemo02 extends Cocos2dxActivity implements UpdatePointsNotifier {
//实现 getUpdatePoints 和 getUpdatePointsFailed 方法
@Override
public void getUpdatePoints(String arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void getUpdatePointsFailed(String arg0) {
// TODO Auto-generated method stub
}
步骤二:声明handler:在你的主Activity类中,增加静态变量Handler
private static Handler handler;
private static Context mContext;
步骤三:定义静态函数:在你的主Activity类中定义一个静态函数showAdStatic()
// 向handler发送要展示Banner的消息
public static void showAdStatic(int adTag) {
Message msg = handler.obtainMessage();
msg.what = adTag; // 私有静态的整型变量,开发者请自行定义值handler.sendMessage(msg);
}
步骤四:在你的主Activity类的OnCreate()函数中,初始化静态变量handler,定义处理消息函数:
mContext = this;
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case 0:
// 显示推荐列表(综合)
AppConnect.getInstance(mContext).showOffers(mContext);
break;
case 1:
// 显示插屏广告
// 判断插屏广告是否已初始化完成,用于确定是否能成功调用插屏广告
boolean hasPopAd = AppConnect.getInstance(mContext)
.hasPopAd(mContext);
if (hasPopAd) {
AppConnect.getInstance(mContext).showPopAd(mContext);
}
break;
case 2:
// 显示推荐列表(软件)
AppConnect.getInstance(mContext).showAppOffers(mContext);
break;
case 3:
// 显示推荐列表(游戏)
AppConnect.getInstance(mContext).showGameOffers(mContext);
break;
case 4:
// 获取全部自定义广告数据
Intent appWallIntent = new Intent(mContext, AppWall.class);
mContext.startActivity(appWallIntent);
break;
case 5:
// 获取一条自定义广告数据
AdInfo adInfo = AppConnect.getInstance(mContext)
.getAdInfo();
AppDetail.getInstanct().showAdDetail(mContext, adInfo);
break;
case 6:
// 消费虚拟货币.
AppConnect.getInstance(mContext).spendPoints(10,
WapsCocos2dxDemo01.this);
break;
case 7:
// 奖励虚拟货币
AppConnect.getInstance(mContext).awardPoints(10,
WapsCocos2dxDemo01.this);
break;
case 8:
// 显示自家应用列表
AppConnect.getInstance(mContext).showMore(mContext);
break;
case 9:
// 根据指定的应用app_id展示其详情
AppConnect.getInstance(mContext).showMore(mContext,
"c8c3dab81e65e695020e69a74ccff196");break;
case 10:
// 调用功能广告接口(使用浏览器接口)
String uriStr = "http://www.baidu.com";
AppConnect.getInstance(mContext).showBrowser(mContext,
uriStr);
break;
case 11:
// 用户反馈
AppConnect.getInstance(mContext).showFeedback(mContext);
break;
case 12:
// 退屏广告
QuitPopAd.getInstance().show(mContext);
break;
}
}
};
步骤五:新建 C++文件或者直接将 Demo 中 Classes 目录下的 WapsAd.h,WapsAd.cpp 拷贝到项目的 Classes
文件夹下。新建 C++文件步骤:在 Cocos2dx/你的工程名(Android 工程)/Classes 目录下,分别增加一个.h
和.cpp文件,文件名可自定义,如WapsAd.h,WapsAd.cpp。
步骤六:头文件的声明:在WapsAd.h文件中,声明一个静态函数showAd():
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#include "cocos2d.h"
#endif
using namespace cocos2d;
class WapsAd
{
public:
WapsAd();
virtual ~WapsAd();
static void showAd(int adTag);//通过JNI调用JAVA静态函数实现展示AD
};
步骤七:cpp文件中实现函数: 在WapsAd.cpp文件中,对函数进行实现:
#include "WapsAd.h"
WapsAd::WapsAd(){}
WapsAd::~WapsAd(){}
void WapsAd::showAd(int adTag)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断当前是否为Android平台
JniMethodInfo showAd;
bool isHave = JniHelper::getStaticMethodInfo(showAd,"cn/waps/demo/WapsCocos2dxDemo01","showAdStatic",
"(I)V");
if (!isHave) {
CCLog("jni:showAdStatic is null");
}else{//调用此函数
showAd.env->CallStaticVoidMethod(showAd.classID, showAd.methodID,adTag);
}
#endif
}
步骤八:Cocos2dx中调用函数
当需要展示或者关闭广告条的时候,直接调用下面的代码:
#include "WapsAd.h" //在调用的文件中包含 WapsAd.h *
WapsAd::showAd(整型参数); //0,1,2,3....
步骤九:编译运行
在 cocos2dx/你的工程名(Android 工程)/proj.android/jni 目录下,打开 Android.mk 文件,更改
LOCAL_SRC_FILES,增加一句:../../Classes/WapsAd.cpp 示例如下:
LOCAL_SRC_FILES := helloworld/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp\
../../Classes/WapsAd.cpp
* 注意“\”
编译之前还需要配置两个环境变量(配置过的可以跳过) :
右键计算机-属性-高级管理-环境变量-添加系统变量
名:NDK_ROOT 值:D:\soft\android-ndk-r8e (你的ndk目录)
名:COCOS2DX_ROOT 值:E:\code\cocos2d-2.1rc0-x-2.1.2\cocos2dx (你的cocos2dx引擎目录)
步骤十:转到cocos2dx/你的工程名(Android工程)/proj.android目录下,执行./build_native.sh 进行编
译, 编译完后, 在Eclipse中刷新你的工程 (必须要刷新, 不然工程中的libgame.so不会更新) , 然后在Eclipse
中编译运行程序即可。
4.在 cocos2dx 游戏 C++代码中调用积分接口
SDK 提供了监听积分余额变动接口,方便 UI 自动刷新显示变动的积分余额。监听积分变动的UI 相关的类必
须实现UpdatePointsNotifier接口。
4.1定义本地函方法
在你的主Activity类中定义一个本地方法:
// 此处涉及到JNI的知识,请查阅相关文档理解
private native int pointsBalanceChange(String pointName, int point,String config);
4.2 在getUpdatePoints()函数中调用本地方法 pointsBalanceChange()。@Override
public void getUpdatePoints(String arg0, int arg1) {
pointsBalanceChange(arg0, arg1, configOnLine);
}
@Override
public void getUpdatePointsFailed(String arg0) {
// TODO Auto-generated method stub
}
4.3 对积分变更进行处理
当积分变更的时候,会调用 UpdatePointsNotifier 的 getUpdatePoints()函数。进而调用了 JAVA 本地方法
pointsBalanceChange()。下面在你需要对积分变更进行处理的地方(如你要显示积分剩余多少)对JAVA 本地
方法进行实现。 下面是在HelloWorld.cpp文件中,对积分变更事件的处理,添加代码如下:
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#include "cocos2d.h"
extern "C"
{
jint Java_cn_waps_demo_WapsCocos2dxDemo01_pointsBalanceChange( JNIEnv *env,jobject thiz,jstring prompt,jint
point,jstring config)
{
/*
jin表示JAVA的本地函数返回类型为int
Java_开头是必须的
com_waps_sample_WapsCocos2dxSample对应包名:com_waps_sample_WapsCocos2dxSample,
WapsCocos2dxSample是类名,开发者需要自己修改。
pointsChange,则是函数名
JNIEnv *env,jobject thiz是两个必须要有参数
jint point则对应JAVA本地函数的参数int pointsBalanceChang(int point)
如开发者的一个类Test在包com.a.b中,而且类中的定义一个本地函数public native void doSomething(int p);
那么这里应该写void Java_com_a_b_Test_doSomething( JNIEnv *env,jobject thiz,jint p )
*/
//获取积分单位
const char* szStr = (env)->GetStringUTFChars(prompt, 0 );
//获取积分
CCString* ns=CCString::createWithFormat("%d",point);
const char* str=ns->getCString();
std::string tempStr(str);
HelloWorld::changeStr= tempStr;
//获取在线参数
const char* configStr = (env)->GetStringUTFChars(config, 0 );
std::string tempStrc(configStr);
HelloWorld::changeConfig= tempStrc;
(env)->ReleaseStringUTFChars(prompt, szStr );
return 0;
}
}注:调用了用户反馈以后退回主 Activity 屏幕会变成竖屏,为了解决此问题需要在主 Activity 中添加以
下代码(如果程序中没有调用用户反馈就不需要添加此代码):
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onWindowFocusChanged(hasFocus);
}








=====================最后----打包上架=======


=====最后的最后,谢谢大家的耐心阅读哈哈。。======

貌似有点长了。东西确实太多。可能有些地方都还没讲得很清楚。段个大概流程吧。具体问题大家具体问谷哥度娘,哈哈。。。


附件刚刚传了现在哈看不到等哈有链接了我补充上。。

下载地址:http://download.csdn.net/detail/zp522123428/7465519










================================华丽的结束===============================

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值