姓名:Javen

Email:javendev@126.com

Github:https://github.com/Javen205

Gitee:https://gitee.com/Javen205

CSDN:https://blog.csdn.net/zywjava

特长:擅长聚合支付、QQ玩一玩

开源项目:IJPay、weixinguide作者

0、体验QQ轻游戏

  • 需要使用Android手机

  • 登录手Q开启厘米秀

  • 侧滑点击人物形象或者选择任意一好友点击「+」滑拔一下找到「厘米秀」

搜索厘米秀 申请体验资格 开启厘米秀
侧滑 好友点「+」或者直接点击人物 游戏入口页

1、平台申请账号

注册很简单,使用已有Q号登录「厘米游戏」开放平台按照流程提交资料审核即可 。开发者接入官方说明文档

「厘米游戏」 开放平台注册提交资料的同时会注册一个相关联的「QQ服务号」。游戏中显示的用户信息是通过后台静默授权「QQ服务号」后再通过用户相关的接口获得,这点与微信公众号以及微信小游戏类似。

一句话概括:目前暂未对个人开放,现阶段为邀请码模式。但如果你有好的IP资源或者优秀开发团队是比较好申请的。

「微信小游戏」 做比较目前来看最大的优势就是

  • 现阶段游戏中集成广告所得广告费用平台不分成

  • 游戏评级高官方可以让游戏上中心化首页推荐位

上线游戏都需要 「游戏自审自查报告」「计算机软件著作权登记证书」,如需内购需要提供 「广电总局版号批文」 以及 「文化部备案信息」

2、环境搭建

QQ玩一玩(轻游戏)开发环境搭建与调试

如果使用了第三方引擎 Mac电脑非必须。

3、第三方引擎推荐

第三方引擎的实现方式为基于 brickswebGL 接口进行封装,具有较高的灵活性,但渲染性能会欠缺。 如开发者对性能要求更高,推荐使用bricks引擎的原生渲染

注意: iOS 在手 Q 770 版本禁用了 webGL,会导致界面卡在 99% 加载界面,开发者忽略 iOS 端表现,关注安卓端表现。

  • Cocos Creator 开发玩一玩说明文档

  • Egret Engine 开发玩一玩说明文档

  • LayaAir 引擎开发玩一玩说明文档

关于使用什么引擎来开发「轻游戏」或者「H5游戏」都有各自的说法。就像大家讨论Java是世界最好的语言一样。

世界上没有不出bug的程序,引擎或者IDE都或多或少存在一定的Bug以及局限性。请根据项目需求以及当下的环境酌情选择。

  • 从现在的技术发展讨论egret和cocos的优缺点H5方面

  • 小程序游戏选择 egret, cocos Creator 还是 layabox?

  • 开发H5游戏引擎的选择:Egret或Laya?

本文示例使用的游戏引擎为Cocos Creator

4、QQ轻游戏常用功能介绍

4.1 获取用户信息
4.1.1 获取游戏全局变量

游戏启动后,引擎会为开发者写入名为 GameStatusInfo的有关游戏的全局参数(类似于H5中windows对象),从中可获取有关用户标识符(openId)、游戏标识(gameId)、机型等参数。

详细参数对照表请移步至 官方参考文档-登录与鉴权

示例参考-- 获取手Q版本跳转其他游戏

if (cc.sys.platform != cc.sys.QQ_PLAY) {    self.setTipMsg("请在QQ玩一玩环境下测试");   return;
}
if (BKTools.versionCompare(GameStatusInfo.QQVer, "7.7.0.0")) {    BKTools.skipGame("2731");
} else {    self.setTipMsg("手Q版本过低,请更新");
}

如何跳转其他游戏完整的代码后面会提到

