0.5.86 • Published 3 years ago

leihuo-cloud-game-react v0.5.86

Weekly downloads
-
License
ISC
Repository
-
Last release
3 years ago

leihuo-cloud-game-react

云游戏 react 组件

NPM Commitizen friendly JavaScript Style Guide

Install

npm install --save leihuo-cloud-game-react

Usage

单个实例

单实例默认为全屏模式

import React, { Component } as React from 'react'
import CloudGame, { isSupport, getGameDataOf } from 'cloud-game-react'

export default class App extends Component {
  constructor(props) {
    super(props);

    this.onStart = this.onStart.bind(this);
    this.onShutdown = this.onShutdown.bind(this);
    this.onStop = this.onStop.bind(this);
  }

  componentDidMount() {
    // 平台是否支持云游戏
    console.log(isSupport());
    console.log(getGameDataOf('NSH'));
  }

  /**
   * 开始游戏回调
   * @public
   */
  onStart(gameData) {
    console.log("onStart", gameData);
  }

  /**
   * 手动退出游戏回调
   * @public
   */
  onStop(gameData) {
    console.log("onStop", gameData);
  }

  /**
   * 调度退出游戏回调
   * @public
   */
  onShutdown(gameData) {
    console.log("onShutdown", gameData);
  }

  render() {
    return (
        <CloudGame
          logger={true}
          scheduleENV="test"
          gameId="NSH"
          onStart={this.onStart}
          onStop={this.onStop}
          onShutdown={this.onShutdown}
        />
    );
  }
}

窗口模式

窗口模式,需要传入容器 dom 对应的 ref

import React, { Component } from "react";
import CloudGame, { isSupport, getGameDataOf } from "leihuo-cloud-game-react";

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      connected: false,
      activeId: 0
    };

    // 容器ref
    this.containerRef = React.createRef();

    // 事件回调
    this.onStart = this.onStart.bind(this);
    this.onStop = this.onStop.bind(this);
    this.onShutdown = this.onShutdown.bind(this);
  }

  componentDidMount() {
    // 平台支持情况
    isSupport();
    // 获取游戏详细信息
    getGameDataOf("NSH");
  }

  /**
   * 开始游戏回调
   * @public
   */
  onStart(gameData) {
    // console.log("onStart", gameData);
  }

  /**
   * 手动退出游戏回调
   * @public
   */
  onStop(gameInstance) {
    window.location.reload();
  }

  /**
   * 调度退出游戏回调
   * @public
   */
  onShutdown(gameInstance) {
    window.location.reload();
  }

  render() {
    const gameVersionId = "2c49453b331a806544d0ec1ced6dc08f2703fe85";

    return (
      <div
        className={`game-container ${
          this.state.activeId === 0 ? "active" : ""
        }`}
        ref={this.containerRef}
      >
        <CloudGame
          debug={false}
          logger={false}
          scheduleENV="dailyBuild"
          urs="chenzelun@corp.netease.com~1574918819"
          gameId="NSH"
          ref={this.containerRef}
          gameVersionId={gameVersionId}
          withRecord={false}
          onStart={this.onStart}
          onStop={this.onStop}
          onShutdown={this.onShutdown}
        />
      </div>
    );
  }
}

同时打开多个实例

云游戏默认是全屏展示游戏,如果需要自定义游戏窗口大小,需要传入容器的 ref。

:warning: 关于建立 RTCPeerConnection 如果页面需要展示多个游戏实例,需要一个游戏连接完成之后(即 onConnectionStateChange 返回为状态为 connected),再进行下一个游戏的连接 ,请不要同时去连接多个游戏。因为浏览器在同时连接多个 WebRTC 时,会出现连接状态的返回状态错误的问题。可以按照下面的示例代码,进行多个游戏的连接。

:warning: 关于控制流 因为键鼠通常只有一套,所以默认的行为是:控制指令是同时发送给多个实例的,但大多的情况是控制指令只需要发给单个实例。通过动态的修改controllerEnable属性,来控制是否发送控制指令。详情可以查看下面的示例。

