与亲朋好友一起玩在线游戏,如果游戏中有实时语音对讲能力就可以拉进玩家之间的距离,添加更多乐趣。我们以经典的中国象棋为例,开发在线语音对讲象棋。本文主要涉及如下几个点:

  1. 在线游戏的规则,本文以中国象棋为例。
  2. 借助Zego 音视频 SDK的实时消息能力,实现在线游戏实时数据传输。
  3. 借助Zego 音视频 SDK的语音能力,实现在线语音。

注意:虽然本文以中国象棋为例,但其他在线小游戏同样可以套用,只是游戏规则不一样而已。

实时语音对讲最终效果如下:

1 中国象棋游戏规则

关于中国象棋的游戏规则,我这里做个简单的介绍。

  1. 车:只能走直线。
  2. 马:只能按字对角走,如果往对角方向的长边有棋子,则不能走。
  3. 象:只能按字对角走,且不能过河。如果字正中心有棋子,则不能走。
  4. 仕:只能在九宫对角线上走。
  5. 帅:只能在九宫里面走,需要注意,双方帅如果在同一条直线上中间必须有棋子,否则不允许在同一条直线。
  6. 跑:如果不吃子,则跟车一样的规则。如果吃子,则需要被吃的子与跑之间有一个棋子。
  7. 兵:没过河时只能前进。过河后,可以左右和前进,但不能后腿。

在玩家每一次下棋时,首先需要验证目标位置是否是有效位置,即是否符合游戏规则:

// 判断是否可以移动
public static boolean canMove(Chessboard chessboard, int fromX, int fromY, int toX, int toY) {
//不能原地走
if (fromX == toX && fromY == toY)
return false; Chess chess = chessboard.board[fromY][fromX];
// 首先,确保目标位置不是自己的子
Chess[][] board = chessboard.board;
if (board[toY][toX] != null && board[toY][toX].isRed() == chessboard.isRed) {
return false;
} switch (chess.type) {
case RED_SHUAI:
case BLACK_SHUAI:
return canShuaiMove(chessboard, fromX, fromY, toX, toY);
case RED_SHI:
case BLACK_SHI:
return canShiMove(chessboard, fromX, fromY, toX, toY);
case RED_XIANG:
case BLACK_XIANG:
return canXiangMove(chessboard, fromX, fromY, toX, toY);
case RED_MA:
case BLACK_MA:
return canMaMove(chessboard, fromX, fromY, toX, toY);
case RED_CHE:
case BLACK_CHE:
return canCheMove(chessboard, fromX, fromY, toX, toY);
case RED_PAO:
case BLACK_PAO:
return canPaoMove(chessboard, fromX, fromY, toX, toY);
case RED_ZU:
case BLACK_ZU:
return canZuMove(chessboard, fromX, fromY, toX, toY);
} return true;
}

如果是符合规则的行走,再直接将目标位置的棋子移除(必须先判断有棋子且是对方棋子才行)。游戏可以一直这样持续下去,直到有一方的被吃掉, 游戏结束。

2 实时游戏数据传输-zego 音视频 SDK

实时传输游戏数据可以自己基于TCP去实现,但有如下几个缺点:

  1. 双方必须在同一个局域网,或者双方必须用有效的互联网ip地址。
  2. 得要精心维护消息数据发送与接收,代码量大且不方便维护。

我们可以借助Zego 音视频 SDK中强大的实时消息能力实现实时棋盘同步,具体如何接入可以查看官方文档:

https://doc-zh.zego.im/article/3575。通过这篇官方文档,基本上可以完成Zego 音视频 SDK的接入工作。

2.1 登录/登出游戏实时语聊房间

使用Zego 音视频 SDK之前必须要先完成登录语聊房间,因为不管是实时语音还是实时消息,都是以房间为单位的。假设读者已经按照官方文档教程创建好引擎对象mEngine。接下来是登录实现代码:

public boolean loginRoom(String userId, String userName, String roomId, String token) {

    ZegoUser user = new ZegoUser(userId, userName);
ZegoRoomConfig config = new ZegoRoomConfig();
config.token = token; // 请求开发者服务端获取
config.isUserStatusNotify = true;
mEngine.loginRoom(roomId, user, config, (int error, JSONObject extendedData) -> {
// 登录房间结果,如果仅关注登录结果,关注此回调即可
});
Log.e(TAG, "登录房间:" + roomId);
return true;
}

登出操作比较简单mEngine.logoutRoom(roomId);指定房间ID即可。

2.2 游戏发送实时消息

有了前面这些准备工作后,接下来是实现实时棋盘同步。封装一个发送消息函数:

