文档结构

一 游戏入口

二 游戏统计

三 视频播放、音频播放

四 支付

五 http通讯

六 游戏配置文件

七 关键字屏蔽

八 新手指引

 

文档结构

cocos2d-js-min.js    cocos引擎

egreth5sdk.js           白鹭SDK

exif.js                       ???

gameApi.js              游戏API(充值、分享统计等)

gameCenterSA.js    ???

main.js                    充值、统计、发送桌面

project.js                 游戏主文件

settings.js               ???

zm_engine_v2.js     ???

 

代码:

Global.js              全局支付、请求指引

data.js                 对话配置、关键词屏蔽

gconst.js              全局常量 (字体名、商品类型等游戏变量)

gevent.js              事件名

glang.js                全局语言(所有动态文本的固定文字)

gplayer.js             游戏主类

grpc.js                  http通讯

gsdk.js                 原生交互、cordova视频、支付

gutils.js                数组、字符串等数据处理

 

guideUI.js            新手指引

createRole.js       创建角色(昵称)

gwnd.js                升级会话框

homeUI.js            主页

loginUI.js             登录

main.js                将游戏内函数存入window,供外部调用

paymentUI.js       支付UI

videoPlayerUI.js  视频播放

 

 

 

一 游戏入口

1 从白鹭平台获取egretID、用户信息等,然后进入游戏正式链接

<div id="gameIframeBox" style="display:block;margin:0 auto;width:100%;height:0px;background-color:#000">
       <iframe id="gameIframe" name="gameIframe" src="http://api.egret-labs.org/v2/game/20409/91822?chanId=20409&channelId=20409&showLoginPanel=no&time=1509974135&egretstartfrom=gamece
nter&egretSdkDomain=https://api.egret-labs.org/v3&egretServerDomain=https://api.egret-labs.org/v3&egretOauthUser=1&egretId=3d66bcad0342d9c2b838810445fc166a&userId=D02F30FBF9C4E6C3F2F7B9738D11772F__qq
&userName=危险的画本&userImg=http://q.qlogo.cn/qqapp/101237728/D02F30FBF9C4E6C3F2F7B9738D11772F/100&userSex=1&sign=118620d8e41c0ccfc78406b0c24c84e4&egretwt=mobile&isEgretLogin=1
"
frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="no" width="100%" height="100%"></iframe> </div>

 

2 正式游戏网页,加载cocos-js代码,运行游戏

<script src="src/settings.js" charset="utf-8"></script>
<script src="main.js" charset="utf-8"></script>

 

二 游戏统计

百度统计

TalkingData

 

三 视频播放、音频播放

新用户进入游戏的视频单独申请播放,和游戏中升级后播放的视频申请步骤不一样。

游戏中levelup后的视频,在升级后根据等级level请求服务器获取相应视频链接。

 

PC端播放视频

