我正在参加「创意开发 投稿大赛」详情请看:创意开发大赛来了!”

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

  1. 在线游戏的规矩,本文以中国象棋为例。
  2. 凭借Zego 音视频 SDK的实时音讯能力,完结在线游戏实时数据传输。
  3. 凭借Zego 音视频 SDK的语音能力,完结在线语音。

留意:虽然本文以中国象棋为例,但其他在线小游戏同样能够套用,只是游戏规矩不相同而已。

实时语音对讲终究作用如下:

Android完结仿微信实时语音对讲功用|与女友游戏开黑

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中强大的实时音讯能力完结实时棋盘同步,详细怎么接入能够查看官方文档: doc-zh.zego.im/article/357…。通过这篇官方文档,基本上能够完结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官方文档doc-zh.zego.im/article/763…。 简略来说,最重要的是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如下:

源码