HTML5游戏引擎(七)-深度管理——深度顺序 & 添加删除指定深度的对象 & 交换不同深度对象 & 重设子对象深度 & 访问容器子对象

HTML5游戏引擎(七)-深度管理——深度顺序 & 添加/删除指定深度的对象 & 交换不同深度对象 & 重设子对象深度 & 访问容器子对象

深度管理

每一个容器都有深度管理功能,它就像排队一样。

每一个显示对象在其父级的容器中都拥有一个属于自己的深度值,而且这个值相对于同级显示对象是唯一的。深度值实际上就是一个显示对象的叠放次序。也可称为 “z-次序”

深度是由每个容器的子对象列表所管理。每个容器都清楚自己拥有多少个子对象。可以通过容器的 numChildren 属性来获取当前容器的子对象数量。

深度顺序

Egret中容器的深度都是从0开始的,当第一个显示对象被添加到容器中时,它的深度值为0。这个显示对象处于容器的最底层。当添加第二个显示对象的时候,它的深度值为1,并且在第一个显示对象上方。如果两个显示对象发生了相交,那么可以从视觉上看到,第二个显示对象遮挡住第一个显示对象。

下面的示例中,创建了两个显示对象,并且让他们发生遮挡,依次查看显示对象的深度值关系。

var spr1:egret.Sprite = new egret.Sprite();
spr1.graphics.beginFill( 0xff0000 );
spr1.graphics.drawRect( 0, 0, 100, 100);
spr1.graphics.endFill();
this.addChild( spr1 );  // 深度 0
var spr2:egret.Sprite = new egret.Sprite();
spr2.graphics.beginFill( 0x00ff00 );
spr2.graphics.drawRect( 0, 0, 80, 80);
spr2.graphics.endFill();
spr2.x  = 50;
spr2.y = 50;
this.addChild( spr2 ); // 深度1

在这里插入图片描述

添加/删除指定深度的对象

使用的 addChild() 方法会默认按照当前子对象深度进行排序,从0开始,每次深度加1,以此类推。

若要将某一个显示对象添加到一个指定深度的时候,需要使用 addChildAt() 方法。

在这里插入图片描述

addChildAt()具体使用方法如下:

容器.addChildAt( 显示对象, 深度值 )

在下面的示例中,随机绘制四个颜色不同的正方形,将它们依次叠加排列,然后新建一个显示对象,并且放到深度为1的位置。

var sprcon:egret.Sprite = new egret.Sprite();
this.addChild( sprcon );
sprcon.x = 10;
for(var i:number = 0; i<4; i++)
{
    var spr:egret.Sprite = new egret.Sprite();
    spr.graphics.beginFill( 0xffffff * Math.random() );
    spr.graphics.drawRect( 0, 0, 100, 100);
    spr.graphics.endFill();
    spr.x = i*20;
    sprcon.addChild( spr );
}
var sprNew:egret.Sprite = new egret.Sprite();
sprNew.graphics.beginFill( 0xff0000 );
sprNew.graphics.drawRect( 0, 0, 300, 150 );
sprNew.graphics.endFill();
sprNew.x = 10;
sprNew.y = 50;
sprcon.addChildAt( sprNew, 1 );

在这里插入图片描述

在删除显示对象时同样可以通过深度来进行控制。

可以使用 容器.removeChild( 显示对象 ) 将一个显示对象移除显示列表,同样,还可以使用

容器.removeChildAt( 深度值 ) 来删除一个指定深度的显示对象。

通过对上面示例代码的修改,将深度值为2的显示对象移除显示列表。

var sprcon:egret.Sprite = new egret.Sprite();
this.addChild( sprcon );
sprcon.x = 10;
for(var i:number = 0; i<4; i++)
{
    var spr:egret.Sprite = new egret.Sprite();
    spr.graphics.beginFill( 0xffffff * Math.random() );
    spr.graphics.drawRect( 0, 0, 100, 100);
    spr.graphics.endFill();
    spr.x = i*20;
    sprcon.addChild( spr );
}
var sprNew:egret.Sprite = new egret.Sprite();
sprNew.graphics.beginFill( 0xff0000 );
sprNew.graphics.drawRect( 0, 0, 300, 150 );
sprNew.graphics.endFill();
sprNew.x = 10;
sprNew.y = 50;
sprcon.addChildAt( sprNew, 1 );
sprcon.removeChildAt( 2 );

在这里插入图片描述

若要一次性将一个容器内的所有子对象全部删除。

Egret 提供了一个方便快捷的方法,使用 removeChildren() 方法可以将当前容器内的所有子对象全部移除显示列表。

使用方法如下:

容器.removeChildren();

依然使用上面的示例,继续在后面编写代码:

sprcon.removeChildren();

编译并运行,舞台sprcon内没有任何显示对象显示。

交换不同深度对象

Egret 为开发者提供了两个方法实现交换不同对象深度的功能。一个是 swapChildren() 方法,另外一个是 swapChildrenAt() 方法。

具体使用方法如下:

容器.swapChildren( 显示对象, 显示对象 )
容器.swapChildrenAt( 深度值, 深度值 )

下面示例中,创建一个sprcon容器,并向其中绘制两个颜色不同的方块。然后分别使用上面两个方法互换两个方块的深度值。

var sprcon:egret.Sprite = new egret.Sprite();
this.addChild( sprcon );
sprcon.x = 10;
var spr1:egret.Sprite = new egret.Sprite();
spr1.graphics.beginFill( 0xff0000 );
spr1.graphics.drawRect( 0, 0, 100, 100 );
spr1.graphics.endFill();
spr1.x = 50;
sprcon.addChild( spr1 );
var spr2:egret.Sprite = new egret.Sprite();
spr2.graphics.beginFill( 0x00ff00 );
spr2.graphics.drawRect( 0, 0, 100, 100 );
spr2.graphics.endFill();
spr2.x = 100;
spr2.y = 50;
sprcon.addChild( spr2 );