4.1.2获取用户昵称
function getNick(callback) { BK.MQQ.Account.getNick(GameStatusInfo.openId, callback);
}
BKTools.getNick(function(openId, nick) {    Global.nickName = nick;
});
4.1.3 获取用户图像
getHead() { let self = this;   let absolutePath = "GameSandBox://_head/" + GameStatusInfo.openId + ".jpg";  let isExit = BK.FileUtil.isFileExist(absolutePath);    cc.log(absolutePath + " is exit :" + isExit);   //如果指定目录中存在此图像就直接显示否则从网络获取  if (isExit) {   cc.loader.load(absolutePath, function (err, texture) {  if (err == null) {    self.head.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(texture);   }   }); } else {    BK.MQQ.Account.getHeadEx(GameStatusInfo.openId, function (oId, imgPath) {   cc.log("openId:" + oId + " imgPath:" + imgPath); var image = new Image();   image.onload = function () {   var tex = new cc.Texture2D();  tex.initWithElement(image); tex.handleLoadedTexture();  self.head.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(tex);   }   image.src = imgPath;   }); }   },  // onLoad () {},    btn(event, data) {  cc.log("点击了按钮");  if (cc.sys.platform == cc.sys.QQ_PLAY) {  this.getHead(); } else {    cc.log("请在QQ玩一玩平台中测试");   }   },
4.2 分享与邀请

QQ轻游戏分享方法比较多具体实现方式可以官方的分享相关文档。这里介绍常用的一种方式 多渠道分享

/** * 获取分享信息    * @param {String} localPicPath     */
function getShareInfo(localPicPath) {   if (!localPicPath) {    localPicPath = "GameRes://qrcode.png";//游戏资源包根目录存放图片qrcode.png   }   let summarys = ["文案1", "游戏太好玩了,玩得停不下来!", "游戏太刺激了,邀请还能领抱枕!", "文案2"];  let shareInfo = {  summary: summarys[getRandomInt(0, 3)],  picUrl: "http://h.hiphotos.baidu.com/image/pic/item/18d8bc3eb13533fa4dd573ada3d3fd1f40345bd6.jpg", //支持HTTPS  extendInfo: Global.openId,//或者使用GameStatusInfo.openId   localPicPath: localPicPath, //分享至空间、微信、朋友圈时需要的图。(选填,若无该字段,系统使用游戏对应的二维码) };  return shareInfo;
}
/** * 分享    * @param {*} shareInfo     * @param {*} callback  */
function toShare(shareInfo, callback) { if (cc.sys.platform == cc.sys.QQ_PLAY) {  BK.QQ.share(shareInfo, function (retCode, shareDest, isFirstShare) {    log("分享结果 retCode:" + retCode + " shareDest:" + shareDest + " isFirstShare:" + isFirstShare);    if (retCode == 0) {   if (callback) { callback(0);    }   if (shareDest == 0) { //聊天窗   log("成功分享至QQ");   } else if (shareDest == 1) {  //空间    log("成功分享至空间");   } else if (shareDest == 2) {  //微信    log("成功分享至微信");   } else if (shareDest == 3) {  // 朋友圈  log("成功分享至朋友圈");  }   } else if (retCode == 1) {    if (callback) { callback(-1);   }   log("分享失败" + retCode);   } else if (retCode == 2) {    if (callback) { callback(-1);   }   log("分享失败,用户取消分享:" + retCode); }   }); } else {    if (callback) { callback(0);    }   }
}

但这里有一个问题 点击右上角的「…」选择分享游戏,分享后图片不显示再次调用接口来实现分享时无任何影响 ,要想解决此问题自需要实现生命周期监听并实现 onShare 方法

关于QQ玩一玩的默认分享问题

4.3 生命周期
/**   * 游戏事件以及生命周期    */
function addGameEvent() {   new BK.Game({   //游戏启动后 onLoad: function (app) {    log("BK.Game.onLoad");    },  //进入点击最大化后  onMaximize: function (app) {    log("BK.Game.onMaxmize"); },  //进入点击最小化后  onMinimize: function (app) {    log("BK.Game.onMinmize"); },  //进入后台后响应   onEnterBackground: function (app) { log("BK.Game.onEnterbackground"); },  //回到前台后响应   onEnterForeground: function (app) { log("BK.Game.onEnterforeground"); },  //点击“分享游戏”后响应。(可选)    onShare: function (app) {   log("BK.Game.onShare");   return getShareInfo();  },  //分享成功  onShareComplete: function (app, retCode, shareDest, isFirstShare) { log("BK.Game.onShareComplete retCode:" + retCode + " shareDest:" + shareDest + " isFirstShare:" + isFirstShare); },  //进入点击关闭响应  onClose: function (app) {   log("BK.Game.onClose");   },  //网络环境切换事件  onNetworkChange: function (app, state) {    log("BK.Game.onNetworkChange:STATE :" + state);  },  //全局异常监听    onException: function () {  log("BK.Game.onException msg:" + this.errorMessage() + " ,stack:" + this.errorStacktace());  }   });
}
4.4 支付与红包

支付接入比较简单,目前没有异步通知给开发者的接口,所有的逻辑都由玩一玩后台处理。支付接入步骤

  • 平台上传道具资源(图片、描述、单价等)

  • 道具申请上架

  • 游戏内通过接口获取道具信息(道具ID、名称、图片等)

  • 通过道具ID列表购买道具

具体流程实现参考官方文档-支付

据内部消息 发送B2C红 在今年国庆假期间将有一批轻游戏试水,有什么样的创意和玩法可以期待一下。红包总金额最低5W最高20W。

5、网络通讯

原生引擎开发指引 中可以了解到。网络方案可以使用原生引擎、或者三方引擎进行界面以及逻辑的搭建。

官方文档-网络功能

下面我会介绍

  • BK.HttpUtil:用于短连接

  • XMLHttpRequest:用于短连接

  • WebSocket:用于长连接

http get/post请求

BK.HttpUtil

function BKGet(url, callback, custom) {  let httpUtil = new BK.HttpUtil(url);   httpUtil.setHttpMethod("get");    httpUtil.custom = custom;  //绑定回调对象    httpUtil.requestAsync(callback.bind(httpUtil));
}

如果是POST请求,将 httpUtil.setHttpMethod("get");设置为 httpUtil.setHttpMethod("post");

//下载图片并保存在手机中
BKTools.BKGet("http://h.hiphotos.baidu.com/image/pic/item/18d8bc3eb13533fa4dd573ada3d3fd1f40345bd6.jpg", function (res, code) {   cc.log("结果:" + code + " 渗透参数:" + this.custom);   BK.FileUtil.writeBufferToFile("GameSandBox://test/test.jpg", res);
}, "custom");
//普通的get请求
BKTools.BKGet("http://www.wanandroid.com/tools/mockapi/3461/Javen", function (res, code) {
cc.log("结果:" + code + " 渗透参数:" + this.custom);
if (code == 200) {    let str = res.readAsString();  cc.log(str);    let data = JSON.parse(str);    if (data.code == 0) { self.setTipMsg("网络请求结果 Gitee:" + data.data.name);    } else {    self.setTipMsg("网络请求异常:" + data.msg);    }
}
}, "请求返回字符串");

XMLHttpRequest

/**   * post 请求   * @param {*} url   * @param {*} data  * @param {*} callBack  */
function post(url, data, callBack) {    log("请求参数:" + data); var xhr = new XMLHttpRequest();    xhr.onreadystatechange = function () { let status = xhr.status;   if (xhr.readyState == 4 && status == 200) { var responseBody = xhr.responseText;   log("响应的结果:" + responseBody); callBack(status, JSON.parse(responseBody)); }   };  xhr.open("POST", url, true);  xhr.send(data);
}
/** * get请求 * @param {*} url   * @param {*} data  * @param {*} callBack  */
function get(url, data, callBack) { log("请求参数:" + data); var xhr = new XMLHttpRequest();    xhr.onreadystatechange = function () { let status = xhr.status;   if (xhr.readyState == 4 && status == 200) { var responseBody = xhr.responseText;   log("响应的结果:" + responseBody); callBack(status, JSON.parse(responseBody)); }   };  xhr.open("GET", url + "?" + encodeURIComponent(data), true);  xhr.send();
}
webSocket请求

如果是QQ玩一玩平台就是使用 BK.WebSocket,其他平台使用 标准的 WebSocket

//Script/common/WebSocket.js
/** * @author Javen    * @copyright 2018-09-22 17:32:21 javendev@126.com     * @description webSocket工具组件   */
let Global = require("Global");
let BKTools = require("BKTools");
let WS_TYPE = cc.Enum({    BK_WS: 1,   WEB_WS: 2,
});
cc.Class({  extends: cc.Component,  // properties: {    // },   // onLoad () {},    start() {   // this.schedule(function () {  //     if (this.hasConnected) { //     }    // }, 5);   },  initWebSocket() {   if (cc.sys.platform == cc.sys.QQ_PLAY) {  this._ws = new BK.WebSocket("ws://" + Global.WEB_SOCKET.URL);   this._wsType = WS_TYPE.BK_WS;  } else {    this._ws = new WebSocket("ws://" + Global.WEB_SOCKET.URL);  this._wsType = WS_TYPE.WEB_WS; }   this.addEventListener(this._ws);    },  addEventListener(ws) {  let self = this;   ws.onopen = function (event) { self._isConnected = true;  BKTools.log("onopen....");    };  ws.onerror = function (event) {    self._isConnected = false; BKTools.log("onerror....");   };  ws.onclose = function (event) {    self._isConnected = false; BKTools.log("onclose....");   };  if (self._wsType == WS_TYPE.BK_WS) {  ws.onMessage = function (ws, event) {  if (event.isBinary) {   let buf = event.data;  //将游标pointer重置为0    buf.rewind();   let ab = new ArrayBuffer(buf.length);  let dv = new DataView(ab); while (!buf.eof) {  dv.setUint8(buf.pointer, buf.readUint8Buffer());    }   self.toHander(ab);  } else {    BKTools.log("BK.WebSocket data type is not binary");  }   }   } else {    ws.onmessage = function (event) {  if (event.data instanceof Blob) {   let blob = event.data; var reader = new FileReader(); reader.readAsArrayBuffer(blob); reader.onload = function (e) { if (e.target.readyState == FileReader.DONE) { let result = reader.result;    self.toHander(result);  }   }   } else {    BKTools.log("webSocket data type is not blob");   }   };  }   },  hasConnected() {    return this._isConnected;   },  toHander(buffer) {  let self = this;   let cmd = proto.UserCmdOutComonProto.deserializeBinary(buffer);    switch (cmd.getId()) {  case proto.UserCmdOutType.RECONNECTION_RESULT:  BKTools.log("重连结果....");  break;  case proto.UserCmdOutType.USER_CONNECT_SUCCESS: BKTools.log("客户端连接成功....");   break;  case proto.UserCmdOutType.USER_LOGIN_SUCCESS:   BKTools.log("反馈登录消息开始...");   break;  case proto.UserCmdOutType.USER_LOGIN_SUCCESS_OVER:  BKTools.log("反馈登录消息结束....");  let loginOver = proto.PlayerLoginOverProtoOut.deserializeBinary(buffer);   //回调给请求页    Global.loginResponse(loginOver);    break;  default:    break;  }   },  send(bytes) {   this._ws.send(bytes);   },  /** * 登录    */  toLogin() { if (!this.hasConnected()) { this.initWebSocket();   return; }   let login = new proto.UserLoginProto();    login.setId(proto.UserCmdInType.USER_LOGIN);    login.setToken(Global.WEB_SOCKET.TOKEN);    this.send(login.serializeBinary()); },  // update (dt) {},
});

如何使用?

将webSocket工具组件绑定到常驻节点,在通过 cc.find查找常驻节点上的 WebSocket组件

this._webSocket = cc.find("常驻节点名称").getComponent("WebSocket");
//调用封装的接口
this._webSocket.toLogin();

6、跳转到其他游戏

跳转到其他游戏手Q 7.7.0 及以上才支持

/**   * 判断手Q版本    * @param {String} ver1 7.1.1.1 * @param {String} ver2 6.3.3.3 */
function versionCompare(ver1, ver2) {   ver1 = parseInt(ver1.replace(/\./g, ""));    ver2 = parseInt(ver2.replace(/\./g, ""));    if (ver1 >= ver2) { return true;    } else {    return false;   }
}
/**    * 跳转到其他游戏   * @param {Number} gameId   */
function skipGame(gameId) { BK.QQ.skipGame(gameId, "扩展参数");//游戏启动时可以通过GameStatusInfo.gameParam获取
}

7、成绩上报与排行榜

官方文档-成绩上报与排行榜

最新版本接口示例 胜局积累-大到小

/**   * 成绩上报  * @param {*} isWin     * @param {*} callback  */
function uploadScore(isWin, callback) { if (cc.sys.platform != cc.sys.QQ_PLAY) {   if (callback) { callback(-1, "此接口只支持QQ玩一玩平台");    }   return; }   if (!isWin) {   isWin = 0; } else {    isWin = 1; }   var data = {   userData: [{    openId: GameStatusInfo.openId,  startMs: Global.startGameTime.toString(),   endMs: ((new Date()).getTime()).toString(), scoreInfo: {    score: isWin,   },  }, ],   attr: { score: {    type: 'rank', order: 3,   }   },  };  BK.QQ.uploadScoreWithoutRoom(1, data, function (errCode, cmd, data) {   log("uploadScoreWithoutRoom callback  cmd" + cmd + " errCode:" + errCode + "  data:" + JSON.stringify(data));    if (callback) { callback(errCode, data);    }   }); }   /** * 拉取排行榜数据   * @param {*} callback  */  function getRankList(callback) {    if (cc.sys.platform != cc.sys.QQ_PLAY) {   if (callback) { callback(-1, "此接口只支持QQ玩一玩平台");    }   return; }   let attr = "score";  let order = 3; let rankType = 0;  BK.QQ.getRankListWithoutRoom(attr, order, rankType, function (errCode, cmd, data) { log("getRankListWithoutRoom callback  cmd" + cmd + " errCode:" + errCode);   if (errCode != 0) {    callback(errCode);  return; }   if (data) { let rankList = data.data.ranking_list; log("data not null " + rankList.length); log(JSON.stringify(data));  // rankList.forEach(element => {    //   log("....华丽的分割线....");   //   log("score:" + element.score);  //   log("nick:" + element.nick);    //   log("....华丽的分割线....");   // });  if (callback) { callback(errCode, rankList);    }   }   }); }

8、关注公众号

查询是否关注公众号

function checkPubAccountState(){
BK.QQ.checkPubAccountState(Global.PUIN ,function(errCode, cmd, data) {  BK.Script.log(0,0," callback errCode = "+errCode+ " cmd = "+ cmd + " data = "+ data); if(data.is_follow == 1){  return true;    }else{  return false;   }   });
}

进入公众号主页

/** * 关注公众号 */
function follow() { if (cc.sys.platform == cc.sys.QQ_PLAY) {  BK.QQ.enterPubAccountCard(Global.PUIN); }
}

如何获取 PUIN ?请移步至官方-公众号

9、广告

详细介绍请移步至官网-广告接入流程

简单的封装与使用

/**   * 加载视频广告    */
function fetchVideoAd(videoType) {  if (!videoType) {   videoType = 0; }   log("开始加载视频广告..." + videoType);  BK.Advertisement.fetchVideoAd(videoType, function (retCode, msg, handle) {  log("retCode:" + retCode + " msg:" + msg);   //返回码0表示成功  if (retCode == 0) {   Global.videoHandle = handle;   //广告监听在业务逻辑中处理  } else {    log("拉取视频广告失败error:" + retCode + " msg:" + msg); }   }.bind(this));  log("加载了视频广告...");
}
/** * 加载条幅广告    */
function fetchBannerAd() {  BK.Advertisement.fetchBannerAd(function (retCode, msg, bannerHandle) {  log("retCode:" + retCode + " msg:" + msg);   if (retCode == 0) {   Global.bannerHandle = bannerHandle;    bannerHandle.onClickContent(function () {   log("用户点击了落地页");  }); bannerHandle.onClickClose(function () { log("用户点击了X关闭广告");    }); } else {    log("fetchBannerAd failed. retCode:" + retCode); }   }.bind(this));
}
function closeBannerAd() {  log("关闭广告....");  if (Global.bannerHandle) {  Global.bannerHandle.close();    Global.bannerHandle = undefined;   }
}
function loadBannerAd() {   if (cc.sys.platform == cc.sys.QQ_PLAY) {  log("预加载Banner"); fetchBannerAd();    }
}
function loadVideoAd() {    if (cc.sys.platform == cc.sys.QQ_PLAY) {  log("预加载Video");  fetchVideoAd(); }
}
/**    * @author Javen    * @copyright 2018-09-26 15:53:52 javendev@126.com     * @description 广告测试    */
let BKTools = require("BKTools");
var Global = require("Global");
cc.Class({  extends: cc.Component,  properties: {   },  // onLoad () {},    btnClick(event, data) { BKTools.log("点击了>" + data);   if (data == 'loadVideo') {  //如果需要判断是否加载成功可以在封装的函数中添加回调 BKTools.loadVideoAd();  } else if (data == 'showVideo') {   if (Global.videoHandle) {   this.jumpVideoAd(); } else {    BKTools.log("无视频广告句柄");   BKTools.loadVideoAd();  }   } else if (data == 'loadBanner') {  BKTools.loadBannerAd(); } else if (data == 'showBanner') {  if (Global.bannerHandle) {  this.showBannerAd();    } else {    BKTools.log("无条幅广告句柄");   BKTools.loadBannerAd(); }   } else if (data == 'closeBanner') { BKTools.closeBannerAd();    } else if (data == 'back') {    cc.director.loadScene("welcome"); }   },  jumpVideoAd() { let self = this;   Global.videoHandle.jump();  Global.videoHandle.setEventCallack( function (code, msg) {}.bind(this), //关闭游戏(不再使用不需要监听)     function (code, msg) {  if (code == 0) {  BKTools.log("达到看广告时长要求,可以下发奖励 endVide code:" + code + " msg:" + msg); //达到看广告时长要求,可以下发奖励   } else {    BKTools.log("其他异常,比如播放视频是程序返回到后台");   }   }.bind(this),   function (code, msg) {  BKTools.log("关闭视频webview endVide code:" + code + " msg:" + msg); //关闭视频webview   }.bind(this),   function (code, msg) {  BKTools.log("开始播放视频 startVide code:" + code + " msg:" + msg); //开始播放视频   }.bind(this));  },  showBannerAd() {    Global.bannerHandle.show(function (succCode, msg, handle) { if (succCode == 0) {  BKTools.log("banner展示成功 home");   } else {    BKTools.log("banner展示失败home msg:" + msg);    }   }); },  start() {   },  // update (dt) {},
});

10、源码

文中涉及到的代码以及案例已上传至 Gitee-Brickengine_Guide

到这里就介绍完了,个人能力有限如有错误欢迎指正如有遗漏欢迎补充。如有疑问欢迎留言一起交流讨论。


欢迎关注「奎特尔星球」微信公众号,欢迎投稿分享你的经验!

「奎特尔星球」微信公众号

「奎特尔星球」博客网站,建设中...

QQ玩一玩(轻游戏)入门到放弃?相关推荐

  1. @aspect注解_Spring自定义注解玩法大全,从入门到放弃

    在业务开发过程中我们会遇到形形色色的注解,但是框架自有的注解并不是总能满足复杂的业务需求,我们可以自定义注解来满足我们的需求. 根据注解使用的位置,文章将分成字段注解.方法.类注解来介绍自定义注解. ...

  2. android qq 进程保活,Android保活从入门到放弃:乖乖引导用户加白名单吧(附7大机型加白示例)...

    1.引言 IM在Android上的保活问题经常在即时通讯网的论坛和技术群里被讨论,自从Android 8.0后系统大大降低了后台运行应用的保活容忍度(详见<Android P正式版即将到来:后台 ...

  3. Egret QQ玩一玩适配【踩坑日记】

    需要申明一点,这是我接过最坑的渠道了,各种神奇的问题,首先是接口比较奇怪而且新旧版本搞得很混乱,其次是平台底层实现性能差而且很多限制.此外,这里需要理清楚一个概念:QQ 玩一玩 和 QQ 玩吧 并非同 ...

  4. LayaBox 接入QQ玩一玩 轻游戏流程

    最近尝试LayaBox 接入QQ玩一玩,遇到一些坑,跟大家分享一下 1.QQ文档 官方文档地址:https://hudong.qq.com/docs/access/index.html 官方提供两个D ...

  5. QQ玩一玩(轻游戏)开发环境搭建与调试

    玩一玩开发环境搭建与调试 前言 Android 调试 下载Android Studio 配置环境变量 进入用户当前目录 设置环境变量 设置生效 检查配置是否正常 下载特殊版测试Q 调试时Android ...

  6. Cocos Creator 开发QQ玩一玩入门到放弃?

    Cocos Creator 开发QQ玩一玩入门到放弃? 文章目录 Cocos Creator 开发QQ玩一玩入门到放弃? 1.环境搭建 1.1 开发工具准备 1.1.2 官方站点 1.1.3 编辑器使 ...

  7. 白鹭引擎开发QQ玩一玩轻游戏之Windows配置开发环境

    准备工作: 1.了解玩一玩   https://hudong.qq.com/  (简单一句话:基于手机QQ内置的一款游戏引擎开发手游的环境) 2.需要下载的软件 本文介绍用白鹭开发游戏 再转换成玩一玩 ...

  8. 玩转QQ玩一玩分享,让游戏增加新的活力

    玩转QQ玩一玩分享,让游戏增加新的活力 邀请好友功能怎么做? 个人性化分享怎么做?分享是否成功如何判断? 分享后的渠道如何判断? 耐心看完会给你一个答案 文章目录 1.相关参考链接 2.分享使用场景 ...

  9. Steam高赞游戏入门机器学习!不写代码,人人可玩,又能吸猫,汉化版已推出...

    栗子 乾明 发自 凹非寺  量子位 报道 | 公众号 QbitAI 撸猫.咖啡,玩游戏. 但我其实是在入门机器学习. 2019年最简单有趣的入门方式,就在这里: Steam高赞游戏,极度易上手. 现在 ...

最新文章

  1. 今晚8点直播 | 美团是怎么玩儿AI的?大牛揭秘美团超大规模数据集——美团大脑
  2. “5G 消息”APP 短暂上线,它会干掉微信还是变成另一个飞信?
  3. python 合并排序的数组
  4. Java的新项目学成在线笔记-day10(一)
  5. 4月全球域名商域名解析量23强:西数解析量破百万
  6. 互掐盗播风云再起 三大视频网站存和解可能
  7. 肖仰华 | 领域知识图谱落地实践中的问题与对策
  8. CSDN Markdown编辑器使用教程
  9. HttpComponents HttpCore 4.3 Alpha1 发布
  10. POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)
  11. 天涯明月刀罗技鼠标自由弹奏脚本
  12. 瑞芯微读取寄存器_瑞芯微Android软件中添加ALC5640 音频CODEC 的寄存器修改
  13. html+css+js制作原神官网,web前端大作业(流风眷堇庭+6个页面+链接)
  14. CSS实现文本居中和块级元素居中
  15. alsa buffer原理_ALSA driver--HW Buffer
  16. js map根据value获取key
  17. PAT乙级(Basic Level)练习题 星际密码[斐波那契][打表]
  18. RxSwift学习(五)--- RxSwift 操作符
  19. Matplot X轴,Y轴最大值限定(固定X轴、Y轴的范围)
  20. 小米15.6ruby 黑苹果 显示黑屏 声音调整

热门文章

  1. 知识蒸馏相关技术【模型蒸馏、数据蒸馏】以ERNIE-Tiny为例
  2. Android关于虚拟控件、全面屏及悬浮球机型适配时遇到的问题
  3. CR渲染器全景图如何渲染颜色通道_【扮家家云渲染】3Dmax干货技巧|设置高质量室内模型渲染参数...
  4. python学习:函数(一)
  5. 我国最高山峰是珠穆朗玛峰:8848m, 我现在有一张足够大的纸张,厚度为:0.01m。 请问,我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?(不明确次数使用while)
  6. 本科计算机去当兵,本科毕业了去当兵,提不了干,又不能考军校,该怎么办?...
  7. jqurey的事件应用
  8. 剑指Offer 12—矩阵中的路径
  9. 经纬度和球体三维坐标换算
  10. 计算机软件技术专业毕业论文,软件技术专业毕业论文.doc