1. 首页
  2. IT资讯

小游戏入门到精通OR放弃?

0、体验QQ轻游戏

  • 需要使用Android手机

  • 登录手Q开启厘米秀

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

搜索厘米秀 申请体验资格 开启厘米秀
小游戏入门到精通OR放弃? 小游戏入门到精通OR放弃? 小游戏入门到精通OR放弃?
侧滑 好友点「+」或者直接点击人物 游戏入口页
小游戏入门到精通OR放弃? 小游戏入门到精通OR放弃?

1、平台申请账号

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

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

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

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

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

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

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

2、环境搭建

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

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

3、第三方引擎推荐

第三方引擎的实现方式为基于 bricks webGL 接口进行封装,具有较高的灵活性,但渲染性能会欠缺。 如开发者对性能要求更高,推荐使用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获取用户昵称
  functiongetNick(callback){  	BK.MQQ.Account.getNick(GameStatusInfo.openId,callback);  }  BKTools.getNick(function(openId,nick){  	Global.nickName=nick;  });  
4.1.3 获取用户图像
  getHead(){letself=this;letabsolutePath="GameSandBox://_head/"+GameStatusInfo.openId+".jpg";letisExit=BK.FileUtil.isFileExist(absolutePath);  cc.log(absolutePath+"isexit:"+isExit);//如果指定目录中存在此图像就直接显示否则从网络获取  if(isExit){  cc.loader.load(absolutePath,function(err,texture){if(err==null){  self.head.getComponent(cc.Sprite).spriteFrame=newcc.SpriteFrame(texture);  }  });  }else{  BK.MQQ.Account.getHeadEx(GameStatusInfo.openId,function(oId,imgPath){  cc.log("openId:"+oId+"imgPath:"+imgPath);varimage=newImage();  image.onload=function(){vartex=newcc.Texture2D();  tex.initWithElement(image);  tex.handleLoadedTexture();  self.head.getComponent(cc.Sprite).spriteFrame=newcc.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  */functiongetShareInfo(localPicPath){if(!localPicPath){  localPicPath="GameRes://qrcode.png";//游戏资源包根目录存放图片qrcode.png  }letsummarys=["文案1","游戏太好玩了,玩得停不下来!","游戏太刺激了,邀请还能领抱枕!","文案2"];letshareInfo={summary:summarys[getRandomInt(0,3)],picUrl:"http://h.hiphotos.baidu.com/image/pic/item/18d8bc3eb13533fa4dd573ada3d3fd1f40345bd6.jpg",//支持HTTPS  extendInfo:Global.openId,//或者使用GameStatusInfo.openId  localPicPath:localPicPath,//分享至空间、微信、朋友圈时需要的图。(选填,若无该字段,系统使用游戏对应的二维码)  };returnshareInfo;  }/**  *分享  *@param{*}shareInfo  *@param{*}callback  */functiontoShare(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");  }elseif(shareDest==1){//空间  log("成功分享至空间");  }elseif(shareDest==2){//微信  log("成功分享至微信");  }elseif(shareDest==3){//朋友圈  log("成功分享至朋友圈");  }  }elseif(retCode==1){if(callback){  callback(-1);  }  log("分享失败"+retCode);  }elseif(retCode==2){if(callback){  callback(-1);  }  log("分享失败,用户取消分享:"+retCode);  }  });  }else{if(callback){  callback(0);  }  }  }  

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

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

4.3 生命周期
  /**  *游戏事件以及生命周期  */functionaddGameEvent(){newBK.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");returngetShareInfo();  },//分享成功  onShareComplete:function(app,retCode,shareDest,isFirstShare){  log("BK.Game.onShareCompleteretCode:"+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.onExceptionmsg:"+this.errorMessage()+",stack:"+this.errorStacktace());  }  });  }  
4.4 支付与红包

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

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

  • 道具申请上架

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

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

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

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

5、网络通讯

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

官方文档-网络功能

下面我会介绍

  • BK.HttpUtil:用于短连接

  • XMLHttpRequest:用于短连接

  • WebSocket:用于长连接

http get/post请求

