摇一摇诞生记五(圆形头像制作,运动时位置交换逻辑等)(cocos creator第一个项目)

大概第四天了,开始大屏端的开发。

大屏端也是分为3个场景 enroll(扫码场景) game(游戏场景显示蜗牛) ranking(结束后排行榜)

扫码节点怎么创建呢?

创建一个sprite(精灵)渲染节点。默认情况下,精灵节点会有一个默认的sprite Frame ,我把他删除(在属性检查器中操作),为什么删除呢?因为二维码是后台动态生成的。

脚本怎么写呢?在enroll.js 的onload 中写如下代码:

        //生产二维码
        cc.loader.load({url: code_url, type: 'png'}, function (err, texture) {
            // Use texture to create sprite frame
                var frame=new cc.SpriteFrame(texture);
            cc.director.getScene().getChildByName('Canvas').getChildByName('scan').getChildByName('code').getComponent(cc.Sprite).spriteFrame = frame;

        });

说明: code_url 是全局变量 由php渲染index.php创建

接下来看看game 场景怎么开发?

因为蜗牛 是动态生成的,所以要创建预制资源 我创建了 snail01, snail02, snail03 ....snail10。为什么要创建10个预制资源呢因为,每种蜗牛的颜色不同,使用的贴图不一样。每个蜗牛预制资源都一个组件蜗牛动画组件。关于动画组件参考官网的视频教程就可以做出来了。

关于显示头像和昵称的预制资源制作 比蜗牛稍微复杂点。 难点如: 头像是 圆形的,怎么解决用到了 mark 类型节点, 头像,昵称也是动态从后台生成的。

说明: head是空节点类型 mark 是mark类型节点, img 是sprite(精灵)类型节点 但要删除默认sprite Frame贴图,nickname是Lable 类型节点。注意img 的宽高摇等于img的宽高,或者略大一两个像素。

game.js脚本怎么写? 如下:

    createSnail : function (wxOpenid,wxNickname,wxHeadimgurl) {

        var whichColorSnail = this.getColorSnail();

        cc.log('whichColorSnail:'+whichColorSnail);
        //并记录下颜色选择
        gamedata.cameScene[wxOpenid] = whichColorSnail;
        gamedata.snailPrefabUse[whichColorSnail] = 1; //标记为1


        gamedata.cameScene[wxOpenid] = whichColorSnail;
        gamedata.ingScene[wxOpenid] = cc.instantiate(eval('this.'+whichColorSnail));

        gamedata.ingHead[wxOpenid] = cc.instantiate(this.headPrefab);
        gamedata.ingHead[wxOpenid].getChildByName('nickname').getComponent(cc.Label).string=wxNickname;

        cc.loader.load(wxHeadimgurl, function (err, texture) {
            // Use texture to create sprite frame
                cc.log('create logo');
            var frame=new cc.SpriteFrame(texture);
                gamedata.ingHead[wxOpenid].getChildByName('mark').getChildByName('img').getComponent(cc.Sprite).spriteFrame = frame;
                //gamedata.ingHead[wxOpenid].getChildByName('mark').getChildByName('img').getComponent(cc.).spriteFrame = frame;

        });

        this.node.addChild(gamedata.ingScene[wxOpenid]);

        this.node.addChild(gamedata.ingHead[wxOpenid])


        //gamedata.ingScene[wxOpenid].children[0].string = '李四';
        return gamedata.ingScene[wxOpenid];
    },

说明: cc.instantiate(eval('this.'+whichColorSnail)); 我怀疑 使用 this[whichColorSnail] 也是可以的。

接下来的就是 ranking场景了。其中头像 节点创建参考 game场景中头像节点创建。区别是 排行榜中节点我是直接作为game.js的属性,不像game是动态this.node.addChild添加的。

