阅读(228) (8)

字节跳动小游戏

2020-02-13 16:13:45 更新

字节跳动小游戏是一种开放能力。允许用户基于给定的 API 编写游戏代码,最终生成可运行在接入小游戏功能的各产品 APP 上。


快速上手

安装开发工具

前往开发者工具下载页面 ,根据自己的操作系统下载对应的安装包进行安装。

文件结构

.
├── game.js               =>  小游戏入口文件
├── game.json             =>  小游戏配置文件
└── project.config.json   =>  工程配置文件

以上三个文件为小游戏的三个必要文件,开发者如有其它资源可以在根目录下自由建立 js, audio, images 等目录,规范自己的开发文件。

配置

game.json 示例

{
  "deviceOrientation": "portrait",
}

deviceOrientation

说明
portrait 竖屏
landscape 横屏

project.config.json 示例

{
    "description": "项目描述",
    "setting": {
        "es6": true,   // 声明使用的 js 语法版本
    }
}


平台能力

tt API

本平台只能使用 JavaScript 来编写小游戏。小游戏的运行环境是一个 绑定了一些方法的 JavaScript VM。不同于浏览器,这个运行环境没有 BOM 和 DOM API,只有 tt系列 API。接下来我们将介绍如何用 tt API 来完成创建画布、绘制图形、显示图片以及响应用户交互等基础功能。

创建 Canvas

var canvas = tt.createCanvas();

通过调用 tt.createCanvas() 接口,可以创建一个 Canvas 对象。用户第一次调用时, 获取到的是一个上屏 Canvas,该 Canvas 已经显示在了屏幕上,且与屏幕等宽等高。小游戏运行期间,有且仅有一个上屏 Canvas。

绘制

var context = canvas.getContext("2d");
context.fillStyle = "#ff00ff";
context.fillRect(0, 0, 100, 100);

触摸事件

平台提供了一系列监听触摸事件的 API:

动画能力

开发者可以利用定时器相关 API 实现动画效果,如下

全局对象

小游戏的运行环境不同于 Web 环境,在真机上运行时,没有BOM API,因此也就没有 window 对象以及其上面的各种属性。所以,从 H5 迁移过来的游戏,开发者需要自己实现 window 对象的兼容(如果是利用游戏引擎开发的小游戏,导出的小游戏版本一般已经包含了一份 adapter,适配了 window 对象)。同时,在小游戏的运行环境中,提供了全局对象 GameGlobal,所有全局定义的变量都是 GameGlobal 的属性。如:

setTimeout === GameGlobal.setTimeout; // true
requestAnimationFrame === GameGlobal.requestAnimationFrame; // true

同时,GameGlobal 是一个全局对象,也是一个循环引用的对象。

GameGlobal.GameGlobal === GameGlobal


关系链数据使用

为了丰富游戏的社交、对战玩法,目前在字节跳动平台上,对于部分宿主 APP(如抖音),我们为小游戏提供了获取关系链数据的 API:

该接口返回的数据结构可参考 API 文档。除此之外,我们还提供了配套的操作用户数据的一系列 API:

开放数据域

为了让开发者安全使用平台的关系数据,我们提供了一个名为开放数据域的环境。这是一个封闭、独立的 JavaScript 作用域。通过在 game.json 中添加配置项 openDataContext 指定开放数据域的代码目录,来开启该项功能,以便使用对应的关系链数据接口,同时,在使用这一功能时,也会有一些限制。

{
  "deviceOrientation": "portrait",
  "openDataContext": "src/myOpenDataContext"
}

对应的代码目录应该如下:

├── src
|   └── myOpenDataContext
|       ├── index.js
|       └── ...
├── game.js
├── game.json
└── ...

index.js 作为开放数据域的入口文件是必需的,平台构建工具会将开放数据目录下的文件自动打包为一个独立文件,其代码运行在开放数据域。而 game.js 其代码运行在主域。

注意:

  • 主域和开放数据域中的代码不能相互 require。

主域和开放数据域的通信

开放数据域不能向主域发送消息。

主域可以向开放数据域发送消息。调用 tt.getOpenDataContext() 方法可以获取开放数据域实例,调用实例上的 OpenDataContext.postMessage() 方法可以向开放数据域发送消息。

// game.js
const openDataContext = tt.getOpenDataContext();
openDataContext.postMessage({
  text: "This is a test."
});

在开放数据域中通过 tt.onMessage() 方法可以监听从主域发来的消息

