Cocos2d

Demo运行指引

1.环境准备
cocos2d是一个跨平台的2D游戏引擎,本demo可以在三个平台(win32,android,ios)下运行。
你需要在windows下或者iMac安装好cocos2dx 库,请参考官方的安装指南。下面以windows的环境来演示运行demo的过程。
如果要编译Android平台,需要事先安装好android sdk和jdk。并依据官方指南,配置好环境变量。
如果要编译iOS平台,需要安装好Xcode软件。
cocos2d支持c++,js,lua语言编写。本demo用c++语言编写。
环境配置好,应该能够通过cocos new 命令创建新项目。

2.demo生成
执行命令 cocos new -l cpp -p cpp-project ValleyDemo
会在当前目录下生成cpp-project文件夹。
里面的目录结构如下

把下载下来的demo文件夹解压覆盖进去。把sdk文件夹放到cocos2d/external下,并重命名为valleyrtc。 打开proj.win32的sln 工程执行编译运行即可。
如果是编译Android项目,则进入到proj.android/jni/下,执行命令
cocos compile -p android -ap armeabi-v7a -l 21
如果没有错误,应该会在bin/debug/android/目录下生成apk文件,安装使用即可。
3.运行demo
界面如下

用户名任意填写,频道号可以填写1-25。
登陆进去后看到界面如下。

主界面显示用户列表,底部有几个按钮操作频道。点击播放中/停止播放按钮切换播放功能 点击说话中/停止说话按钮控制自己是否说话。点击扬声器/听筒按钮可以选择播放的声音是否外放。挂断按钮退出频道。如果检测到人声说话,界面会提示当前某用户正在说话中…..。

SDK的集成

1.概述

本文档主要描述了将SDK 集成进项目里的一些步骤和注意点。
SDK 包含了三个平台的头文件和动态库。目前支持C/C++语言。对于js 和lua语言,需要开发者自行封装。
头文件包括:
ValleyRtcAPI.h
ValleyRtcDef.h
ValleyRtcExtInterface.h
windows库包含32位和64位的ValleyRtcAPI.dll。
Android库包含armeabi-v7a的libValleyRtcSDK.so 和ValleyRtcSDK.jar
iOS库包含静态库valley_rtc_sdk.framework

2.集成步骤。

假设我们已经有现成的项目:cpp-project。
将sdk放到第三方库目录下,并配置好头文件引用路径。不妨假设放在cocos2d/external目录下,叫valleyrtc。
在项目里添加测试代码

//包含头文件
#include"ValleyRtcAPi.h"
调用 GetSDKVersion();

通过以下设置使其编译通过。

Windows平台

在项目属性c/c++/添加额外引用路径,添加$(EngineRoot)/cocos2d/external/valleyrtc/include,连接属性/额外库路径添加$(EngineRoot)external\valleyrtc\win32 输入里添加ValleyRtcAPi.lib。

Android平台

在AndroidManifest.xml添加权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

proj.android/jni/Android.mk脚本的开头 include $(CLEAR_VARS) 后面,添加上

include $(CLEAR_VARS)
LOCAL_MODULE := ValleyRtcSDK
LOCAL_SRC_FILES := prebuilt/libValleyRtcSDK.so
include $(PREBUILT_SHARED_LIBRARY)
LOCAL_SHARED_LIBRARIES := ValleyRtcSDK

这里prebuilt就是放so的地方。
添加头文件路径
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../cocos2d/external/valleyrtc/include
把ValleyRtcSDK.jar放到libs文件夹内。

iOS平台

将valley_rtc_sdk.framework引入工程。
添加valley_rtc_sdk.framework的引用路径。
在plist文件里添加麦克风权限。如图

添加系统依赖库
CoreTelephoney.framework
libiconv.tbd
libc++.1.tbd
libz.tbd

接口目录

C++ 接口请参考
http://doc.valley.ren/index.php?s=/8&page_id=61

对于cocos2dx的Android平台要先获取InitAndroid的参数。
参考代码如下

static bool run_once = false;
if (!run_once)
{
run_once = true;
JniMethodInfo loadSO;
jclass jcls = JniHelper::getEnv()->FindClass( "com.audio.unity.Unity3DLoader" );
jclass cls_ref = reinterpret_cast<jclass>( JniHelper::getEnv()->NewGlobalRef( jcls ) );
jmethodID mid_init = JniHelper::getEnv()->GetMethodID( cls_ref, "<init>", "()V" );
if ( !mid_init )
{
return;
}
jobject obj = JniHelper::getEnv()->NewObject( cls_ref, mid_init );
JniHelper::getEnv()->DeleteLocalRef( obj );

JniMethodInfo jniMethodInfo;
bool isHave = JniHelper::getStaticMethodInfo(
jniMethodInfo,
"org/cocos2dx/lib/Cocos2dxActivity",
"getContext",
"()Landroid/content/Context;" );

CCAssert( isHave, "代码写错了,这个函数肯定有!" );
obj = jniMethodInfo.env->CallStaticObjectMethod( jniMethodInfo.classID, jniMethodInfo.methodID );
jniMethodInfo.env->DeleteLocalRef( jniMethodInfo.classID );
InitAndroid( obj );
}