enroll.js 中onload中代码如下:

    onLoad () {
        var self = this;

        //设置游戏状态
        var state_data = {game_name:'shake',type:'gameState',state : 3}
        WebSocketManager._wsObj.send(JSON.stringify(state_data));

        var finalPlayerArr10 = gamedata.sortedPlayerArr.slice(0,10);
        cc.log('in ranking');
        cc.log('finalPlayerArr10:'+JSON.stringify(finalPlayerArr10));

        var ranking_num = 0;
        var nameArr = ['first','second','third','forth','fifth','sixth','seventh','eighth','ninth','tenth'];
        for(var i=0; i< finalPlayerArr10.length ; i++){

            //异步加载
            cc.loader.load(finalPlayerArr10[i].wxHeadimgurl, function (err, texture) {
                // Use texture to create sprite frame
                var frame=new cc.SpriteFrame(texture);
                self[nameArr[ranking_num]].spriteFrame = frame;
                cc.log('which'+nameArr[ranking_num]);
                ranking_num++;

            });
            //显示分数
            self[nameArr[i]+'Score'].string = finalPlayerArr10[i].score;

            //显示名称
            self[nameArr[i]+'Name'].string = finalPlayerArr10[i].wxNickname;

            // //显示蜗牛  不显示了
            // var finalSnail = this.createFinalSnail(finalPlayerArr10[i].wxOpenid,finalPlayerArr10[i].wxNickname);
            // finalSnail.setPosition(this.getFinalPosition(finalPlayerArr10[i].wxOpenid));

        }

说明: 为什么不用 i代替ranking_num 呢?确实刚开始我是用i的但是经测试我发现第一名总是显示到第二名的位置。所以推测

cc.loader.load是异步加载的,所以不能用i  ,我就定义一个ranking_num变量。

接下来说说game.js中业务逻辑 ,蜗牛怎么更新实时的位置? 这个就属于纯纯的业务逻辑了,看博客的朋友可以不用看下面的内容!

逻辑要求: 编号1 的跑道 是第一名的跑道,编号2 是第二名 ,编号3是第三名,以此类推,总共 10个跑道显示前十名。那是不是就能10个人玩呢,也不是,可以同时超过十个的人玩。比如100个人,大屏幕上只显示前十名,0.5秒间隔重新计算实时排名。假如我是第十三名,再次计算我是第九名了,就能显示在编号9的跑道位置。

接下来要解决的是移动蜗牛到新跑道问题。有人说,那不简单吗,0.5 时,把原来的屏幕上的蜗牛全部销毁,再重新生成前十名的蜗牛。我认为此方式不可取原因有二。一: 销毁,再重建,耗资源,也许10秒,8秒内总是这十个人时前十名呢,太浪费资源了。二:感官上不友好,玩家本来是第一名,突然闪现到第九名,显然对玩家体验太差。

这块逻辑比较绕,所以先写写伪代码,思路理清了,再写代码不迟!

//1。保存老的前十名的玩家,留着分析 old -10; 并且创建oldPlayerArr10 和 一个标记对象isDealOldPlayer10

//2。对sortedPlayerArr 重新排列  取出前10   new-10; 并创建newPlayerRanking10

 

//3。从老old -10开始for分析  如果 不在ingScene ;在 isDealOldPlayer10 中del这个属性 处理         

// 如果在ingScene; 不在new -10  进行节点销毁,ingScene更新

//                           在 new-10中,获得新的位置,并移动到新位置

 

//4。从new-10开始for分析,         

// 在old中的进一步在看是否处理过;已经处理过的1就不管了end; 没有处理过的(可能只有一种情况就是3。中在old new 都存在但是ingScene中)没有.  这个作为新点来处理 和下面处理方式一样(创建新的snailPrefab,ingScene更新)         

// 不在old中 创建新的snailPrefab

 

说明: 3.步其实还是有很多细节的,一开想着就是 for遍历,首先处理第一名,接着是第二名。。。但是有一种情况可以想象的到。假如。 第一名新位置 是第10名。那么 处理完第一名。第一名变到新位置10 和 原来第十名同时存在一个跑道上!!!。接下来处理第二名假如新位置是第9名。那么处理完第二名,编号9跑道也是同时存在两个蜗牛!!!。 分析到这里大家都明白了吧,不能这么处理! 

比较合适的方式是:处理完第一名,假如新位置是 10 ,那么接下来处理 old 第十名 ,看新位置假如是 4,接下来再处理old第四名.....明白了吧。到什么情况下终止处理呢?就是当前处理的老蜗牛,一新位置和老位置一样,二,新的名次已经在前十名之外了。

有人说 ,傻呀,就不能让10只蜗牛同时移动到新位置,或没有位置的就销毁。的确这种方式更合理些。但是我还没有找到同时执行那些代码的方法,如果大神知道这种方法,烦请告诉我,谢谢!

 

下面重点分析下第3步的代码。通过以上伪代码,隐约要递归方式(特点是 会循环,不知道具体的循环次数,内容类似),但是怎么写呢?还是比较困难的,先不管了,我先写第一名的处理,不考虑递规步递规问题。代码如下:

        for(var c=0;c < oldPlayerArr10.length ; c++) {

            // if(! oldPlayerArr10[c].wxOpenid in gamedata.ingScene){
            //     continue;
            // }
            //
            // if (isDealOldPlayer10[oldPlayerArr10[c].wxOpenid] == 1) {
            //     continue;
            // }
            //
            // if(! oldPlayerArr10[c].wxOpenid in newPlayerRanking10 ){ //节点销毁,ingScene更新,标记为已处理
            //     gamedata.ingScene[oldPlayerArr10[c].wxOpenid].node.destroy();
            //     delete gamedata.ingScene[oldPlayerArr10[c].wxOpenid];
            //
            // }else { //在new-10中
            //     gamedata.ingScene[oldPlayerArr10[c].wxOpenid].runAction(cc.moveTo(2,this.getSnailPosition(oldPlayerArr10[c].wxOpenid)));
            //     //在新位置上需要动的点
            //
            //     if(oldPlayerRanking10[oldPlayerArr10[c].wxOpenid] == newPlayerRanking10[oldPlayerArr10[c].wxOpenid]){ //名次没有变化,跑道没有变化
            //
            //     }else{
            //         var nextTrack = newPlayerRanking10[oldPlayerArr10[c].wxOpenid];
            //         //查看nextTrack跑道是否有 老蜗牛,没有则end  若有则开始处理它
            //         oldPlayerRanking10
            //         var nextWxOpenid = this.getWxOpenidByTrack(nextTrack,oldPlayerRanking10);
            //
            //         if(nextWxOpenid != ''){
            //             //在new-10中
            //             //不在new-10中
            //         }
            //
            //     }
            // }
            //
            // isDealOldPlayer10[oldPlayerArr10[c].wxOpenid] = 1; //标记为已处理
}

写到if(nextWxOpendi != '')....就发现是时候改成递规了。

continue---> return false ; 把 newPlayerRanking10, oldPlayerRanking10 等这些改为参数:改好的递规函数如下:大家如果遇到写递规时,有困难也可以采取这种间接方式,把第一个过程写下来然后再改为递规的方式。

    recurrenceDealOldPlayer: function (wxOpenid, newPlayerRanking10, oldPlayerRanking10,isDealOldPlayer10,ingScene_tmp) {
        cc.log('in recurreceDealOldPlayer:');
        // cc.log('in gamedata.ingScene:');
        // cc.log(ingScene_tmp);
        cc.log('wxOpenid:'+wxOpenid);
        var aa = wxOpenid in ingScene_tmp;
        cc.log('wxOpenid in ingScene_tmp:'+aa);


        if(!( wxOpenid in ingScene_tmp)){
            return false;
        }

        if (isDealOldPlayer10[wxOpenid] == 1) {
            return false;
        }
        cc.log('ingScene_tmp【wxopenid]:'+ ingScene_tmp[wxOpenid]);

        if(! (wxOpenid in newPlayerRanking10) ){ //节点销毁,ingScene更新,标记为已处理
            var deadNode = ingScene_tmp[wxOpenid];
            delete ingScene_tmp[wxOpenid];

            cc.log('nodeDestroy():');
            //deadNode.node.destroy();
            deadNode.destroy();

            //更新snailPrefabUse 中值
            gamedata.snailPrefabUse[gamedata.cameScene[wxOpenid]] = 0;

            //销毁logo节点
            var logoNode = gamedata.ingHead[wxOpenid];
            delete gamedata.ingHead[wxOpenid];

            cc.log('logonodeDestroy():');
            //logoNode.node.destroy();
            logoNode.destroy();

            cc.log('2222isDealOldPlayer10:'+JSON.stringify(isDealOldPlayer10));
            isDealOldPlayer10[wxOpenid] = 1; //标记为已处理

        }else { //在new-10中
            ingScene_tmp[wxOpenid].runAction(cc.moveTo(config.runActionTime,this.getSnailPosition(wxOpenid)));

            cc.log('2222111isDealOldPlayer10:'+JSON.stringify(isDealOldPlayer10));
            isDealOldPlayer10[wxOpenid] = 1; //标记为已处理

            if(oldPlayerRanking10[wxOpenid] == newPlayerRanking10[wxOpenid]){ //名次没有变化,跑道没有变化
                return false;
            }else{
                //名次发生变化才需要变更head位置
                gamedata.ingHead[wxOpenid].runAction(cc.moveTo(config.headRunActionTime,this.getLogoPosition(wxOpenid)));

                var nextTrack = newPlayerRanking10[wxOpenid];
                //查看nextTrack跑道是否有 老蜗牛,没有则end  若有则开始处理它
                var nextWxOpenid = this.getWxOpenidByTrack(nextTrack,oldPlayerRanking10);

                if(nextWxOpenid != ''){
                    //在new-10中
                    //不在new-10中
                    this.recurrenceDealOldPlayer(nextWxOpenid,newPlayerRanking10,oldPlayerRanking10,isDealOldPlayer10,ingScene_tmp);
                }

            }
        }



    },

 

至此,大屏端的主要逻辑已经写完了,下一篇说说微信扫码,php 渲染index.php(cocos打包后是index.html),与php socket服务,整个流程是怎么样的,怎样衔接的。

 

未完待续。。。。。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值