多实例实例代码

import React, { Component } from "react";
import CloudGame, { isSupport, getGameDataOf, resetKeys } from "leihuo-cloud-game-react";

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      connected: false,
      activeId: 0
    };

    // 容器ref
    this.containerRef = React.createRef();
    this.containerRef2 = React.createRef();

    // 事件回调
    this.onStart = this.onStart.bind(this);
    this.onStop = this.onStop.bind(this);
    this.onShutdown = this.onShutdown.bind(this);
    this.onUpdateRtcStatus = this.onUpdateRtcStatus.bind(this);
    this.onConnectionStateChange = this.onConnectionStateChange.bind(this);
  }

  componentDidMount() {
    // 平台支持情况
    isSupport();
    // 获取游戏详细信息
    getGameDataOf("NSH");
  }

  /**
   * onDataChannel回调
   * @public
   */
  onDataChannel(channel) {
    // console.log("onDataChannel", channel);
  }

  /**
   * 开始游戏回调
   * @public
   */
  onStart(gameData) {
    // console.log("onStart", gameData);
  }

  /**
   * 手动退出游戏回调
   * @public
   */
  onStop(gameInstance) {
    window.location.reload();
  }

  /**
   * 调度退出游戏回调
   * @public
   */
  onShutdown(gameInstance) {
    window.location.reload();
  }

  /**
   * rtc状态更新回调
   * @public
   */
  onUpdateRtcStatus(status) {
    // console.log(status);
  }

  /**
   * webRTC peer connection 状态变化回调
   * 当实例1的rtc连接建立之后,再连接第二个实例
   * 也就是onConnectionStateChange返回的状态为connected之后,再进行其他的实例的连接
   * 不然会出现一些控制流错误的问题
   * @public
   */
  onConnectionStateChange(state, data) {
    if (state === "connected") {
      this.setState({
        connected: true
      });
    }
  }

  /**
   * 修改active状态
   * 根据activeId,动态修改controllerEnable属性
   * 控制是否给示例控制信号
   * @public
   */
  onChangeActiveId(id) {
    this.setState({ activeId: id });
  }

  render() {
    const gameVersionId = "2c49453b331a806544d0ec1ced6dc08f2703fe85";

    return (
      <div
        style={{
          display: "flex",
          flexDirection: "column"
        }}
      >
        <div
          className={`game-container ${
            this.state.activeId === 0 ? "active" : ""
          }`}
          onMouseEnter={() => {
            resetKeys()
            this.onChangeActiveId(0)
          }}
          ref={this.containerRef}
        >
          <CloudGame
            windowNo={0}
            debug={false}
            logger={false}
            scheduleENV="dailyBuild"
            urs="chenzelun@corp.netease.com~1574918819"
            gameId="NSH"
            ref={this.containerRef}
            controllerEnable={this.state.activeId === 0}
            startWithPointerLock={false}
            gameVersionId={gameVersionId}
            startWithFullScreen={false}
            withRecord={false}
            onScheduleChange={this.onScheduleChange}
            onStart={this.onStart}
            onStop={this.onStop}
            onControllerChannel={this.onDataChannel}
            onDataStreamChannel={this.onDataChannel}
            onShutdown={this.onShutdown}
            onUpdateRtcStatus={this.onUpdateRtcStatus}
            onConnectionStateChange={this.onConnectionStateChange}
          />
        </div>

        <div
          className={`game-container ${
            this.state.activeId === 1 ? "active" : ""
          }`}
          ref={this.containerRef2}
          onMouseEnter={() => {
            resetKeys()
            this.onChangeActiveId(1)
          }}
        >
          {this.state.connected ? (
            <CloudGame
              windowNo={1}
              debug={false}
              logger={false}
              scheduleENV="dailyBuild"
              gameId="NSH"
              ref={this.containerRef2}
              controllerEnable={this.state.activeId === 1}
              startWithPointerLock={false}
              gameVersionId={gameVersionId}
              startWithFullScreen={false}
              withRecord={false}
              onScheduleChange={this.onScheduleChange}
              onStart={this.onStart}
              onStop={this.onStop}
              onControllerChannel={this.onDataChannel}
              onDataStreamChannel={this.onDataChannel}
              onShutdown={this.onShutdown}
              onUpdateRtcStatus={this.onUpdateRtcStatus}
            />
          ) : null}
        </div>
      </div>
    );
  }
}