请求加载视频

            login_preload: function() {
                gaudio.loadBgSound(),
                gevent.emit(gevent.EVENT_LOAD_VIDEO, 1101)
            }
                gevent.on(gevent.EVENT_LOAD_VIDEO,
                function(e) {
                    var t = e.detail;
                    1 != gsdk.videoType() && this.loadVideo(this.getVideoURL(t))
                }

 

cocos自带的video播放html视频

            loadVideo: function(e) {
                if (1 != gsdk.videoType()) {
                    var t = new cc.Node("VideoPlayer");
                    t.setAnchorPoint(cc.p(0, 0));
                    var n = t.addComponent(cc.Widget);
                    n.isAlignTop = !0,
                    n.isAlignBottom = !0,
                    n.isAlignLeft = !0,
                    n.isAlignRight = !0,
                    n.top = 0,
                    n.bottom = 0,
                    n.left = 0,
                    n.right = 0,
                    this.videoPlayer = t.addComponent(cc.VideoPlayer),
                    this.videoPlayer.keepAspectRatio = !0,
                    this.node.addChild(t),
                    this.videoPlayer.remoteURL = e;
                    var i = document.getElementsByClassName("cocosVideo")[0];
                    i.setAttribute("x5-video-player-type", "h5"),
                    i.setAttribute("webkit-playsinline", "true");
                    var o = function() {
                        this._onVideoEnded()
                    };
                    this.videoPlayer.node.on("completed", o, this),
                    this.videoPlayer.node.on("stopped", o, this),
                    this.videoPlayer.play(),
                    this.videoPlayer.pause(),
                    this.videoPlayer.node.active = !1
                }
            }

 

App播放视频

一种是进入游戏时播放固定视频

  enterGmae: function() {
                var e = this.editBox.string;
                if (e.length <= 0) gwnd.showPrompt(glang.NameEmpty);
                else if (this._checkName(e)) gwnd.showPrompt(glang.ContainsIllegalCharacters);
                else {
                    gevent.emit(gevent.EVENT_LOAD_VIDEO, 1102);
                    var t = this;
                    grpc.CreateRole(function(n) {
                        0 === n && (gsdk.analytics(gconst.TD_EVENT.CREATE_ROLE, {
                            roleName: e
                        }), gsdk.reportUserProgress(1), t.playVideo())
                    },
                    e)
                }
            }

 

第二种是角色升级时,播放视频

            _tryShowLevelUpAction: function() {
                this._tryShowComingTelphone() || this.tryShowStoryVideo()
            },
            tryShowStoryVideo: function() {
                var e = gplayer.level;
                if (gplayer.max_story_video_level >= e) return ! 1;
                var t = gsheet.Level.find({
                    Level: e
                });
                if (t.StoryVideoId <= 0) return ! 1;
                grpc.WatchStoryVideo(function(t) {
                    0 == t && (gplayer.max_story_video_level = e)
                }),
                gaudio.pauseBgSound();
                var n = cc.instantiate(this.levelupAnim);
                this.node.addChild(n);
                return n.once("anim-complete",
                function(e) {
                    n.removeFromParent(),
                    gwnd.openVideo(t.StoryVideoId, gconst.VIDEO_TYPE.STORY)
                },
                this),
                !0
            }

 

 

需要播放视频时,根据视频ID和视频类型,请求播放视频。

 gwnd.openVideo(1101, gconst.VIDEO_TYPE.STORY);
VIDEO_TYPE: {
    STORY: 1,
    FACE_TIME: 2,
    LIBRARY: 3,
    SEVENLOGIN: 4
},
VIDEO_PLAY_STATE: {
    NONE: 0,
    PLAYING: 1,
    PAUSED: 2,
    COMPLETED: 3
}

 

发送请求视频事件

 openVideo: function(e, t, n) {
      gevent.emit(gevent.EVENT_OPEN_VIDEO, {
       videoId: e,
       callBack: n,
       videoType: t
        })
}

 

处理播放视频事件,关闭背景音乐,并尝试播放视频

gevent.on(gevent.EVENT_OPEN_VIDEO,
    function(e) {
          this._isOpenVideo = !0,
          this.bgSoundState("video", !0),
          this.windowLayer.getChildren().length <= 0 && this.anim.play("Exit")
}
gevent.on(gevent.EVENT_OPEN_VIDEO,
     function(e) {
           var t = e.detail;
           1103 == t.videoId && (this.food = !0),
           this._quondamVideoId = t.videoId,
           this._videoId = gutils.getmapVideoID(t.videoId),
           this._videoType = t.videoType,
           this._callBack = t.callBack,
           Global.home.active = !1,
           1 == gsdk.videoType() && (document.body.style.backgroundColor = "transparent", cc.director.setClearColor(cc.color(0, 0, 0, 0)), this.touchLayer.active = !0),
           this._tryPlay()
      },
this)

 

判断是否需要加载小标题再播放视频,或是直接播放视频

            _tryPlay: function() {
                this._playState = gconst.VIDEO_PLAY_STATE.NONE,
                this._lastSubtitle = null,
                this._subtitles = new Array;
                var e = !1;
                gconst.VIDEO_TYPE.STORY != this._videoType && gconst.VIDEO_TYPE.INTERIM != this._videoType || (e = !0),
                e && 1 == gsdk.videoType() ? this._loadSubtitle() : this._play()
            }

 

获取并拼接视频正式Url,并使用cordova播放视频,监听播放进度和播放完成事件

            _play: function() {
                var e = this;
                if (1 == gsdk.videoType()) {
                    this.maskLayer.active = !0,
                    gsdk.videoStop();
                    var t = 0,
                    n = 0;
                    gplayer.hasOwnProperty("account_id") && (t = gplayer.account_id),
                    gplayer.hasOwnProperty("level") && (n = gplayer.level),
                    this.setloadingView(!0),
                    gsdk.getVideoURL(this._videoId, t, n,
                    function(t) {
                        gsdk.videoPlay(t),
                        e._onVideoPlaying(),
                        gsdk.watchProgress(function(t) {
                            e._onVideoProgress(t)
                        },
                        function() {
                            e._onVideoEnded()
                        })
                    },
                    function(e, t) {})
                } else this.onClicked();
                gaudio.pauseBgSound()
            }

 

使用插件cordova播放视频

videoPlay: function(e) {
          cordova.plugins.videobackground.play(e, !1)
}

 

播放视频结束,可能是多段视频组成的场景。第一段播放,中间有两个选项,根据用户选择,再播放第二段视频。

            _onVideoEnded: function() {
                var e = !0;
                if (this.removeVideo(), this.food) this.food = !1,
                e = !1,
                this.nodeSelectFood.getChildByName("txtSelect").getComponent(cc.Label).string = glang.SelectFood,
                this.nodeSelectFood.active = !0;
                else {
                    var t = gsheet.Video.find({
                        ID: this._quondamVideoId
                    });
                    if (t) {
                        this.btnPlay.active = !1,
                        e = !1,
                        this.options.active = !0;
                        var n = this.options.getChildByName("op1"),
                        i = this.options.getChildByName("op2");
                        n.getComponent(cc.Label).string = t.NextOption1,
                        i.getComponent(cc.Label).string = t.NextOption2,
                        n.once(cc.Node.EventType.TOUCH_END,
                        function() {
                            this.options.active = !1,
                            this._quondamVideoId = t.NextVideoId1,
                            this._videoId = gutils.getmapVideoID(t.NextVideoId1),
                            this.loadVideo(this.getVideoURL(this._videoId)),
                            this._tryPlay()
                        },
                        this),
                        i.once(cc.Node.EventType.TOUCH_END,
                        function() {
                            this.options.active = !1,
                            this._quondamVideoId = t.NextVideoId2,
                            this._videoId = gutils.getmapVideoID(t.NextVideoId2),
                            this.loadVideo(this.getVideoURL(this._videoId)),
                            this._tryPlay()
                        },
                        this)
                    }
                }
                e && this.closeVideoPlayer()
            }

 

 

四 支付接入

 

 

点击商品,提示购买

            clickEvent: function() {
                var e = gsheet.ShopGoods.find({
                    ID: this._sheet.GoodsId
                });
                if (gplayer.isHaveShopGoods(e)) gwnd.showPrompt(e.HaveTip);
                else if (e.OpenFuncId > 0 && !gplayer.isFuncOpend(e.OpenFuncId)) {
                    var t = gsheet.FuncOpening.find({
                        ID: e.OpenFuncId
                    }),
                    n = gsheet.Level.find({
                        Level: t.OpenLevel
                    }),
                    i = gutils.substitute(glang.BuyUnopenedGoodsTip, e.Name, n.Day);
                    gwnd.showPrompt(i)
                } else Global.sdk_payment_pay(e.ID)
            }

 

 弹出购买商品的提示框

            payment_pay: function(e) {
                var t = this;
                lobby.purchaseConfirm ? gwnd.confirmPrompt(function() {
                    t.payment_resume()
                },
                "商品购买", "请为您选购的商品进行支付", gconst.PROMPT_WND_TYPE.ONE, "关闭") : gwnd.loading(!0);
                var n = {
                    ID: e.ID,
                    Price: 100 * e.Price,
                    Label: e.Name,
                    level: gplayer.level,
                    Name: gplayer.name,
                    accountId: gplayer.account_id
                };
                lobby.purchase(n, e.ID,
                function(e) {
                    e ? t.payment_OnRecipt(e) : (gwnd.closeConfirmPrompt(), t.payment_resume()),
                    gwnd.loading(!1)
                },
                function(e, t) {
                    if (gwnd.closeConfirmPrompt(), gwnd.loading(!1), e || t) {
                        var n = "";
                        t && t.length > 0 && (n += t),
                        e && e.length > 0 && (n += "错误码:" + e),
                        gwnd.showPrompt(n)
                    } else gwnd.showPrompt("充值失败!")
                },
                function(e, t, n, i, o) {
                    gwnd.loading(!1),
                    e >= n.Price ? gwnd.open("common_wnd", [n, i, o]) : gwnd.open("common_nomoney_wnd", [e, t, n, i, o])
                })
            }

 

 确认购买。获取商品ID、价格、名字等信息,发起购买请求。

project.js

            payment_resume: function() {
                window.lobby && lobby.processPendingPurchases(this.payment_OnRecipt)
            }
  "商品购买", "请为您选购的商品进行支付", gconst.PROMPT_WND_TYPE.ONE, "关闭") : gwnd.loading(!0);
                var n = {
                    ID: e.ID,
                    Price: 100 * e.Price,
                    Label: e.Name,
                    level: gplayer.level,
                    Name: gplayer.name,
                    accountId: gplayer.account_id
                };
                lobby.purchase(n, e.ID,
                function(e) {
                    e ? t.payment_OnRecipt(e) : (gwnd.closeConfirmPrompt(), t.payment_resume()),
                    gwnd.loading(!1)
                },

 

生成商品订单

gameApi.js

    //充值补单
    this.processPendingPurchases = function(payment_OnRecipt_callback){
        self.rpc.request(function(code, errmsg, rcptArr){
            if(200 === code && rcptArr){
                for(var i=0;i<rcptArr.length;i++){
                    payment_OnRecipt_callback(rcptArr[i]);
                }
            }
        },self.sdkHash.loveportalurl + "pendingpurchase.php",{gameid:self.appId,account:self.lovechaccount,channel:self.CHANNEL_PLATFORM});
    }
//充值 cData : {ID: 道具ID,Price: 价格 (分)   ,Label: (商品名or描述) }
    this.purchase = function(cData, dialysis, succeedCallback, failedCallback){
        if(!self.sdkJs){
            failedCallback(0, "登录失败请重试");
            return;
        }
        var _attachs = {
            itemname:cData.Label,
            playerlevel:cData.level,
            playername:cData.Name,
            accountid:cData.accountId,
            channelattachs:self.sdkHash.attachs
        }
        var createOrderData = {
            gameid:self.appId,
            account:self.lovechaccount,
            sdkname:self.CHANNEL_SDKNAME,
            channel:self.CHANNEL_PLATFORM,
            itemid:cData.ID,
            attachs:_attachs
        }
        self.sdkJs.purchase(cData, createOrderData, succeedCallback, failedCallback);
    }

 

发起http请求购买。ZmSDK是啥...

main.js

    //充值
    this.purchase = function (cData, createOrderData, succeedCallback, failedCallback) {
        //创建订单
        self.rpc.request(function(code, errmsg, sData){
            if(200 === code){
                self.purchaseStart(cData, sData, succeedCallback, failedCallback);
            }else{
                failedCallback(code, errmsg);
            }
        },self.sdkHash.loveportalurl + "requestpay.php",createOrderData);
    }

    this.purchaseStart = function (cData, sData, succeedCallback, failedCallback) {
        var payinfojson = {
            check: sData.attachs.check,
            feeid: cData.ID+"",
            fee: sData.price+"",
            feename: cData.Label,
            extradata: sData.gameorderid,
            serverid: 1+"",
            rolename: cData.Name,
            roleid: cData.accountId+"",
            servername: ""
        };
        ZmSdk.getInstance().pay(payinfojson, function(data){
            //跳转到了支付页面
            if(data.retcode == 3)
                return;
            if(data.retcode == 1){
                failedCallback(0,data.msg);
                return;
            }
            if(data.retcode == 2){
                failedCallback(0,"您取消了支付");
                return;
            }
            if(data.retcode == 0)
                succeedCallback();
        });
    }

 

支付成功回调

project.js

            payment_OnRecipt: function(e) {
                grpc.SdkPaymentPay(function(t, n, i, o, s, a, c, l, r) {
                    1 !== t ? 0 === t && (lobby.finishPurchase(e), gplayer.buyShopGoodsSuccess(n, i, o, s, a, c, l, r), gwnd.showPrompt(glang.PaySuccess), gevent.emit(gevent.PAY_SUCCESS)) : lobby.finishPurchase(e)
                },
                e)
            }

 

发起http请求,告知服务端支付完成

gameApi.js

    //完成一笔订单
    this.finishPurchase = function(rcpt){
        self.rpc.request(function(){},self.sdkHash.loveportalurl + "finishpurchase.php",{gameid:self.appId,receipt:rcpt});
    }

游戏内更新界面

 gevent.on(gevent.PAY_SUCCESS, this._paySuccessHandler, this)
_paySuccessHandler: function() {
     this.updateView()
}

 

五 Http通讯协议

post模式。

http包含token,且所有请求都写在Http类里面,留出回调接口

    grpc: [function(e, t, n) {
        "use strict";
        cc._RF.push(t, "e1dd3ZUONZBW4caM364h+q8", "grpc");
        var i = {
            token: "",
            request: function(e, t, n) {
                gwnd.loading(!0);
                var i = new XMLHttpRequest;
                i.onreadystatechange = function() {
                    if (cc.log("xhr.readyState:" + i.readyState + "--xhr.status:" + i.status + "--xhr.responseText:" + i.responseText), i.readyState == XMLHttpRequest.DONE) if (200 == i.status) {
                        var e = i.responseText;
                        cc.log("rpc:|" + e);
                        var n = JSON.parse(e);
                        if ("err10001" == n[0]) return gwnd.confirmPrompt(function() {
                            gsdk.isExitLobby() ? gsdk.exitToLobby() : cc.director.loadScene("logoCanvas")
                        },
                        " 重复登录提醒", "检测到您的账号在其他设备登录游戏,请重新登录验证。", gconst.PROMPT_WND_TYPE.ONE),
                        void gwnd.loading(!1);
                        t.apply(this, n.rpc),
                        "mail" in n && gplayer.addNewMails(n.mail),
                        "activity" in n && gplayer.addNewActivitys(n.activity),
                        "activity_target" in n && gplayer.updateActivityTargets(n.activity_target),
                        gwnd.loading(!1)
                    } else gwnd.loading(!1)
                },
                i.open("POST", gsdk.serverURL(), !0);
                var o = "A=" + encodeURIComponent(e);
                if ("" !== this.token && (o = o + "&T=" + encodeURIComponent(this.token)), void 0 !== n) {
                    o += "&G=";
                    var s = JSON.stringify(n);
                    o += encodeURIComponent(s)
                }
                cc.log("rpcName:" + e + "--send:" + o),
                i.setRequestHeader("Content-type", "application/x-www-form-urlencoded"),
                i.send(o)
            },
            getSDKGiftReward: function(e, t) {
                this.request("getSDKGiftReward", e, [t])
            },
            getSendToDesktopReward: function(e) {
                this.request("getSendToDesktopReward", e, [])
            },
            BindAccount: function(e, t, n, i, o) {
                this.request("BindAccount", e, [t, n, i, o])
            },

 

 

 

六 游戏配置文件

 所有标题、随机姓名、对话全部都写在代码里

 

七 关键字屏蔽

取名时,从服务器下载name_forbit.txt,里面有被屏蔽的关键字。

 cc.loader.loadRes("forbid/name_forbid.txt",
     function(t, n) {
         t || (e._forbidNames = n.split("\r\n"))
 })

 

八 新手指引做法

每次进入某界面(有新手指引的界面)时,检查该界面是否需要显示新手指引,如果有,则显示新手指引。

这个检查会每次进入某界面都会检查一次,新手指引完成后,会向服务器发送保存当前指引步骤。

点击新手指引按钮时,会执行bind的处理函数handler,来继续指引操作。

 

下一步新的指引

            newbieGuide: function(e, t, n, i) {
                gevent.emit(gevent.EVENT_GUIDE_START_STEP, {
                    step: e,
                    btnView: t,
                    callback: n,
                    isEnable: i
                })
            }

 

处理下一步新手指引

            onLoad: function() {
                gevent.on(gevent.EVENT_GUIDE_START_STEP, this.guideStartHander, this)
            },
            guideStartHander: function(e) {
                this.step = e.detail.step,
                this.btnView = e.detail.btnView,
                this.callback = e.detail.callback,
                this.isEnable = e.detail.isEnable,
                this._data = gsheet.GuideStep.find({
                    ID: this.step
                }),
                gsdk.analytics(gconst.TD_EVENT.BEGIN_MISSION, {
                    guideStep: this.step
                }),
                this.newbieGuide()
            }

 

显示Dog新手指引

            newbieGuide: function() {
                if (this.node.on(cc.Node.EventType.TOUCH_END, this.touchNodeEnd, this), this.createDog(), void 0 != this.btnView) {
                    var e = this.btnView.getComponent(cc.Button);
                    void 0 != e && void 0 == this.isEnable && (e.interactable = !1),
                    this.perch = cc.instantiate(this.perchPf),
                    this.node.addChild(this.perch),
                    this.schedule(this.updateDisplay, .2),
                    this.perch.on(cc.Node.EventType.TOUCH_END, this.touchBtnEnd, this),
                    this.arrow = cc.instantiate(this.arrows),
                    this.arrow.rotation = this._data.Rotation,
                    this.node.addChild(this.arrow),
                    this.perch.active = !1,
                    this.arrow.active = !1,
                    this.updateDisplay()
                }
            },
            updateDisplay: function() {
                var e = this.btnView.getNodeToWorldTransform();
                if (void 0 != this.worldTransform) if (this.worldTransform.tx == e.tx && this.worldTransform.ty == e.ty) {
                    this.perch.active = !0,
                    this.arrow.active = !0,
                    this.perch.x = e.tx,
                    this.perch.y = e.ty;
                    var t = this.btnView.getContentSize();
                    this.perch.setContentSize(t),
                    this.arrow.x = e.tx + t.width / 2,
                    this.arrow.y = e.ty + t.height / 2
                } else this.worldTransform = e;
                else this.worldTransform = e
            }

 

posted on 2017-11-06 22:25  gamedaybyday  阅读(1035)  评论(0编辑  收藏  举报