public void sendMsg(String roomId, ArrayList<ZegoUser> userList, Msg msg) {

    String msgPack = msg.toString();
// 发送自定义信令,`toUserList` 中指定的用户才可以通过 onIMSendCustomCommandResult 收到此信令
// 若 `toUserList` 参数传 `null` 则 SDK 将发送该信令给房间内所有用户
mEngine.sendCustomCommand(roomId, msgPack, userList, new IZegoIMSendCustomCommandCallback() {
/**
* 发送用户自定义消息结果回调处理
*/
@Override
public void onIMSendCustomCommandResult(int errorCode) {
//发送消息结果成功或失败的处理
Log.e(TAG, "消息发送结束,回调:" + errorCode);
}
}); }

其中,roomId表示房间号,userList表示接收人列表,msg是我们自定义的一个实体类。创建一个表示实时棋盘界面的实体类:

public class MsgBoard extends Msg {
public boolean isRedPlaying; //接下来是否是红方下棋
public byte[][] board; //当前棋局面
public int fromX;
public int fromY;
public int toX;
public int toY; public MsgBoard(int msgType, String fromUserId, boolean isRedPlaying, byte[][] board, int fromX, int fromY, int toX, int toY) {
super(msgType, fromUserId);
this.board = board;
this.isRedPlaying = isRedPlaying;
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
}

游戏中每个玩家下完棋后,将当前棋子位置发出去(如果有服务器,为了安全,这个工作最好让服务器去做)。这样,可以实现不局限于2个游戏玩家,如果有多个观众,任何观众随时上线即可观看对战。

3 接入实时语音SDK

第2小节完成了Zego 音视频 SDK的接入,接下来完成实时实时语音功能。实时语音实现过程可以看即构官网的实时音视频SDK官方文档https://doc-zh.zego.im/article/7636

简单来说,最重要的是2步:

  1. 推:语音推流
  2. 拉:语音拉流

注意:一切操作都必须先登录房间成功后再做,否则会失败。

3.1 语音推流

实时语音推流代码如下:

public void pushStream(String streamId) {
//不管有没有语音推流,先停止语音推流
mEngine.stopPublishingStream();
mEngine.startPublishingStream(streamId);
Log.e(TAG, "已推流:" + streamId);
}

这里的streamId建议RoomID_UserID_后缀形式,以确保唯一性,避免串流

3.2 语音拉流

顾名思义,拉流是拉取对方的实时语音流。那如何知道对方的streamID呢?可以监听如下回调函数:

 public void onRoomStreamUpdate(String roomID,
ZegoUpdateType updateType,
ArrayList<ZegoStream> streamList,
JSONObject extendedData) ;

房间里面一旦有新的流推送或有流停止推送都会触发这个回调函数。我们根据updateType参数来判断是新增还是删除:

if(updateType == ZegoUpdateType.ADD){
//表示有新增流
} else if (updateType == ZegoUpdateType.DELETE) {
//表示有流停止推送
}

一旦判断有新增语音流,那么可以直接拉取对方流,拉流和停止拉流代码如下:

public void pullStream(String streamId) {
mEngine.startPlayingStream(streamId);
} public void stopPullStream(String streamId) {
mEngine.stopPlayingStream(streamId);
}

4 实时语音对讲demo/源码分享

实现了在线实时语音对讲的中国象棋对战游戏,其他任何游戏均可直接套用本文的实时消息同步和实时语音对讲能力。我将这两部份能力封装起来,读者可以直接下载源码复用。

实时语音对讲源码和Demo如下:

源码

Android实现仿微信实时语音对讲功能|与女友游戏开黑的更多相关文章

  1. Android 高仿微信实时聊天 基于百度云推送

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天终于有幸利用百 ...

  2. Android开发--仿微信语音对讲录音

    原文地址:http://www.2cto.com/kf/201502/378704.html 自微信出现以来取得了很好的成绩,语音对讲的实现更加方便了人与人之间的交流.今天来实践一下微信的语音对讲的录 ...

  3. Android 高仿微信头像截取 打造不一样的自定义控件

    转载请表明出处:http://blog.csdn.net/lmj623565791/article/details/39761281,本文出自:[张鸿洋的博客] 1.概述 前面已经写了关于检测手势识别 ...

  4. [转]Android 超高仿微信图片选择器 图片该这么加载

    快速加载本地图片缩略图的方法: 原文地址:Android 超高仿微信图片选择器 图片该这么加载 其示例代码下载: 仿微信图片选择器 ImageLoader

  5. android高仿微信拍照、多选、预览、删除(去除相片)相冊功能

