我们经常会用到容器的概念,在Phaser中,最常用作容器的就是Group和Sprite。Word就是游戏中最底层的一个容器。 在此,整理了一下Sprite和Group用作容器的异同,纯属个人理解,供参考。
添加子对象的方法
Sprite常用方法是addChild() Group添加子对象的方法很多个,如add()、addChild()、create()……
两者都继承了DisplayObjectContainer
Sprite和Group的容器功能都继承自DisplayObjectContainer,但DisplayObjectContainer的一些原有的属性方法在Sprite中被重写了,比如width、height、getBounds()等;而Group则完整的继承了DisplayObjectContainer的属性方法,如果单纯作为容器使用,Group应该更合适,更专业。
关于Texture和层级关系
Sprite有自己的texture,显示内容将会在它所有children的最底层,相当于背景(根据先画的垫底,后画的在上的渲染规则,以及先有父才有子的关系,所以不难理解) 而Group 没有自己的texture,他只是一个纯容器,如同空气没有显示的东西,所以他自身跟children没有显示上的层级关系,只有children们各自之间的层级关系
与children的坐标关系
Sprite 的children坐标位置是相对于父级Sprite的,即会随父级Sprite的移动而移动。(这是常用的而且合乎常理的逻辑) Group的坐标默认都是0的,因为创建时没有坐标的参数,(之前没做测试,以为没有用的,惭愧),其实跟sprite一样它的子对象坐标都是相对坐标,它的所有子对象都会跟随父级group移动的。 注意:一般很少改变group的坐标,可能大多情况下我们只关注它的子对象,而不是这个group本身,而且碰撞检测都是针对子对象分别进行的(group没有自身的物理属性);如果改变了group的坐标,读取子对象的坐标时,就要注意,你要的是xy还是world.x和world.y了。
关于包含children的总尺寸
有时,我们需要知道添加的children后这个Sprite总的尺寸,比如一些有多个显示对象组成的sprite组合体(里面可能有各种显示对象如sprite、text、image等)。 如果Sprite作为容器,你无法用width/height得到他包含了children的总尺寸; 但是group却可以!因为刚才说了,Group完整的继承了DisplayObjectContainer的属性方法,他的width、height就是干这个的(而在sprite中这些属性方法被覆盖重写了)。所以说作为容器,Group更专业!
问题来了
那么,我们想要一个组合的Sprite,需要子对象的坐标位置都随父级变化,有自己的物理属性,又想方便地知道这个Sprite包含所有子对象的总尺寸,怎么办? 也许你应该想到了,用这两者的组合!(OK,讲这么多,该上点代码了……) 具体实现是:
var sprite = game.add.sprite(x,y); sprite.childrenGroup = sprite.addChild(game.make.group()); // 添加一个Group作为sprite唯一的下级子对象 sprite.childrenGroup.add(child); // 所有子对象通过这种方式添加到这个Group中 var allWidth = sprite.childrenGroup.width; // 获取这个Group的尺寸就是总尺寸了,可以根据总尺寸更新父级的body
OK, just enjoy it !
很棒的总结,这里我也说一下我的理解。 Sprite作为容器,它的孩子一般是一个整体的一部分,比如,一个飞机,可以有机身、机翼、螺旋桨,如果这些都是单独的素材,那么我们可以把飞机定义为一个Sprite,然后机身、机翼、螺旋桨作为它的孩子,通过addChild来加入。它的特点是共享父精灵的物理属性(比如位移、旋转),并且它们之间的相对位置固定。 而如果是一群飞机,这时候我们建议用Group,每一个飞机都是独立个体,有自己的位移、旋转等,并且它们的相对位置并不固定,有时可以挨得很近,有时可以离得很远。
之前以为group的坐标似乎是没有用,以为他的子对象的坐标不是相对group的,是我之前理解错了!(前文已纠正) 因为创建Group时是没有坐标参数的,默认为0,而且一般情况下不需要操作group的坐标,所以开始会让人有个错觉。