// src/myOpenDataContext/index.js
tt.onMessage(data => {
  console.log(data);
  /* {
    text: 'This is a test.',
  } */
});

如何使用关系链数据

通过关系链 API 获取到的用户数据,在绘制排行榜等业务场景下如果想要展示,需要将排行榜绘制到 sharedCanvas 上,再在主域将 sharedCanvas 渲染上屏。可参考以下示例代码:

  1. sharedCanvas 是主域和开放数据域都可以访问的一个离屏画布。在开放数据域调用 tt.getSharedCanvas() 将返回 sharedCanvas。根据业务逻辑获取关系链数据,然后绘制到 sharedCanvas 上。
    //  src/myOpenDataContext/index.jsconst sharedCanvas = tt.getSharedCanvas();
    const context = sharedCanvas.getContext("2d");
    
    function drawRankList(data) {
      data.forEach((item, index) => {
        // ...
        context.fillStyle = "red";
        context.fillRect(0, 0, 100, 100);
      });
    }
    
    tt.getCloudStorageByRelation({
      success: res => {
        const data = res.data;
        drawRankList(data);
      }
    });
  2. 在主域中可以通过开放数据域实例访问 sharedCanvas,通过 drawImage() 方法可以将 sharedCanvas 绘制到上屏画布。
    // game.jsconst openDataContext = tt.getOpenDataContext();
    const sharedCanvas = openDataContext.canvas;
    
    const canvas = tt.createCanvas();
    const context = canvas.getContext("2d");
    context.drawImage(sharedCanvas, 0, 0);
    sharedCanvas 的宽高只能在主域设置,不能在开放数据域中设置。本质上其也是一个离屏 Canvas,而重设 Canvas 的宽高会清空 Canvas 上的内容。所以可以通过 postMessage 通知开放数据域去重绘 sharedCanvas 。 
    // game.jssharedCanvas.width = 400;
    sharedCanvas.height = 200;
    
    openDataContext.postMessage({
      command: "render"
    });
    // src/myOpenDataContext/index.js
    openDataContext.onMessage(data => {
      if (data.command === "render") {
        // ... 重绘 sharedCanvas
      }
    });

运行时限制

主域

  1. sharedCanvas 只能被绘制到上屏 canvas 上。
  2. 上屏 canvas 不能调用 toDataURL,其 context 不能调用 getImageData、readPixels。
  3. sharedCanvas 不能调用 toDataURL 和 getContext。
  4. 不能将上屏 canvas 和 sharedCanvas 以任意形式绘制到其他 canvas 上,包括 drawImage、createPattern、texImage2D、texSubImage2D。
  5. sharedCanvas 的宽高只能在主域设置

开放数据域

  1. 不能设置 sharedCanvas 的宽高
  2. 开放数据域的 Image 只能使用本地或者是通过 tt.xx 系列 API 拿到的平台本身的用户头像图片,不能使用开发者自己服务器上的图片。对于非本地或非用户头像图片,可以先从主域 tt.downloadFile() 下载图片文件,再通过 OpenDataContext.postMessage() 把文件路径传给开放数据域去使用。

开放数据域只能调用有限的 API,如下所示:

  • 所有定时器相关 API
  • 所有触摸事件 API
  • tt.createCanvas()
  • tt.createImage()
  • tt.getUserCloudStorage()
  • tt.setUserCloudStorage()
  • tt.removeUserCloudStorage()
  • tt.onMessage()


开放能力

平台允许开发者可以利用一些产品宿主提供的如登录,分享,以及不久的未来支持的支付,广告等一系列开放能力,用以完善自己的产品逻辑和体验。具体可以参考开放能力一栏。


快速调试


其他说明

代码包限制

通常情况下,每个小游戏允许上传的代码包总大小为 4MB,请开发者注意自己的游戏包大小。

文件类型

小游戏限制了可以上传的文件类型。只有在以下列表中的文件可以上传成功:

  • png
  • jpg
  • jpeg
  • gif
  • svg
  • json
  • js
  • cer
  • obj
  • dae
  • fbx
  • mtl
  • stl
  • 3ds
  • mp3
  • pvr
  • wav
  • plist
  • ttf
  • fnt
  • gz
  • ccz
  • m4a
  • mp4
  • bmp
  • atlas
  • swf
  • ani
  • part
  • proto
  • bin
  • sk
  • mipmaps
  • txt
  • zip
  • tt
  • map
  • ogg
  • silk
  • dbbin
  • dbmv
  • etc
  • lmat
  • lm
  • ls
  • lh
  • lani
  • lav
  • lsani
  • ltc