使用第一种方法进行两个方块的深度互换:

sprcon.swapChildren( spr1, spr2 );

使用第二种方法进行两个方块的深度互换:

sprcon.swapChildrenAt( 0, 1 );

重设子对象深度

当一个显示对象添加到显示列表中后,可以手动重设这个显示对象的深度。

实现显示对象深度重置的方法是 setChildIndex() ,使用方法如下:

容器.setChildIndex( 显示对象, 新的深度值 );

示例代码如下:

var sprcon:egret.Sprite = new egret.Sprite();
this.addChild( sprcon );
sprcon.x = 10;
var spr1:egret.Sprite = new egret.Sprite();
spr1.graphics.beginFill( 0xff0000 );
spr1.graphics.drawRect( 0, 0, 100, 100 );
spr1.graphics.endFill();
spr1.x = 50;
sprcon.addChild( spr1 );
var spr2:egret.Sprite = new egret.Sprite();
spr2.graphics.beginFill( 0x00ff00 );
spr2.graphics.drawRect( 0, 0, 100, 100 );
spr2.graphics.endFill();
spr2.x = 100;
spr2.y = 50;
sprcon.addChild( spr2 );
sprcon.setChildIndex( spr1, 1 );

上面这段代码中默认是绿色的方块遮盖在红色方块上方的,通过对spr1(红色方块)的深度重置(重置为1)将其放置于绿色方块上方。

访问容器子对象

Egret 提供两种访问容器子对象的方法: getChildAt()getChildByName() 方法。

具体使用方法如下:

容器.getChildAt( 深度值 );`
`容器.getChildByName( 显示对象 )

下面示例代码中,向一个容器中存放了两个方块,通过深度来获取其中一个方块,并调整它的透明度。

var sprcon:egret.Sprite = new egret.Sprite();
this.addChild( sprcon );
sprcon.x = 10;
var spr1:egret.Sprite = new egret.Sprite();
spr1.graphics.beginFill( 0xff0000 );
spr1.graphics.drawRect( 0, 0, 100, 100 );
spr1.graphics.endFill();
spr1.x = 50;
spr1.name = "sprite1";
sprcon.addChild( spr1 );
var spr2:egret.Sprite = new egret.Sprite();
spr2.graphics.beginFill( 0x00ff00 );
spr2.graphics.drawRect( 0, 0, 100, 100 );
spr2.graphics.endFill();
spr2.x = 100;
spr2.y = 50;
spr2.name = "sprite2";
sprcon.addChild( spr2 );
var _spr:egret.DisplayObject = sprcon.getChildAt( 1 );
_spr.alpha = 0.5;

下面示例代码中,通过显示对象的 name 获取其中一个方块,并调整它的透明度。

var sprcon:egret.Sprite = new egret.Sprite();
this.addChild( sprcon );
sprcon.x = 10;
var spr1:egret.Sprite = new egret.Sprite();
spr1.graphics.beginFill( 0xff0000 );
spr1.graphics.drawRect( 0, 0, 100, 100 );
spr1.graphics.endFill();
spr1.x = 50;
spr1.name = "sprite1";
sprcon.addChild( spr1 );
var spr2:egret.Sprite = new egret.Sprite();
spr2.graphics.beginFill( 0x00ff00 );
spr2.graphics.drawRect( 0, 0, 100, 100 );
spr2.graphics.endFill();
spr2.x = 100;
spr2.y = 50;
spr2.name = "sprite2";
sprcon.addChild( spr2 );
var _spr:egret.DisplayObject = sprcon.getChildByName( "sprite2" );
_spr.alpha = 0.5;

  • 两种获取方式对比

    通过深度值和 name 属性获取子对象的作用是相同的,但Egret在内部的实现原理却大大不同。

    使用深度值获取子对象时,Egret会根据当前容器的显示列表查找指定深度的显示对象,并作为返回值返回给用户。这种检索方式是快速的,不需要进行大量运算。

    通过name属性来获取子对象,Egret内部首先会对当前容器的所有子对象进行编译,同时匹配相同的 name 属性值,当发现相同 name属性的时候,则将该子对象作为返回值返回给用户。虽然在Egret内部进行了相关算法优化,但还是在消耗了一些性能。

    因此推荐使用第一种方法,通过深度值来获取子对象。

zindex

重设子对象深度有2种方法:使用 setChildIndex 和使用 zIndex.

从 Egret 5.2.24 版本开始,DisplayObject 中新增加了一个 zIndex 属性,可以设置对象的 Z 轴顺序。该值越大,越靠近顶部。

在 PC 的 Chrome 浏览器和安卓系统中,zIndex 的效率比 setChildIndex 高很多。极限测试时可以达到10倍以上。

在 iOS 系统中,两种方式的效率基本一致,没有很大区别,这跟系统浏览器的内核有关。

注意,要给一个对象使用 zIndex,包含此显示对象的 DisplayObjectContainer 对象一定要设置 sortableChildren = true,开启排序功能,否则设置 zIndex 是无效的

let container = new egret.Sprite();
container.sortableChildren = true;//注意,一定要设置为true
this.addChild(container);
let texture: egret.Texture = RES.getRes('bird_png');
let b1 = new egret.Bitmap();
b1.texture = texture;
b1.x = 100;
this.addChild(b1)
let b2 = new egret.Bitmap();
b2.texture = texture;
b2.x = 270;
this.addChild(b2)
let b3 = new egret.Bitmap();
b3.texture = texture;
b3.x = 440;
this.addChild(b3)
b2.zIndex = 3;//将第二个图片设置到顶部
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值