js接口说明

概述

本文档介绍了JS脚本接口使用指南,包括函数,参数,返回值,回调格式等等。具体的接入请看前面章节。
js通过jsb的形式与c++绑定,需要将文件jsb_valley_rtc.cpp jsb_valley_rtc.h放到classes里面,参与编译。
在bool AppDelegate::applicationDidFinishLaunching()函数里的末尾注册下
sc->addRegisterCallback( register_jsb_valley_rtc );

在js脚本里的一个简单的代码实例如下:

      this.channel = new ValleyChannel("d:/","");
var version = this.channel.GetSDKVersion();
cc.log("SDK Version:"+version);
var ch = this.channel;
this.channel.Respond = function(param){
cc.log("Respond " + param);
var obj = JSON.parse(param);
switch(obj.type)
{
case 1:
{
if(obj.ec == 0)
{
cc.log("Login success");
var count = ch.GetUserCount();
cc.log("user count:" + count);
var users = ch.GetUserList();
cc.log("userlist:" + users);
}
else
{
cc.log("Login Failed, error code:" + ec);
}
}
break;
}

}
this.channel.Notify = function(param){
cc.log("Notify "+param);
}
this.channel.Login("1","1");

第一步是实例化一个频道。接收两个参数:congfig目录;app授权码,测试环境可以填写空的字符串。
第二步是设置回调函数,总共有两个,Respond和Notify。接收的参数都是json字符串。
Respond的json格式是:{“type”:1,”ec”:0,”ob”:{“userid”:”1”,”channelid”:”1”,”userinfo”:””}}
这里type是事件类型,ec是错误码,ob是附加的参数,不同类型对应不同的参数。
Notify的json格式是:{“type”:101,”ob”:{“userid”:”233”,”userinfo”:””,”disspeak”:false,”block”:false}}
这里type是事件类型,ob是附加的参数,不同类型对应不同的参数。
如果希望函数回调在指定线程,需要在cpp的channel->RegisterRtcSink( delegate,false );里面把第二个参数改为true,然后不断的调用Poll函数去轮询事件。
第三步是登陆频道,如果登陆成功,在Respond函数里会接收到type=1的事件。
这里可以做其他事情。
第四步登出频道,并释放。

##接口说明

new ValleyChannel(configPath,appAuthoKey)

功能 实例化频道
参数 configPath 一个可读可写的路径。appAuthoKey从服务提供商获取,测试环境可填空。
返回值 返回实例
调用方式 同步

int Login(channelid,userid,userinfo)

功能 登陆频道
参数 channelid 频道id,任意字符串,测试环境填写1-25;userid 任意字符串;userinfo可选,自定义。
返回值 错误码
调用方式 异步

void Logout()

功能 登出频道
参数
返回值
调用方式 同步

void Release()

功能 释放频道实例,不可以再调用其成员函数
参数
返回值
调用方式 同步

int GetLoginStatus()

功能 获取当前登陆状态
参数
返回值 0表示未登陆,1表示正在登陆,2表示已登陆。
调用方式 同步

int SetChannelAttr(name,value)

功能 设置频道属性,自定义
参数 name 键,任意字符串,value 值,任意字符串。
返回值 错误码
调用方式 异步

string GetChannelAttr(name)

功能 设置频道属性,自定义
参数 name 键,任意字符串。
返回值 字符串值。
调用方式 同步

int GetUserCount()

功能 查询当前频道用户数
参数
返回值 用户数
调用方式 同步

string GetUserList()

功能 获取用户列表
参数
返回值 json字符串,格式为
userlist:{“user_count”:1,”users”:[{“userid”:”1”,”userinfo”:””,”disspeak”:false,”block”:false}]}
调用方式 同步

string GetUser(uid)

功能 获取指定用户信息
参数 uid 用户id字符串
返回值 json字符串,格式为 {“userid”:”1”,”userinfo”:””,”disspeak”:false,”block”:false}
调用方式 同步

int KickOff(uid)

功能 将用户踢出频道
参数 uid 用户id字符串
返回值 错误码
调用方式 异步

int SetUserAttr(uid,name,value)

功能 设置用户属性
参数 uid 用户id字符串,name 键字符串,value 值字符串。
返回值 错误码
调用方式 异步

string GettUserAttr(uid,name)

功能 获取用户属性
参数 uid 用户id字符串 name 键字符串
返回值 错误码
调用方式 同步

int BlockUser(uid,isBlock)

功能 拒听用户声音
参数 uid 用户id字符串 isBlock 是否拒听
返回值 错误码
调用方式 异步