    先声明授人与鱼不如授人与渔,仅仅能提供一个思路,当然须要源代码的同学能够私下有偿问我要源代码:QQ:508181017 工作了将近三年时间了,一直没正儿八经的研究系统自带的相冊和拍照,这回来个高仿微信 ...

  6. android之使用GridView+仿微信图片上传功能

    由于工作要求最近在使用GridView完成图片的批量上传功能,我的例子当中包含仿微信图片上传.拍照.本地选择.相片裁剪等功能,如果有需要的朋友可以看一下,希望我的实际经验能对您有所帮助. 直接上图,下 ...

  7. Android 高仿微信语音聊天页面高斯模糊效果

    目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高 ...

  8. Android 高仿微信即时聊天 百度云为基础的推

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...

  9. Android ActionBar仿微信界面

    ActionBar仿微信界面 1.学习了别人的两篇关于ActionBar博客,在结合别人的文章来仿造一下微信的界面: 思路如下:1).利用ActionBar生成界面的头部,在用ActionBar的Ac ...

  10. Android NineGridLayout — 仿微信朋友圈和QQ空间的九宫格图片展示自定义控件

    NineGridLayout 一个仿微信朋友圈和QQ空间的九宫格图片展示自定义控件. GitHub:https://github.com/HMY314/NineGridLayout 一.介绍 1.当只 ...

随机推荐

  1. 初始化一个ArrayList的多种方式

    序言 本片文章用于归纳java中初始化一个ArrayList的几种方式 add方法添加 最基础的方式就是我们在new一个ArrayList之后使用add方法添加元素 /** * 第一种方式,通过add ...

  2. Excel二维码图片生成器

    Excel二维码图片生成器 它可以将excel文件的数据,每行数据生成一张二维码图片,并保存到电脑.软件无需安装,解压后即可直接使用,无需联网,操作简便快捷. 软件下载地址:点此下载 步骤1:导入事先 ...

  3. 【实时数仓】Day05-ClickHouse:入门、安装、数据类型、表引擎、SQL操作、副本、分片集群

    一.ClickHouse入门 1.介绍 是一个开源的列式存储数据库(DBMS) 使用C++编写 用于在线分析查询(OLAP) 能够使用SQL查询实时生成分析数据报告 2.特点 (1)列式存储 比较: ...

  4. Python全栈工程师之从网页搭建入门到Flask全栈项目实战(4) - Flask模板语法与继承

    1.Flask模板介绍 前置:理解渲染机制即上篇笔记中render_template()功能是如何实现的! 1)找到html文件地址 2)读取html文件中的内容 3)替换html中的特殊字符 4)将 ...

  5. 【Java难点攻克】「NIO和内存映射性能提升系列」彻底透析NIO底层的内存映射机制原理与Direct Memory的关系

    NIO与内存映射文件 Java类库中的NIO包相对于IO包来说有一个新功能就是 [内存映射文件],在业务层面的日常开发过程中并不是经常会使用,但是一旦在处理大文件时是比较理想的提高效率的手段,之前已经 ...

  6. asp前端无法获取后端中select *查询带出来的全部字段

    1.环境 前端:ASP.vbscript 后端:vb 数据库:Sql Server 2.问题描述 最近在做需求时碰到一个很奇怪的问题,后端通过select *查询带出来的字段,在前端只能获取到部分字段 ...

  7. Hadoop详解(07) - Hdfs数据压缩

    Hadoop详解(07) - Hdfs数据压缩 概述 压缩技术能够有效减少底层存储系统(HDFS)读写字节数.压缩提高了网络带宽和磁盘空间的效率.在运行MR程序时,I/O操作.网络数据传输. Shuf ...

  8. ArcGIS插件-太乐地图

    在很多行业,打败你的往往不是竞争对手,而是你意想不到的其他因素.回想十年前,如果能预料到现在的处境,也许当时的心态和做法会有所不同.在多年前,市场上出现包括水经注.太乐.BigeMap.91卫图等多种 ...

  9. [阿里云]Datahub测试使用记录

    由于需要测试阿里云Datahub功能,因此测了一下Datahub的一些功能 DATAHUB: 简介: 阿里云的流式数据(streaming)处理平台 对流式数据的发布(publish)订阅(subsc ...

  10. 当LOGO设计与世界文化擦出火花——JJQ的LOGO设计之路

      <当LOGO设计与世界文化碰撞出火花--论 JJQ 的LOGO是如何制成的> (友链:https://tg.hszxoj.com/user/475) 首先我们对jjq对应的汉字进行拉长 ...