BK.HttpUtil

  functionBKGet(url,callback,custom){lethttpUtil=newBK.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){letstr=res.readAsString();  cc.log(str);letdata=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  */functionpost(url,data,callBack){  log("请求参数:"+data);varxhr=newXMLHttpRequest();  xhr.onreadystatechange=function(){letstatus=xhr.status;if(xhr.readyState==4&&status==200){varresponseBody=xhr.responseText;  log("响应的结果:"+responseBody);  callBack(status,JSON.parse(responseBody));  }  };  xhr.open("POST",url,true);  xhr.send(data);  }/**  *get请求  *@param{*}url  *@param{*}data  *@param{*}callBack  */functionget(url,data,callBack){  log("请求参数:"+data);varxhr=newXMLHttpRequest();  xhr.onreadystatechange=function(){letstatus=xhr.status;if(xhr.readyState==4&&status==200){varresponseBody=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/**  *@authorJaven  *@copyright2018-09-2217:32:21javendev@126.com  *@descriptionwebSocket工具组件  */letGlobal=require("Global");letBKTools=require("BKTools");letWS_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=newBK.WebSocket("ws://"+Global.WEB_SOCKET.URL);this._wsType=WS_TYPE.BK_WS;  }else{this._ws=newWebSocket("ws://"+Global.WEB_SOCKET.URL);this._wsType=WS_TYPE.WEB_WS;  }this.addEventListener(this._ws);  },  addEventListener(ws){letself=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){letbuf=event.data;//将游标pointer重置为0  buf.rewind();letab=newArrayBuffer(buf.length);letdv=newDataView(ab);while(!buf.eof){  dv.setUint8(buf.pointer,buf.readUint8Buffer());  }  self.toHander(ab);  }else{  BKTools.log("BK.WebSocketdatatypeisnotbinary");  }  }  }else{  ws.onmessage=function(event){if(event.datainstanceofBlob){letblob=event.data;varreader=newFileReader();  reader.readAsArrayBuffer(blob);  reader.onload=function(e){if(e.target.readyState==FileReader.DONE){letresult=reader.result;  self.toHander(result);  }  }  }else{  BKTools.log("webSocketdatatypeisnotblob");  }  };  }  },  hasConnected(){returnthis._isConnected;  },  toHander(buffer){letself=this;letcmd=proto.UserCmdOutComonProto.deserializeBinary(buffer);switch(cmd.getId()){caseproto.UserCmdOutType.RECONNECTION_RESULT:  BKTools.log("重连结果....");break;caseproto.UserCmdOutType.USER_CONNECT_SUCCESS:  BKTools.log("客户端连接成功....");break;caseproto.UserCmdOutType.USER_LOGIN_SUCCESS:  BKTools.log("反馈登录消息开始...");break;caseproto.UserCmdOutType.USER_LOGIN_SUCCESS_OVER:  BKTools.log("反馈登录消息结束....");letloginOver=proto.PlayerLoginOverProtoOut.deserializeBinary(buffer);//回调给请求页  Global.loginResponse(loginOver);break;default:break;  }  },  send(bytes){this._ws.send(bytes);  },/**  *登录  */  toLogin(){if(!this.hasConnected()){this.initWebSocket();return;  }letlogin=newproto.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}ver17.1.1.1  *@param{String}ver26.3.3.3  */functionversionCompare(ver1,ver2){  ver1=parseInt(ver1.replace(/./g,""));  ver2=parseInt(ver2.replace(/./g,""));if(ver1>=ver2){returntrue;  }else{returnfalse;  }  }  
  /**  *跳转到其他游戏  *@param{Number}gameId  */functionskipGame(gameId){  BK.QQ.skipGame(gameId,"扩展参数");//游戏启动时可以通过GameStatusInfo.gameParam获取}  

7、成绩上报与排行榜

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

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

  /**  *成绩上报  *@param{*}isWin  *@param{*}callback  */functionuploadScore(isWin,callback){if(cc.sys.platform!=cc.sys.QQ_PLAY){if(callback){  callback(-1,"此接口只支持QQ玩一玩平台");  }return;  }if(!isWin){  isWin=0;  }else{  isWin=1;  }vardata={userData:[{openId:GameStatusInfo.openId,startMs:Global.startGameTime.toString(),endMs:((newDate()).getTime()).toString(),scoreInfo:{score:isWin,  },  },],attr:{score:{type:'rank',order:3,  }  },  };  BK.QQ.uploadScoreWithoutRoom(1,data,function(errCode,cmd,data){  log("uploadScoreWithoutRoomcallbackcmd"+cmd+"errCode:"+errCode+"data:"+JSON.stringify(data));if(callback){  callback(errCode,data);  }  });  }/**  *拉取排行榜数据  *@param{*}callback  */  functiongetRankList(callback){if(cc.sys.platform!=cc.sys.QQ_PLAY){if(callback){  callback(-1,"此接口只支持QQ玩一玩平台");  }return;  }letattr="score";letorder=3;letrankType=0;  BK.QQ.getRankListWithoutRoom(attr,order,rankType,function(errCode,cmd,data){  log("getRankListWithoutRoomcallbackcmd"+cmd+"errCode:"+errCode);if(errCode!=0){  callback(errCode);return;  }if(data){letrankList=data.data.ranking_list;  log("datanotnull"+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、关注公众号

查询是否关注公众号

  functioncheckPubAccountState(){  BK.QQ.checkPubAccountState(Global.PUIN,function(errCode,cmd,data){  BK.Script.log(0,0,"callbackerrCode="+errCode+"cmd="+cmd+"data="+data);if(data.is_follow==1){returntrue;  }else{returnfalse;  }  });  }  

进入公众号主页

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

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

9、广告

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

简单的封装与使用

  /**  *加载视频广告  */functionfetchVideoAd(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("加载了视频广告...");  }/**  *加载条幅广告  */functionfetchBannerAd(){  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("fetchBannerAdfailed.retCode:"+retCode);  }  }.bind(this));  }functioncloseBannerAd(){  log("关闭广告....");if(Global.bannerHandle){  Global.bannerHandle.close();  Global.bannerHandle=undefined;  }  }functionloadBannerAd(){if(cc.sys.platform==cc.sys.QQ_PLAY){  log("预加载Banner");  fetchBannerAd();  }  }functionloadVideoAd(){if(cc.sys.platform==cc.sys.QQ_PLAY){  log("预加载Video");  fetchVideoAd();  }  }  
  /**  *@authorJaven  *@copyright2018-09-2615:53:52javendev@126.com  *@description广告测试  */letBKTools=require("BKTools");varGlobal=require("Global");  cc.Class({extends:cc.Component,properties:{  },//onLoad(){},  btnClick(event,data){  BKTools.log("点击了>"+data);if(data=='loadVideo'){//如果需要判断是否加载成功可以在封装的函数中添加回调  BKTools.loadVideoAd();  }elseif(data=='showVideo'){if(Global.videoHandle){this.jumpVideoAd();  }else{  BKTools.log("无视频广告句柄");  BKTools.loadVideoAd();  }  }elseif(data=='loadBanner'){  BKTools.loadBannerAd();  }elseif(data=='showBanner'){if(Global.bannerHandle){this.showBannerAd();  }else{  BKTools.log("无条幅广告句柄");  BKTools.loadBannerAd();  }  }elseif(data=='closeBanner'){  BKTools.closeBannerAd();  }elseif(data=='back'){  cc.director.loadScene("welcome");  }  },  jumpVideoAd(){letself=this;  Global.videoHandle.jump();  Global.videoHandle.setEventCallack(function(code,msg){}.bind(this),//关闭游戏(不再使用不需要监听)  function(code,msg){if(code==0){  BKTools.log("达到看广告时长要求,可以下发奖励endVidecode:"+code+"msg:"+msg);//达到看广告时长要求,可以下发奖励  }else{  BKTools.log("其他异常,比如播放视频是程序返回到后台");  }  }.bind(this),function(code,msg){  BKTools.log("关闭视频webviewendVidecode:"+code+"msg:"+msg);//关闭视频webview  }.bind(this),function(code,msg){  BKTools.log("开始播放视频startVidecode:"+code+"msg:"+msg);//开始播放视频  }.bind(this));  },  showBannerAd(){  Global.bannerHandle.show(function(succCode,msg,handle){if(succCode==0){  BKTools.log("banner展示成功home");  }else{  BKTools.log("banner展示失败homemsg:"+msg);  }  });  },  start(){  },//update(dt){},});  

10、源码

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31557424/viewspace-2218282/,如需转载,请注明出处,否则将追究法律责任。

主题测试文章,只做测试使用。发布者:予衬,转转请注明出处:http://www.cxybcw.com/170806.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code