int DisableUserSpeak(uid,disable)

功能 禁言用户
参数 uid 用户id字符串 disablee 是否禁言
返回值 错误码
调用方式 异步

void EnableSpeak(enable)

功能 是否讲话
参数 enable 是否讲话
返回值
调用方式 同步

void EnablePlayout(enable)

功能 是否播放
参数 enable 是否播放
返回值
调用方式 同步

bool GetSpeakEnabled()

功能 是否开启讲话
参数
返回值 0表示没有开启讲话
调用方式 同步

bool GetPlayoutEnabled()

功能 是否开启播放
参数
返回值 0表示没有开启播放
调用方式 同步

int SetPlayoutVolume(volume)

功能 设置播放音量
参数 音量值,范围[0-100]
返回值 错误码
调用方式 同步

int GetPlayoutVolume()

功能 查询当前播放音量
参数 音量值,范围[0-100]
返回值 音量值
调用方式 同步

void SetSpeakerphoneOn(on)

功能 打开扬声器模式
参数 on bool值,是否打开
返回值
调用方式 同步

bool GetSpeakerphoneOn()

功能 查询当前播放模式
参数
返回值 true表示扬声器模式
调用方式 同步

int Playeffect(trackidx,filename,loopflag,volScale)

功能 播放mp3文件
参数 trackidx 音轨id,有效值0-4.每个音轨只能同时播放一个文件
filename 全路径的合法mp3文件,不支持采样率11025以及更低格式的文件。
loopflag 是否循环播放
volScale 调整mp3音量,有效值[0.0,4.0]
返回值 错误码,参见Plugin.h
调用方式 同步

void StopPlayEffect(trackidx)

功能 停止播放背景音
参数 trackidx 音轨,有效值0-4.
返回值
调用方式 同步

string GetSDKVersion()

功能 当前SDK版本号
参数
返回值 字符串
调用方式 同步

string GetErrDesc(ec)

功能 根据错误码获取错误描述
参数
返回值 返回错误描述字符串,中文,供调试用。
调用方式 同步

接口返回的错误码如下

#define ERR_SUCCEED 0         // 操作成功
#define ERR_NOT_LOGINED -1 // 未登录成功
#define ERR_ALREADY_RUN -2 // 已经在运行
#define ERR_USER_NOTFOUND -3 // 未找到用户
#define ERR_EXCUTING -4 // 正在执行中
#define ERR_NOT_INITIALIZE -5 // 未初始化
#define ERR_UNSUPPORT -6 // 功能不支持
#define ERR_ARGUMENT -7 // 参数错误
#define ERR_CHANNEL_EXPIRED 1 // 频道已经失效
#define ERR_CONNECT_SERVER_FAILED 2 // 连接服务器失败
#define ERR_REQUEST_TIMEOUT 3 // 请求超时
#define ERR_CONFIG 4 // 配置信息错误
#define ERR_NET_POOL 5 // 网络不好
#define ERR_VERSION_UNSUPPORTED 6 // 版本不支持
#define ERR_AUTHO_FAILED 7 // 授权失败
#define ERR_NOT_ENOUGH_CHANNEL 8 // 频道资源不足
#define ERR_SERVER_ERROR 9 // 服务器错误
#define ERR_OPEN_RECORD 10 // 打开采集失败
#define ERR_OPEN_PLAYOUT 11 // 打开播放失败
#define ERR_RECORD_PERMISSION 12 // 没有录音权限
#define ERR_UNDEFINED 100 // 未定义错误

//plugin
#define ECODE_OPENFILE_FAILED 1001 // 文件打开失败
#define ECODE_UNSUPPORT_FORMAT 1002 // 文件格式不支持
#define ECODE_PARAMS_ERROR 1003 //参数错误

Respond函数的参数格式如下

type desc ob
1 登陆返回结果 {“userid”:””,”channelid”:””,”userinfo”:””}
2 频道属性设置结果 {“name”:””,”value”:””}
101 踢人结果 {“userid”:””}
102 设置用户属性结果 {“userid”:””,”name”:””,”value”:””}
201 禁言用户结果 {“userid”:””,”disable”:bool}
202 拒听用户结果 {“userid”:””,”block”:bool}

Notify函数的参数格式如下

type desc ob
1 网络连接不通通知 null
2 网络重新连接上通知 null
3 同一账号重复登陆通知 null
4 房间关闭通知 {“error”:””}
5 房间属性改变通知 {“name”:””,”value”:””}
101 新用户加入频道通知 {“userid”:””,”userinfo”:””,”disspeak”:bool,”block”:bool}
102 用户离开频道通知 {“userid”:””}
103 用户被踢出频道通知 {“userid”:””}
104 用户属性改变通知 {“userid”:””,”name”:””,”value”:””}
201 用户被禁言通知 {“userid”:””,”disable”:bool}
202 用户讲话通知 {“userid”:””,”volume”:int}