Skip to content

Container

何波 edited this page Mar 1, 2019 · 12 revisions

Container实质

Container中有一个this.children = []的数组,Container的作用就是向children数组中addChildremoveChildremoveAllChildrensortChildrengetChildIndexswapChildrenAtsetChildIndex等操作

Container.getObjectsUnderPoint ( x y [mode=0] ) Array

返回此Container中指定坐标(x,y)下所有DisplayObject的数组。如果该Container中的DisplayObject设置mouseEnabled = true将会忽略。数组将按可视深度的顺序排序,最上面的DisplayObject索引为0。这是用最基础的形状检查,并且运行起来可能是一个昂贵的操作,所以你最好小心使用它。例如,if testing for objects under the mouse, test on tick (instead of on stagemousemove), and only if the mouse's position has changed.

  • 默认情况下(mode=0),此方法计算所有显示对象DisplayObject。
  • mode=1,将遵守mouseEnabled和mouseChildren属性值。
  • mode=2,会排除DisplayObject没有mouse event listeners 或DisplayObject:Cursor:Property属性的显示对象。也就是说,只包括通常会拦截鼠标交互的对象。在某些情况下,这可以通过减少需要测试的显示对象的数量来显著提高性能。

这个方法同时解释了hitareamask

hitTest ( x y )

Inherited from DisplayObject but overwritten in hitTest:450

测试display object是否与指定的局部点local point相交(即在指定位置绘制alpha>0的像素)。这将忽略显示对象的alpha、shadow和compositeoperation,以及包括regx/y在内的所有转换属性。

Container.prototype.hitTest = function(x, y) {
  // TODO: optimize to use the fast cache check where possible.
  return (this.getObjectUnderPoint(x, y) != null);
};

而DisplayObject.prototype.hitTest为

p._testHit = function(ctx) {
  try {
    var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1; // 判断图像坐标0,0位置1像素大小的透明度是否大于1
  } catch (e) {
    if (!DisplayObject.suppressCrossDomainErrors) {
      throw "An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images.";
    }
  }
  return hit;
};

getObjectUnderPoint ( x y mode ) DisplayObject

getObjectsEnderPoint类似,但只返回最上面的显示对象。这比getObjectsUnderPoint()运行得快得多,但仍然可能是一个昂贵的操作。

有的游戏的就可以getObjectUnderPoint来进行粗略的碰撞检测,如TrashDash这个游戏

var target = obstacles.getObjectUnderPoint(hero.x, hero.y, 1);
if (target && !dead) {
  if (target.trash) {
    target.parent.removeChild(target);
    changeWeight(0.2);
    playSound("crunch");
  } else if (!inDash) {
    die();
  }
}

因为这种点与面进行碰撞检测,与实际的面与面进行碰撞检测有较大的误差。可以把障碍物中添加一个hitbox比实际的障碍物大一号,注意hero的regX和regY为中心点

var wall = new lib.Wall();
wall.hitArea.visible = false;
wall.cache(0, 0, 190, 640);
wallImg = wall.cacheCanvas;
wallHitArea = wall.hitArea;

mouseChildren:true

指示该container中的children对象单独启用鼠标/指针交互,如果设为false,类似于事件冒泡,如果children中的click触发,则Container也会触发。如果一个Button是一个Container,其addChild(label),如果Button.mouseChildren = false。则点击Button的click事件会执行,而label的click事件不会执行。即Container事件不会向children传递。

numChildren

Returns the number of children in the container.

tickChildren: true

如果false,则Container中的tick事件不会传递到children,这可以提供一些性能优势。除了防止发送“tick”事件外,它还将防止某些显示对象上与tick相关的update。(ex. Sprite & MovieClip frame advancing, DOMElement visibility handling)

p._tick = function(evtObj) {
    if (this.tickChildren) { // 是否允许children更新tick事件
        for (var i=this.children.length-1; i>=0; i--) {
            var child = this.children[i];
            if (child.tickEnabled && child._tick) { child._tick(evtObj); }
        }
    }
    this.DisplayObject__tick(evtObj);
};

Clone this wiki locally