Props

proprequiredtypedefaultoptionsdesc
refoptionobjectundefinedoutside ref窗口模式所属外层容器的 ref,外层容器需要定义尺寸和 relative
windowNooptionnumberundefinednumber窗口模式需要唯一的窗口序号(1-n)
loggeroptionboolean/string[]falsetrue/false/string[]日志,支持的配置有:session,schedule,rtc,keyboard, mouse, touch
debugoptionbooleanfalsetrue/false是否打印日志,主要包括控制日志
platformoptionobject自动判断object平台环境,默认自动判断,也可强制指定
directionoptionstring自动判断portrait/landscape移动端屏幕方向,默认自适应
gameIdrequiredstringNSHNSH/L22/D10/L10/L12/游戏 ID
gameDataoptionobjectundefinedobject游戏相关配置,一般使用默认配置,无需手动配置
serverIpoptionstringundefinedstringPC 游戏,服务器地址,默认手动选服
gameVersionIdoptionstringundefinedstring游戏版本 id,dailyBuild 环境徐配置此项
controllerEnableoptionbooleantruetrue/false是否发送控制指令,比如键鼠操作
scheduleENVoptionstringtesttest/dev/hw/dailyBuild/nw/ws_string调度环境,也可自定义指定 websocket 地址
serverENVoptionstring自动判断online/dailyBuild/url_string默认根据环境自动判断,也可自定义指定 cdn 路径
directIpoptionstringundefinedundefined也可不使用调度,与实例地址直连,直连 IP 地址
withRecordoptionbooleanfalsetrue/false是否开启录像(开发中)
backPlayoptionbooleantruetrue/false切到后台,是否仍继续游戏,或者暂停游戏
startWithFullScreenoptionbooleanfalsetrue/false点击开始游戏是否全屏
withStartButtonoptionbooleantruetrue/false是否展示开始游戏按钮,不展示默认为静音状态,需要用户修改muted
mutedoptionbooleanfalsetrue/false是否静音
holdTimeoptionnumberundefinednumber一段时间内,用户没有操作,则自动释放实例,配置此时间
minBandWidthoptionnumberundefinednumber最小带宽要求,小于此值显示提示
extendArgsoptionstringundefinedjsonstring额外参数,传给调度 socket,需要是一个 jsonString
sessionIdoptionstringundefinedstring调度 sessionId,主要是给自动化测试使用
menuTypeoptionstringundefinedbutton/default/disable菜单类型,button:界面按钮打开 default: ctrl+alt disable: 不使用
audioRecordEnableoptionbooleanfalsetrue/false是否打开声音录制,传给游戏
onScheduleoption(scheduleWs) => voidundefined(scheduleWs) => void调度 webSocket 建立是回调,可以拿到调度 ws 句柄
onScheduleChangeoption(state) => voidundefined(state) => void调度状态更新回调函数
onConnectionStateChangeoption(status) => voidundefined(status) => voidwebRTC connectionStateChange 回调
buriedPointsoptionstring[][]string[]埋点配置,埋点事件名称组成的数组
onDataChanneloption(channelObject)=> voidundefined(channelObject)=> voiddataChannel 回调,获取所有 dataChannel 状态和句柄
onControllerChanneloption(channelObject)=> voidundefined(channelObject)=> voidcontrollerChannel 回调,获取 controllerChannel 状态和句柄
onDataStreamChanneloption(channelObject)=> voidundefined(channelObject)=> voiddataStreamChannel 回调,获取 dataStreamChannel 状态和句柄
onBuriedoption(eventObject) => voidundefined(eventObject) => void埋点事件回调,iframe 发送 postMessage
onStartoption(gameData) => voidundefined(gameData) => void开始游戏回调
onStopoption(instance) => voidundefined(instance) => void手动关闭游戏回调
onShutdownoption(instance) => voidundefined(instance) => void调度退出游戏回调
onMouseDownoption(point) => voidundefined(point) => voidmouseDown 回调
onMouseMoveoption(point) => voidundefined(point) => voidmouseMove 回调
onMouseUpoption(point) => voidundefined(point) => voidmouseUp 回调
onTouchStartoption(point) => voidundefined(point) => voidtouchStart 回调
onTouchMoveoption(point) => voidundefined(point) => voidtouchMove 回调
onTouchEndoption(point) => voidundefined(point) => voidtouchEnd 回调
onVolumeChangeoption(number) => voidundefined(number) => void修改音量回调

