从零开始教你制作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 plaincopy

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

[cpp] view plaincopy

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

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

[cpp] view plaincopy

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

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

[cpp] view plaincopy

  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 plaincopy

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

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

水管类:Obstacle.cpp

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

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

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

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

[cpp] view plaincopy

  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 plaincopy

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

根据游戏状态处理。

碰撞检测方法:intersectsRect

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

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

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

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

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

分数的显示:

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

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

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

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

然后

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  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

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

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

时间: 2024-10-12 20:52:28

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

详解cocos2dx 3.0的release版本在android平台的签名过程

当您的游戏准备发布前,需要编译成为release版本,命令中需要增加 -m release,编译命令如下: cocos compile -p android -m release 在编译结束后,生成xxx_release_unsigned.apk,此时会提示进行签名,需要输入.keystore的路径. .keystore的生成方法: 使用keytool,命令如下: keytool -genkey -v -keystore my-release-key.keystore -alias alias_

Cocos2d-x 2.0以上版本安装方法

1,cd 到2dx根目录,MAC平台使用./create-multi-platform-projects.py  然后提示: -bash: ./create-multi-platform-projects.py: /usr/bin/evn: bad interpreter: No such file or directory 没关系,我们打开.py文件,发现其实引用的是tools/project-creator/create_project.py 这文件 2,我们再cd 到tools/proje

7、Cocos2dx 3.0游戏开发找小三之3.0版本的代码风格

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27691337 Cocos2d-x代码风格 前面我们已经多次提到 Cocos2d-x 源自于 Cocos2d-iPhone.Cocos2d-iPhone 是一个十分出色的游戏引擎,许多优秀的 iOS平面游戏都基于 Cocos2d-iPhone 开发,而它的实现语言是 Objective-C.因此,Cocos2d-x 也就沿袭了 Objective-C 的

8、Cocos2dx 3.0游戏开发找小三之3.0版本的内存管理

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27693365 复杂的内存管理 移动设备上的硬件资源十分有限,内存尤为宝贵,开发者必须十分慎重地利用内存,避免不必要的消耗,更要防止内存泄漏. 基于 Cocos2d-iPhone 的 Objective-C风格的内存管理是 Cocos2d-x 的一个特色. 把 Objective-C 的内存管理方式引入 C++,使得游戏开发的内存管理难度下降了个层次.

解决cocos2d-X 2.0版本后创建的Android项目提示org.cocos2dx.lib.Cocos2dxActivity找不到问题

原地址: http://blog.163.com/[email protected]/blog/static/6070970220132511558143/ 解决方法:    复制 ***\cocos2dx\platform\android\java\src\ (***为cocos2d-x更目录) 到你android项目中的src文件夹中这样就又有一个麻烦问题,是不是每次创建都要复制呢,答案当然是否定的,来看一劳永逸的方法,定位 (cocos2d-x根目录)\template\android\,

TalkingData游戏版本在Cocos2d-x 3.0使用

Cocos2dx在3.0的版本中改动确实不少啊,所以导致原来可以在Cocos2.x版本上的demo都不能直接用,所以不得不重要写一个新的demo 但是TalkingData的库一直都是可以用的,只是之前的demo不能运行. =====为了打包的大小新的Demo中没有cocos2d这个库,下载后可以copy一份,或者直接引用cocos的文件下面的库==== 一.先来看一下在Cocos3.0上用脚本生成的工程的整个目录结构. 包括android和ios的内容,注意:在生成工程的时候,会把cocos的

实习小白::(转) Cocos2d-x 3.0 开发(十五)使用UILayout布局,制作对话界面

1.概述 上一篇我们在编辑器中设计了一个静态的UIScrollView,而通常我们都需要在程序中动态增加信息.插入元素的位置怎么确定?在3.0中UILayout已经实现了基本的布局,一起来看看吧: 2.编辑界面 打开CocoStudio的UIEditor 编辑一个界面,创建一个ScrollView和两个Button.因为ScrollView继承自UILayout,这里我们采用它.不太能搞定的童鞋可参考:Cocos2d-x 3.0 开发(十四)使用UIScrollView 实现大小不同物品拖动展示

Cocos2dx 3.0开发环境搭建--Eclipse上构建一个Android项目

一.前言: 本篇主要介绍Cocos2d-x 3.0的一些基础内容,以及在Eclipse上上编译我们的Cocos2d-x项目,成功把Helloworld运行起来了.看完本篇博客之后,你就会知道Cocos2d-x 3.0竟然发生了如此大的变化,变得如此简单,环境搭建.项目创建.编译的方式更加人性化了. 二.环境准备: 1.下载ADT Bundle(Eclipse捆绑了SDK和ADT),或者是Eclipse安装了ADT插件. 2.安装JDK.NDK.Ant .Python,然后配置环境. 3.Coco

Cocos2d-x 3.0 实例学习教程 前沿

前一段时间学过cocos2d-x  2.x ,后来去做了一些别的项目.最近又想开发自己的游戏了,可是cocos2d-x 已经升级到3.0 ,好多API都变了.所以决定再把cocos2d-x学一遍,一是加深理解,二是熟悉一下3.0的新接口. 我感觉学习3.0最好的办法是学习官方给出的实例,如果在网上搜索学习的话,会出现很多不同的答案,而且版本cocos2d-x beta版和3.0版还有很多不同. 接下来的教程是对官方实例的分析以及根据实例创建自己的小实例. Cocos2d-x 3.0 实例学习教程