2008/09/09 | 利用遮罩实现的镜面效果
类别(Flash课件设计) | 评论(1) | 阅读(318) | 发表于 23:52

  在蚕子老师的博客里看到的想法,用遮罩实现了一下,鱼骨头可以拖拽,镜面尚不能拖动。

对影子使用遮罩,遮罩要足够大,并且和镜面平齐,这样影子就不会跑到左边来了,这里不需要代码计算。

实现的代码如下:

fishBone.addEventListener(MouseEvent.MOUSE_DOWN,onMD);
fishBone.addEventListener(MouseEvent.MOUSE_UP,onMU);
fishBone.addEventListener(MouseEvent.MOUSE_MOVE,onMM);
var isDown = false;
fishShadow.mask = maskMC ;
fishShadow.x = 2 * mirrorMC.x - fishBone.x

function onMD(evt:MouseEvent){
 fishBone.startDrag(false,new Rectangle(0, 0, stage.width, stage.height));
 isDown = true;
}
function onMU(evt:MouseEvent){
 fishBone.stopDrag();
 isDown = false;
}
function onMM(evt:MouseEvent){
 if( isDown ){
  fishShadow.x = 2 * mirrorMC.x - fishBone.x
  fishShadow.y = fishBone.y;
 }
}

  再来考虑一下镜面旋转的问题,当镜面旋转时,影子也要旋转,并且距离会发生变化,从数学的用度来想,镜面是一个线状形态,目标物是一个位置点,这是一个点到线的距离运算关系,通常需要先算出物体到镜面的距离,这个距离等于影子到镜面的距离,然后再根据当前镜面的角度换算出影子的位置。

  影子的旋转角度倒是个简单的算术,镜子每旋转1度,影子会旋转2度,这可以通过观察得知,当镜子和目标的夹角是45度,影子的目标对象垂直。当镜子和目标的夹角是90度(镜子平放),影子刚好倒影在目标物的下方。

  是不是必须进行点到线的位置运算呢?在 Flash 里,这是不需要的,如果你对全局坐标和局部坐标的换算了解的话,这里存在有一个非常简单的算法。当镜面竖直摆放时,我们的镜面MC 原坐标点放在镜面的中间,观察一下目标 和 影子之间的位置关系,可以发现,影子的 x 值恰好是目标对象 x 的负数,二者的 y 值相等。我们知道当一个 MC 发生旋转时,它的坐标系也会同时跟着旋转,那么在这个发生了旋转的坐标系里面,仍然符合目标对象和影子对象的 x 值取负,y 值相同的规律。

  运动总是相对的,如果我们把镜子的旋转,看成是目标对象的移动+旋转,那么镜面是不动的,目标对象只是绕着镜面的原点在做圆周运动,相对而言,影子的移动关系就是将目标对象的 x 值取反,y 值保持相同,就是这么个关系。

  影子移动的核心算法如下:

var globalPt = new Point( fishBone.x,fishBone.y );    //先获取鱼骨 的全局坐标
  var localPt = mirrorMC.globalToLocal( globalPt );  //在镜子的坐标系中计算出镜子的本地坐标
  localPt.x = -localPt.x;   //镜了坐标系中符合我们上面讨论的,x 取反,y 不变的规律
  globalPt = mirrorMC.localToGlobal( localPt );  //将镜子中的局部坐标换算回舞台坐标,(因为影子对象实际上是在舞台上放着)
  fishShadow.x = globalPt.x;  //改变影子的坐标位置
  fishShadow.y = globalPt.y;
  fishShadow.rotation =  mirrorMC.rotation *2;  //改变影子的旋转角度
  maskMC.rotation = mirrorMC.rotation;   //遮罩也同步改变一下

  镜子的旋转需要用到三角函数,代码如下:

var pt:Point = new Point(stage.mouseX,stage.mouseY);
  var ang = Math.atan2(pt.y - mirrorMC.y,pt.x - mirrorMC.x );  //位置运算时,取的是相对
  mirrorMC.rotation = ang * 180 / Math.PI + angOffset;

  镜子的上、下半部拖拽时,算法应该是不同的,如果用同一个算法,会发现镜子会有反转的情况,因为拖动上半部分时,角度换算如果是正确的,用到下半部分时,角度实际上会有个180度的差值,这个差值的存在导致镜面发生反转。

  解决的办法是这样的,在镜子 mc 内部,分成上下两部分别构成独立的 mc ,我的镜头初始状态是竖立的,那么拖动上半部,换算出的角度值需要 +90度,才是正确的 rotation 值,下半部需要 -90度,才是正确的结果。我们把这个值当做是对计算角度的修正(angOffset),合并到角度计算函数中去。当点击开始于上半部分的镜片,则 angOffset   值为 90,当点击开始于下半部分的镜片,则 angOffset   值为 -90,当鼠标按下并拖动时,才真正的参与运算。

  完成后的效果如下:镜面可拖拽进行旋转。

 压缩包下载

0

评论Comments