视角移动是一个flash游戏应用中常用的技巧。我们知道,有时候,游戏给出的场景会比较大,超出我们舞台的范围,此时就需要使用拖拽功能来调整视角。(就像农场类游戏)。
先看一下结果预览:http://www.iamsevent.com/upload/CameraMovement.swf
      首先呢,我们依然用图解的形式来看看视角调整的本质所在。

通过图我们可以看到,背景图片被添加进来之后默认会放在(0,0)也就是左上角的位置,此时由于图片大小超出了舞台大小,所以有一部分被隐藏掉了。
      当我们想要移动视角的时候,比如我们想看背景图片的右下角,那么此刻视野所在范围会被从左上角拉到右下角,我们发现,随着视角的移动,背景图片在不断移动,而舞台位置是不会发生任何变化的,这下问题变得简单了,原来视角的移动是背景图片的x,y位置变化引起的!那么如何改变背景图片的坐标才能正确地操作视角能够浏览全部场景呢?
      让我们边做边说吧。你可以任意拖动一张足够大的图片到flash CS工具的库(library)中,建立一个元件并把库中你刚才拖进来的图片放到这个元件里去,这样你的图片就成了一个元件了。之后将此元件拖到舞台上,给他取个ID名,就叫background吧。好了,准备工作做好后 let`s 看看我们应该在第一帧上写入什么脚本代码。
      首先我们看上面给出的图解,我们看到当我们的视野停留在背景左上角的时候是一个临界情况,这已经到达了我们视野所能看到的最左边,最上边了,再看不到更左边的东西了,此时背景图片的坐标为(0,0);
         另一个临界情况是我们的视野来到了背景的最右下角,再也不能看到更右边更下边的东西了,此时背景图片的横坐标是 -(场景宽 - 舞台宽),即:舞台宽 - 场景宽(注意这里是负的坐标哦,因为图片的左上角在(0,0)点的左上边),同理,其纵坐标就是舞台高 - 场景高。
      那么此时,我们就可以确定背景图片的横坐标移动范围是0到 (stage.stageWidth - background.width), 
      纵坐标是0 到 (stage.stageHeight - background.height)。
      若你想通过鼠标位置来控制背景坐标的改变,就需要以下代码:

  1. background.x = mouseX / stage.stageWidth * (stage.stageWidth - background.width); 
  2. background.y = mouseY / stage.stageHeight  * (stage.stageHeight - background.height); 

虽然我很想用一句“你懂的”来解释这两行代码,但是如果这样做我想明天就会在我的帖子前面看到一堆大便。我们来看mouseX / stage.stageWidth 这个算式是什么意思,首先我们确定鼠标的移动范围只有舞台这一块地方,那么mouseX的取值范围就一定是0到stage.stageWidth ,所以上面这个算式算的就是一个比例值,一个当前鼠标横坐标处于舞台宽度几分之几的位置,用这个比例值去乘以我们背景图片最小横坐标值即可算出当前背景图片移到了什么位置。假如鼠标停留在最左边,mouseX等于0造成了background.x也将会等于0,通过观察图片此时的位置我们发现这没错,视野停在背景的最左边位置;把鼠标移到最右边,mouseX等于stage.stageWidth 则background.x = 1 * (stage.stageWidth - background.width),这也没错,背景图片向左移到了它所能到达的最远地方,此时视野也停在场景最右边了。如果你继续不停地实验都不会出错,鼠标移到了舞台宽度的1/3处,背景响应也会左移它所能到达的最远距离的1/3处。同理,纵坐标也是这么运算出来的。最后,你可以把上述两行代码放到一个enterFrame的监听函数中去,测试影片,看到视角正随着我们的鼠标移动而移动。
      如果你觉得功能不够强大,就可以继续跟着我做,我们把视角的移动做成和大多数游戏那样,要保持按下鼠标左键才能一点点地拖动视角(就像开心农场一样)。首先我们要做的当然是添加事件侦听,让鼠标按下时候开始进入拖拽状态,进入此状态后再任意移动鼠标就可以移动视角;再让鼠标松开后结束拖拽的状态。

  1. this.addEventListener(MouseEvent.MOUSE_DOWN, startDragMap); 
  2. this.addEventListener(MouseEvent.MOUSE_UP, stopDragMap); 

在startDragMap()监听函数中我们需要做什么呢?我们先用手搭住下巴思考一下先:嗯……我需要按下鼠标后左移一点点视野就会往左边过来一点点(即让背景图片往左边移动),上移一点点视野就会往上过来一点点(即让背景图片往上移动一点点)。那么我们就需要在鼠标按下的位置记录下此位置,并添加上MOUSE_MOVE事件,表明我们已经进入了视野拖拽状态,此后的每一次鼠标移动都会触发此事件,然后在此事件的处理函数中调整视野。

  1. var oldX:Number; 
  2. var oldY:Number; 
  3. function startDragMap(event:MouseEvent):void 
  4.    { 
  5.     addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); 
  6.     oldX = stage.mouseX;//这里用mouseX也可以,但是使用stage.mouseX获得鼠标在舞台上的横坐标更加精确一点 
  7.     oldY = stage.mouseY; 
  8.    } 

在onMouseMove()监听函数中我们要做的就是控制视野啦,因为我们调整视野的幅度需要根据你进入视野拖拽状态后移动鼠标的幅度大小来确定,如,你按下鼠标后往左移动了5,那么背景图片就向右移动5。

  1. function onMouseMove(event:MouseEvent):void
  2.     var distX:Number = stage.mouseX - oldX; 
  3.     var distY:Number = stage.mouseY - oldY; 
  4.     background.x = Math.min( Math.max( stage.stageWidth - background.width,  background.x + distX ), 0 ); 
  5.     background.y = Math.min( Math.max( stage.stageHeight - background.height,  background.y + distY ), 0 ); 
  6.     oldX = stage.mouseX; 
  7.     oldY = stage.mouseY; 
  8.    } 

通过代码我们看到,前两行做的工作就是我们刚才说的计算你视野调整的幅度,用stage.mouseX - oldX得到幅度值,不要写反哦。接下来两行对一些新童鞋来说看起来有点不知所措,那我们一段段看:我们想假设我们按下鼠标键后右移了,那么distX的值就是个正数,要想让背景图片右移就得让background.x增大,它的值将会等于 background.x + distX ,Math.min()与Math.max()这两个函数分别能够求出其参数中的最小最大值,我们为了限制background.x的最小值不低于stage.stageWidth - background.width,就可以把算式写成background.x = Math.max( stage.stageWidth - background.width,  background.x + distX ),当第二个参数低于最小值时会去第一个参数的值赋值给background.x;之后,再在其外面套上一层Math.min来限制其最大值。之后,我们还需要更新oldX, oldY的值以便下一次鼠标移动时保证dist值的正确性。
    最后,我们要写上鼠标松开后停止拖拽的函数,所做的事情非常简单,仅仅是移去MOUSE_OVER的事件监听就行了。

  1. function stopDragMap(event:MouseEvent):void 
  2.    { 
  3.     removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); 
  4.    } 

将我们上面提到的代码组装起来就可以测试影片了,如果你成功了,恭喜你自己吧,你又掌握了一招。

这里提供第二种也是使用率更高一些的视角移动方式:

  1. import flash.geom.Rectangle; 
  2. function startDragMap(event:MouseEvent):void 
  3.    { 
  4.          var w:Number =  stage.stageWidth - background.width; 
  5.          var h:Number = stage.stageHeight - background.height; 
  6.         background.startDrag( falsenew Rectangle(w, h,  -w, -h) ); //别忘了在使用此方法前要把background的类型改成Sprite哦 
  7.     } 
  8.  
  9. function stopDragMap(event:MouseEvent):void 
  10.    { 
  11.          background.stopDrag(); 
  12.     } 

这种方法的优势是显而易见的,就是代码简单易懂。不过有的朋友不清楚startDrag()这个陌生的方法有什么用,我们可以通过帮助手册来看看它的用法和参数。这是Sprite类独有的方法,我们之前在FLASH CS中创建的大部分元件都默认类型为MovieClip,若为此类型的话是不能使用startDrag()方法的,所以要使用该方法的话得在创建新元件的时候把类型选择为Sprite才行。该方法第一个参数是用来选择是否将可拖动的 Sprite 锁定到鼠标位置中央,我们一般都保留其默认值,传入参数false或者不传。第二个参数对我们比较有用,是传入一个矩形对象(Rectangle),用以指定目标Sprite可移动的范围。我们从上面给出的示意图中可以看到,背景图片可移动的范围就是在(0,0)点和( stage.stageWidth - background.width,  stage.stageHeight - background.height)这两点所确定的矩形范围内,那么我们就可以初始化一个矩形对象并传给startDrag()方法,该矩形对象的左上角坐标在(w, h)处(也就是(stage.stageWidth - background.width, stage.stageHeight - background.height)处,我缩写一下省点篇幅),长度和宽度分别为-w和-h(因为w和h是负数,你若写成Math.abs(w), Math.abs(h)更保险一些,不过就是稍微比前者会消耗一点计算时间)。如此,我们就让鼠标按下时可以拖动背景图片,且限定其移动范围在允许的范围之内,测试一下影片,和之前的运行效果一样的。
      虽然第二种方法使用的代码少,很多人喜欢用,但是不得不承认一点,就是使用第一种方法在调整视野时改变的仅仅是背景图的坐标而已,而第二种方法使用了内置的startDrag()方法来拖拽背景图片就使flash player自动进行一系列的运算,很有可能改变的不仅仅是背景图的坐标这一个属性而已了,所以第二种方法的效率不如第一种高,若在使用第二种方式拖拽时发现有点卡,试着用第一种方式吧。