CocosCreator微信小游戏入门实战《小猫钓鱼》(三):预制体Prefab

分类栏目:cocos教程

315

上一节我们完成了鱼的运动代码的编写,这一节我们主要需要通过预制体和单例实现将鱼放置到场景当中。

看起来将鱼放置到场景中是个很简单的事情,你可以说,上一节我已经知道怎么做出一只游来游去的鱼了,那我一只一只的按照之前的方法将它们放到场景中就可以了啊!

但是,你不知道玩家能够挑战多长的时间,对于小白玩家来说,可能他只能挑战几秒钟的时间,这种情况下你尚可以通过老方法去一个一个的放置鱼,但假设有一个游戏高手,他能够无限长的时间进行游戏,那你的鱼理论上也需要放置无限多个,怎么办?

这个时候我们就需要Prefab预制体了。

Prefab是什么?

它是储存在项目中的一种可以被反复克隆使用的游戏对象,当游戏中需要非常多反复使用的对象、资源时,Prefab可以帮助快速的生成这些相同或者相似的游戏资源。例如子弹、怪物等等。

Prefab拥有以下特点:

  1. 能够放到多个场景中,也可以在同一个场景中重复多次放置
  2. 当把Prefab加入到场景时,实际上时创建了一个新的实例,该实例本质上是Prefab的克隆
  3. 当Prefab选择了自动同步时,无论场景中放置了多少Prefab实例,只要修改Prefab,所有实例都会保持同步。

关于Prefab,可以参考官方文档:

http://docs.cocos.com/creator/manual/zh/asset-workflow/prefab.html

OK,接下来我们来进行Prefab的制作。

在cocoscreator中,prefab的制作很简单,在场景中编辑好节点后,直接使用鼠标,将节点从层级管理器拖到资源管理器,即可创建出一个Prefab。

双击assets中的预制体可以进入预制体编辑中,编辑完预制体后,点击保存或者关闭推出编辑。

接下来,我们创建一个场景的脚本,并且挂载到Canvas下。在场景脚本的Update中,我们去根据游戏进程创建实例鱼。

同时在场景中,我们创建一个空的节点,命名FishPool,用来作为所有鱼的父节点,方便进行节点的管理。

场景脚本代码:


cc.Class({
    extends: cc.Component,
    properties: {
        mPrefab : {
            default : null,
            type : cc.Prefab
        },
        mFishPool : {
            default : null,
            type : cc.Node
        },
        mHook : {
            default : null,
            type : cc.Node
        },
        mDepth : {
            default : 0,
            type : cc.Float,
            visible : false
        },
    },
    // LIFE-CYCLE CALLBACKS:
    // onLoad () {},
    start () {
    },
    update (dt) {
        var depth = Math.floor(Math.abs(this.mHook.y) / 100);// 100pixel = 1 m
        if (depth - this.mDepth > 0)//每1m生成一只鱼
        {
            var fish = cc.instantiate(this.mPrefab);
            fish.x = Math.random() * 640 - 320;//随机X轴坐标
            fish.y = this.mHook.y - 480 - 100;//在屏幕可视范围下方提前生成
            this.mFishPool.addChild(fish);
        }
        this.mDepth = depth;
    },
});



OK,保存一下,预览效果:

基本符合我们的预期。

不过还有个问题,目前的鱼外观只有一种,看起来很单调,并且每1m生成一只鱼非常的机制并不能做出很好玩的关卡出来。因此我们需要丰富一下,并且将一些数值提取成为配置,交给策划同学来进行配置。

在这之前我们先做一个关卡的配置表出来,需要配置的参数有:深度(到多少深度的时候刷新鱼),鱼的资源路径,鱼的运动速度

我们采用JSON作为配置表的数据格式,当然你也可以采用xml或者csv等,这就需要而外写一些代码进行解析。

实际项目中推荐开发一个小工具方便策划同学通过excel配置,并且一键转换输出为你使用的数据格式。

新建一个JSON文件,我把它命名为Scene.json,写入以下数据



[
    {"depth":1,"res":"Fish/fish01","speed":1},
    {"depth":2,"res":"Fish/fish02","speed":1},
    {"depth":3,"res":"Fish/fish03","speed":1},
    {"depth":4,"res":"Fish/fish04","speed":1},
    {"depth":5,"res":"Fish/fish05","speed":1},
    {"depth":6,"res":"Fish/fish06","speed":1},
    {"depth":7,"res":"Fish/fish07","speed":1},
    {"depth":8,"res":"Fish/fish08","speed":1},
    {"depth":9,"res":"Fish/fish09","speed":1},
    {"depth":10,"res":"Fish/fish10","speed":1}
]


在场景脚本的properties中添加属性,并在编辑器中配置



mSceneData : {
            default : null,
            type : cc.JsonAsset
        },

关于使用JSON资源,请参考官方文档:

http://docs.cocos.com/creator/manual/zh/asset-workflow/json.html

接着,我们对场景脚本进行修改:

cc.Class({
    extends: cc.Component,
    properties: {
        mPrefab : {
            default : null,
            type : cc.Prefab
        },
        mFishPool : {
            default : null,
            type : cc.Node
        },
        mHook : {
            default : null,
            type : cc.Node
        },
        mDepth : {
            default : 0,
            type : cc.Float,
            visible : false
        },
        mSceneData : {
            default : null,
            type : cc.JsonAsset
        },
        mIndex : {
            default : 0,
            visible : false
        }
    },
    // LIFE-CYCLE CALLBACKS:
    // onLoad () {},
    start () {
    },
    update (dt) {
        this.mDepth = Math.floor(Math.abs(this.mHook.y) / 100);// 100pixel = 1 m
        let data = this.mSceneData.json[this.mIndex];
        if (data != undefined && this.mDepth >= data.depth)//到达配置的位置时,生成一只鱼
        {
            var fish = cc.instantiate(this.mPrefab);
            cc.loader.loadRes(data.res,cc.SpriteFrame,function(err,spriteFrame){
                if (!err)
                    fish.getComponent(cc.Sprite).spriteFrame = spriteFrame;
            });//更换图片外观
            fish.x = Math.random() * 640 - 320;//随机X轴坐标
            fish.y = this.mHook.y - 480 - 100;//在屏幕可视范围下方提前生成
            this.mFishPool.addChild(fish);
            this.mIndex++;
        }
    },
});


我们使用cc.loader.loadRes来进行资源的加载,并在加载结束后进行资源的更换。

具体请参考官方文档中动态加载资源部分的文档:

http://docs.cocos.com/creator/manual/zh/scripting/load-assets.html#%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD

敲完代码,OK,预览一下:

成功,整个海底世界变得丰富一些了呢。