游戏事件埋点

目前只有 L12 支持埋点,具体的埋点事件有:

事件描述
get_in进入游戏选服界面(网页上开始记录倒计时)
choose_role选择角色
choose_hair_color选择发色
enter_name输入玩家姓名
arrange_suite进入家园摆放家具
stay_time进入游戏之后到最后退出停留总时间
playing进入关卡,玩家正式开始打(全血)
kill_one玩家杀掉 1 个小兵
kill_two玩家杀掉 2 个小兵
kill_three玩家杀掉 3 个小兵
kill_four玩家杀掉 4 个小兵
kill_five玩家杀掉 5 个小兵
health_70pct玩家血量掉至 70%
health_50pct玩家血量掉至 50%
health_30pct玩家血量掉至 30%
health_10pct玩家血量掉至 10%
kill_hantang玩家杀掉韩棠
win_los玩家胜利/失败

Methods

isSupport 是否支持云游戏

getGameDataOf 获取游戏详细信息

获取调度 host 地址 getScheduleHostOf

获取 RTC 信令交换代理地址 getRTCApiOf

多实例切换实例前清空键盘 resetKeys

使用:

import CloudGame, {
  isSupport,
  getGameDataOf,
  getScheduleHostOf,
  getRTCApiOf,
  resetKeys
} from "cloud-game-react";

// 支持情况
isSupport();

// 获取游戏配置
getGameDataOf("NSH");

// 获取调度地址
getScheduleHostOf("test");

// 获取接口地址
getApiHostOf("test");

// 多实例清空键盘
resetKeys();

调度

接口文档: https://confluence.leihuo.netease.com/pages/viewpage.action?pageId=24009410 主要流程: 调度

键鼠协议

二报文格式进制格式统一为大端序, 偏移均为字节序 具体协议内容,请查看看键鼠协议

注意: 一些键是被接受端屏蔽的,比如 window 键或者一些系统快捷键。

手柄协议

二报文格式进制格式统一为大端序, 偏移均为字节序 具体协议内容,请查看手柄协议

注意: 传输前,需先发手柄链接信号。

手游触控协议

二报文格式进制格式统一为大端序, 偏移均为字节序 具体协议内容,请查看触控协议

注意: 目前暂最多支持 5 个触控点,触控点对应 id 固定为 0~4,一定注意不要使用系统返回的 touch id。

埋点流程

主要流程: 调度

Contributing

仓库地址 https://git-wz.nie.netease.com/hzheyuan/cloudgame-component-of-react

node && npm node >= 8.0 npm >= 5.0

  1. 根目录 npm install
  2. 根目录 npm start start
  3. example 目录 npm install
  4. 如果使用 npm 执行:npm link leihuo-cloud-game-react 否则忽略此步骤
  5. example 目录 npm run start
  6. 跟新版本:npm run release
  7. changelog 为标准写法
注意: 请按照规程填写 commit!,详情

issues

  1. 反馈收集的问题
  2. 游戏启动本地输入法进行输入(pc 与手游不同)
  3. 默认操作:打开链接,复制按钮,上传文件
  4. 可配置的快捷键,解决(系统,浏览器)快捷键与游戏快捷键冲突
  5. ice 打洞
  6. 手柄非游戏操作(移动网页元素,点击按钮等)
  7. 配套日志 sdk 和管理插件

License

MIT ©