Cocos Creator基础教程(12)—精灵变身

Stella981
• 阅读 379

在Cocos Creator中使用率最高的非精灵(Sprite)莫属了, 在游戏中我们经常会遇到将一张图片替换成另一张图片的情况,或者是在不同状态时来回切换图片。实现这个功能对程序员同学来说并不难,但是!回头检视一下编写的代码,能否让美术、策划同学使用上吗?如果不能的话,相信这篇教程可能对你和你的伙伴有更多启发!

1. SpriteIndex组件

我们这里设计一个SpriteIndex组件,使用组件的index属性来控制Sprite组件的spriteFrame属性,从而得到图片变换的能力。

//SpriteIndex.jscc.Class({
    extends: cc.Component,               //编辑器属性,只在编辑状态有效
    editor: CC_EDITOR && {
        requireComponent: cc.Sprite,     //要求节点必须有cc.Sprite组件
    },

    properties: {
        spriteFrames: [cc.SpriteFrame],  //定义一个SpriteFrames数组
        _index: 0,                       //以下划线“_”开始的为私用变量
       
        index: {                         //index属性控制图片切换
            type: cc.Integer,            //定义属性为整数类型
            //这次没使用notify方式实现属性值的变化监听,改用getter/setter方式
            get() {                           
                return this._index;
            },            //为负数退出             set(value) {                
                if (value < 0) {                                        return;
                }                                //根据spriteFrames组件长度计算this._index
                this._index = value % this.spriteFrames.length;                                //获取当前节点上的Sprite组件对象
                let sprite = this.node.getComponent(cc.Sprite);                                //设置Sprite组件的spriteFrame属性,变换图片
                sprite.spriteFrame = this.spriteFrames[this._index];
            },
        }
    },    
    /**
    *next方法,调用index++切换图片,
    *可以方便被cc.Button组件的事件调用
    */
    next() {                this.index++; //调用自身index属性,编号+1
    }
});

代码比之前的教程要复杂了一点点,对没有编程经验的美术、策划同学来说可能残忍了点,但坚持跟着注释了解组件的实现意图,相信你会收获更多。

我们再看下图,SpriteIndex组件的用法:

Cocos Creator基础教程(12)—精灵变身

  1. 在编辑器场景中添加一个Sprite组件

  2. 然后挂载上SpriteIndex

  3. 添加SpriteFrames数组属性元素

  4. 将可能会出现的图片拖动到SpriteFrames数组属性下

  5. 尝试修改index属性,你会看到精灵图片的变化

2. 运行时图片切换

请出我们的按钮组件,通过点击时调用SpriteIndex.next方法进行切换,看下图配置:

Cocos Creator基础教程(12)—精灵变身

此时启动预览,尝试点击这个精灵节点你就能看到图片在不断切换变化了。如果你想玩的再高级一点,可以在一个定时器中调用next方法,它立马就是成了一个序列帧动画了。

3. 直接继承cc.Sprite

我们设计的是通用型组件,最好还是不要访问别的节点、组件的属性和方法,保持干净!这样更具有可扩展性和适应性。

SpriteIndex在这里就是给cc.Sprite做辅助的,它能不脱离cc.Sprite而存在。坚持做到最好,尽可能的让组件更多人能使用,限制越少越好,属性也是越少越好,只要能完成任务就行,看下在的做法,我们改进一下:

//SpriteEx.jslet SpriteEx = cc.Class({        extends: cc.Sprite,    //继承自cc.Sprite

    properties: {                spriteFrames: [cc.SpriteFrame],                _index: 0,                index: {                    type: cc.Integer,
            set(value) {                                if (value < 0) {                                        return;
                }                                this._index = value % this.spriteFrames.length;                //直接访问spriteFrame属性,因为this就是cc.Sprite
                this.spriteFrame = this.spriteFrames[this._index];
            },
            get() {                                return this._index;
            }
        }
    },

    next() {        this.index++
    }
});//下面是控制SpriteEx组件在属性检查器中的属性显示//不显示spriteFrame属性cc.Class.Attr.setClassAttr(SpriteEx, 'spriteFrame', 'visible', false);//不显示Atlas属性cc.Class.Attr.setClassAttr(SpriteEx, '_atlas', 'visible', false);//根据函数返回值控制属性显示、隐藏cc.Class.Attr.setClassAttr(SpriteEx, 'fillType', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});

cc.Class.Attr.setClassAttr(SpriteEx, 'fillCenter', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'fillStart', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'fillEnd', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'fillRange', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'srcBlendFactor', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});
cc.Class.Attr.setClassAttr(SpriteEx, 'dstBlendFactor', 'visible', function() {        return this._type === cc.Sprite.Type.FILLED;
});

上面的核心代码没几行,千万不要被吓到了,后面的属性控制函数主要是减少不必要的属性产生的干扰,提高组件使用时的体验,看下图:

Cocos Creator基础教程(12)—精灵变身

红色框线是我们添加的属性,上面的是cc.Sprite组件原始属性,我们屏蔽了spriteFrame、Atlas属性的显示,这里已经看不到了。

节点下面再挂接一个Button组件,与之前的SpriteIndex的用法一样,运行起来效果相同。不过这里的节点挂载的组件少了一个,使用起来会简单一些,对策划、美术同学来说更贴心啦。

可能有程序员同学会怀疑,「奎特尔星球」是不是被美术、策划给收买了,尽为他们着想。请相信Shawn,我这是在为程序员节省时间,将界面编辑的工作交给擅长的人,这样你就有时间可以去学习更有价值的东西了,比如说写点文章分享到「奎特尔星球」上!

4.小结

本篇介绍了对cc.Sprite组件的扩展,有两种方式,一种是做辅助,一种是继承,他们没有绝对的优缺点,需要根据不同的情景取舍不同的方案。一是实现起来尽可能简单,二是用起来容易,三是能解决实际问题。

其实我们这里仍然是在讲组件化思维,合格的组件化组件将成为非程序员创作游戏内容的利器,它也是提高生产力的秘密。我在想以后是不是做代码审查,美术、策划也能为程序投上一票呢?

继续之前的问卷调查,希望大家能积极参与,感谢您的支持!


欢迎关注「奎特尔星球」微信公众号,更期待你向公众号投稿,来我们一起成长!

Cocos Creator基础教程(12)—精灵变身

热门文章TOP10,邀你遨游「奎特尔星球」

  1. Cococ Creator基础教程—meta的秘密(3)

  2. uikiller再度进化支持Cocos Creator 2.0

  3. 庆祝「奎特尔」500勇士,诞生!

  4. 当creator遇上protobufjs—感谢有你,再战2.0

  5. Cocos Creator基础教程(7)—场景切换

  6. Cocos Creator基础教程(9)—优化代码编辑器

  7. Cocos Creator基础教程(4)—color属性的妙用

  8. Cocos Creator基础教程(1)—从zIndex开始

  9. Cocos Creator基础教程(2)—聊聊scale与size属性

  10. Creator模块介绍—领略模块化的力量

  11. 探索CocosH5正确的开发姿势

本文分享自微信公众号 - Creator星球游戏开发社区(creator-star)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
浩浩 浩浩
3年前
【Flutter实战】图片和Icon
3.5图片及ICON3.5.1图片Flutter中,我们可以通过Image组件来加载并显示图片,Image的数据源可以是asset、文件、内存以及网络。ImageProviderImageProvider是一个抽象类,主要定义了图片数据获取的接口load(),从不同的数据源获取图片需要实现不同的ImageProvi
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
2个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这