本文原创:转载请注明地址: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类
- #include "cocos2d.h"
- #include "Obstacle.h"
- class FlyBirdGame :public cocos2d::Layer
- {
- public:
- static cocos2d::Scene* createScene();
- virtual bool init();
- CREATE_FUNC(FlyBirdGame);
- void initUI();
- void gameStart(Object* pSender);
- void update(float time);
- Obstacle* obstacle;
- };
- #include "cocos2d.h"
- #include "FlyBirdGame.h"
- #include "resource.h";
- USING_NS_CC;
- Scene* FlyBirdGame::createScene()
- {
- auto scene = Scene::create();
- auto layer = FlyBirdGame::create();
- scene->addChild(layer);
- return scene;
- }
- bool FlyBirdGame::init()
- {
- if (!Layer::init())
- {
- return false;
- }
- initUI();
- return true;
- }
initUI里是一些UI初始化方法:
- // win size
- auto winSize = Director::getInstance()->getVisibleSize();
- // game bg
- auto bg = Sprite::create(bird_bg);
- bg->setPosition(winSize.width / 2, winSize.height / 2);
- bg->setScale(winSize.width / bg->getContentSize().width, winSize.height / bg->getContentSize().height);
- this->addChild(bg);
- // start btn
- auto startBtn = MenuItemImage::create(bird_start_btn, bird_start_btn_pressed, CC_CALLBACK_1(FlyBirdGame::gameStart, this));
- auto menu = Menu::create(startBtn, NULL);
- menu->setTag(100);
- this->addChild(menu);
- // hero
- auto hero = Sprite::create(bird_hero);
- hero->setPosition(winSize.width / 5, winSize.height*0.8);
- hero->setVisible(false);
- hero->setTag(200);
- this->addChild(hero);
开始游戏按钮绑定的gameStart方法:
- void FlyBirdGame::gameStart(Object* pSender)
- {
- auto btn = this->getChildByTag(100);
- btn->setVisible(false);
- auto hero = this->getChildByTag(200);
- Size win = Director::getInstance()->getWinSize();
- obstacle->gameStart = true;
- }
隐藏开始按钮,显示小鸟,水管开始移动
还有更新方法:
- scheduleUpdate();
- void FlyBirdGame::update(float time)
- {
- obstacle->update();
- }
=======================================
水管类:Obstacle.cpp
update方法里判断游戏是游戏是否开始
- void Obstacle::update()
- {
- if (gameStart == false)
- return;
- addCount++;
- if (addCount == 60)
- {
- addOne(0);
- addCount = 0;
- }
- for (int i = obstacleList->count() - 1; i >= 0; i--)
- {
- auto s = (Sprite*)obstacleList->getObjectAtIndex(i);
- s->setPositionX(s->getPositionX() - 3);
- if (s->getPositionX() < -s->getContentSize().width / 2)
- {
- obstacleList->removeObjectAtIndex(i);
- this->removeChild(s);
- }
- }
- }
并且遍历水管列表
出边界的化销毁
接下来是addOne方法:添加水管方法:
- void Obstacle::addOne(int offsetX)
- {
- Size size = Director::getInstance()->getWinSize();
- auto sprite = Sprite::create(bird_obstacle_up);
- Size spriteSize = sprite->getContentSize();
- obstacleList->addObject(sprite);
- this->addChild(sprite);
- auto sprite2 = Sprite::create(bird_obstacle_down);
- Size spriteSize2 = sprite->getContentSize();
- obstacleList->addObject(sprite2);
- this->addChild(sprite2);
- // set positon
- int maxUpY = size.height + spriteSize.height / 4;
- int minUpY = size.height - spriteSize.height / 4;
- int y1 = CCRANDOM_0_1()*(maxUpY - minUpY) + minUpY;
- int maxDownY = spriteSize.height / 4;
- int minDownY = -spriteSize.height / 4;
- int y2 = CCRANDOM_0_1()*(maxDownY - minDownY) + minDownY;
- if (y1 - y2 - spriteSize.height < 160)
- {
- y2 = y1 - spriteSize.height - 160;
- }
- sprite->setPosition(ccp(size.width + spriteSize.width / 2 + offsetX, y1));
- sprite2->setPosition(ccp(size.width + spriteSize2.width / 2 + offsetX, y2));
- }
然后随机一下,并且保证上下连个水管有个最小的距离
效果如下:
=============================
此时的游戏还没触摸和碰撞逻辑
马上添加:(刚才抽空玩了把魔方:五阶的我只能搞定一个面,虽然有官方规律但是那样好像比的是记忆力)
听说cocos2dx3.0的事件监听方式改变了
先在FlyBirdGame.h里声明俩方法:
- void onTouchesEnded(const vector<Touch*>& touches, Event* event);
- void onTouchesBegan(const vector<Touch*>& touches, Event* event);
在cpp文件的初始化里绑定事件:
- // touch
- auto dispatcher = Director::getInstance()->getEventDispatcher();
- auto listener = EventListenerTouchAllAtOnce::create();
- listener->onTouchesEnded = CC_CALLBACK_2(FlyBirdGame::onTouchesEnded, this);
- listener->onTouchesBegan = CC_CALLBACK_2(FlyBirdGame::onTouchesBegan, this);
- dispatcher->addEventListenerWithSceneGraphPriority(listener, this);
在两个事件方法里改变标记位,在小鸟的update方法里根据这个标记位来改变高度
=============================
碰撞检测:
记得cocos2dx3.0以前都是自己写一个根据CCSprite获取CCRect的方法
现在直接用 Sprite的getBoundingBox()方法
不过如果有特殊需求还得自己写,比如想扩大或缩小碰撞区域
在FlyBirdGame.cpp文件里
update算主逻辑方法:
- void FlyBirdGame::update(float time)
- {
- auto winSize = Director::getInstance()->getVisibleSize();
- auto hero = this->getChildByTag(TAG_HERO);
- Rect rHero = ((Sprite*)hero)->getBoundingBox();
- switch (GAME_STATUS)
- {
- case GAME_STATUS_PLAYING:
- obstacle->update();
- // update bird positionY
- if (isFlying&&hero->getPositionY() < winSize.height)
- {
- hero->setPositionY(hero->getPositionY() + v);
- }
- else if (hero->getPositionY()>0)
- {
- hero->setPositionY(hero->getPositionY() - v);
- }
- //check collision
- for (int i = 0; i < obstacle->obstacleList->count(); i++)
- {
- Sprite* obstacleRect = (Sprite*)obstacle->obstacleList->getObjectAtIndex(i);
- bool pia = rHero.intersectsRect(obstacleRect->getBoundingBox());
- if (pia == true)
- {
- GAME_STATUS = GAME_STATUS_GAME_OVER;
- break;
- }
- }
- break;
- case GAME_STATUS_GAME_OVER:
- CCLog("over");
- this->getChildByTag(TAG_OVER)->setVisible(true);
- break;
- case GAME_STATUS_RESTART:
- //reset game
- <span style="white-space: pre;"> </span>obstacle->removeAllChildren();
- obstacle->obstacleList->removeAllObjects();
- // reset hero
- hero->setPosition(winSize.width / 5, winSize.height*0.8);
- // show btn
- auto btn = this->getChildByTag(TAG_START_BTN);
- btn->setVisible(true);
- // show logo
- auto logo = this->getChildByTag(TAG_LOGO);
- logo->setVisible(true);
- break;
- }
- }
根据游戏状态处理。
碰撞检测方法:intersectsRect
bool pia = rHero.intersectsRect(obstacleRect->getBoundingBox());
if (pia == true)
{
GAME_STATUS = GAME_STATUS_GAME_OVER;
break;
}
游戏状态定义在 resource.h 文件里
- static const int GAME_STATUS_START = 10;
- static const int GAME_STATUS_PLAYING = 20;
- static const int GAME_STATUS_GAME_OVER = 30;
- static const int GAME_STATUS_RESTART = 40;
接下来可以优化很多很多东西
===================================================
真搞不懂为什么和弦要那么别扭的按法
相较之下
还是代码简单
继续优化
添加小鸟动画:
添加到resource.h 文件中等待使用
也可以直接在cpp文件中用不过骨头习惯了资源统一管理
- Animation* an = Animation::create();
- an->addSpriteFrameWithFileName(bird_hero);
- an->addSpriteFrameWithFileName(bird_hero2);
- an->addSpriteFrameWithFileName(bird_hero3);
- an->setDelayPerUnit(0.5f / 3.0f);
- an->setLoops(-1);
- Animate* anim = Animate::create(an);
- hero->runAction(anim);
F5运行看效果,确实生动一点了
=========================================================
分辨率问题:
在AppDelegate.cpp入口方法中加入:
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionExactFit);
其中320,480是游戏設計時的分辨率。
后面参数介绍如下“:
- //kResolutionExactFit x,y都拉伸,使铺满屏幕
- //kResolutionNoBorder 一个方向铺满屏幕,另外一个方向超出屏幕
- //kResolutionShowAll 854 * 480 的设计区域全部可见,但是可能留有黑边(如在960 * 640的屏幕上)
分数的显示:
之前的几个demo都是使用本办法显示的特殊数字:一排图片然后根据每位上的数字决定显示哪个图片
本来打算自己封装个方法,再一看,有更简单的:
从自带的demo里找点合适的字体资源,拷贝到fonts文件夹下
记住把fnt和对应的png都拷贝过来
然后
- auto label1 = LabelBMFont::create("123456", "fonts/futura-48.fnt");
- addChild(label1);
- label1->setPosition(Point(win.width / 2, win.height / 2));
================================================
分数显示ok了,下面看下分数逻辑
当小鸟的坐标等于柱子的坐标时,score+1(因为是上下俩柱子对象,所以除以2显示)
别忘记判断时要让小鸟飞过柱子,而不是跟柱子纵轴对齐
相关代码在检测碰撞时添加:
- //check collision
- for (int i = 0; i < obstacle->obstacleList->count(); i++)
- {
- Sprite* obstacleSprite = (Sprite*)obstacle->obstacleList->getObjectAtIndex(i);
- bool pia = rHero.intersectsRect(obstacleSprite->getBoundingBox());
- if (pia == true)
- {
- GAME_STATUS = GAME_STATUS_GAME_OVER;
- break;
- }
- int oPosX = obstacleSprite->getPositionX() + obstacleSprite->getContentSize().width / 2;
- int heroX = hero->getPositionX() - hero->getContentSize().width;
- if (oPosX == heroX)
- {
- score++;
- auto scoreSprite = (LabelBMFont*)this->getChildByTag(TAG_SCORE);
- String* s = String::createWithFormat("%d", score / 2);
- scoreSprite->setString(s->getCString());
- }
- }
======================================================
增加下游戏难度
之所以死不了是因为小鸟的速度改变的很均匀
因为触摸事件只改变速度 不改变加速度
- // update bird positionY
- if (hero->getPositionY() > 0 && hero->getPositionY() < winSize.height)
- {
- velocity -= gravity;
- hero->setPositionY(hero->getPositionY() + velocity);
- }
- //if (isFlying&&hero->getPositionY() < winSize.height)
- //{
- // hero->setPositionY(hero->getPositionY() + velocity);
- //}
- //else if (hero->getPositionY()>0)
- //{
- // hero->setPositionY(hero->getPositionY() - velocity);
- //}
- //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
================================华丽的结束===============================