2011-07-18 110 views
0

我有一个水池,在这里鱼会移动到一个“食物”,目前我的问题看起来很现实,当食物掉落时,所有的鱼都以相同的速度移动,这是一种“漂移”就像一辆汽车漂流,当它靠近食物而旋转时。我可以知道什么是错的吗?我认为这是因为我应用的阻力,但如果我不应用它,vx和vy将加起来大量。旋转计算或游戏的阻力?

以下链接包含.swf,我还附加了使鱼类移动所需的巢穴功能。 http://www.swfcabin.com/open/1310970656

package 
{ 

    import flash.display.MovieClip; 
    import flash.display.Stage; 
    import flash.events.Event; 
    import flash.filters.DropShadowFilter; 
    import flash.events.TouchEvent; 
    import flash.media.Sound; 
    import flash.text.TextField; 
    import flash.utils.Timer; 
    import flash.events.TimerEvent; 
    import flash.geom.Point; 

    /** 
    * ... 
    * @author Z 
    * Fish class, makes fishes behaviors, find food. 
    */ 
    public class Fish extends MovieClip 
    { 

     //food var 
     private var foodTarget:Food; 
     public var foodDroppedArray:Array = new Array(); 
     public var foodDistArray:Array = new Array(); 
     private var foodInPond :int = 0; 
     private var foodLocationDegrees:Number; 
     //fish variables 
     private var _fishSwimMax:Number = 3; 
     private var _fishDrag:Number = 0.95; 
     private var _fishSwimSpeed:Number; 
     private var _destinationX:int; 
     private var _destinationY:int; 
     private var _minX:Number = 0; 
     private var _minY:Number = 0; 
     private var _maxX:Number = 1024; 
     private var _maxY:Number = 768; 
     private var _vx:Number = 0; 
     private var _vy:Number = 0; 
     private var _dx:Number = 0; 
     private var _dy:Number = 0; 
     private var foodropSound:foodSound = new foodSound(); 
     //global 
     public var otherFishes:Array = new Array(); 
     public var hit :MovieClip; 
     private var foodRipple:Rippler; 
     private var _bg:Background; 
     private var number:Number; 
     private var _easeSpeed:Number; 


     public function Fish() 
     { 

      foodropSound = new foodSound(); 

      getRandomDestination(); 
      //fish starting settins 
      this.x = _maxX/2;//Math.random(); 
      this.y = _maxY/2;//Math.random(); 
      _fishSwimSpeed = Math.ceil(Math.random() * 1000) +500; 
      trace("fish speed "+_fishSwimSpeed); 
      //set up shadow 
      setUpShadow(); 

      //adding listener 
      this.addEventListener(Event.ENTER_FRAME, loop, false, 0, true); 


     } 

     public function loop(e:Event):void 
     { 

      updateCollision(); 
      //getDistance(this.x - i.x, this.y - i.y) 
      if(foodDroppedArray.length > 0) 
      { 
         moveToFood(getSmallestVal(foodDroppedArray)); 
         trace("moving to smallest distance of all food"); 
         return; 
      }else 
      { 
      swimAround(); 
      } 

     } 

     /*** 
     * Fish to move to food with easing. 
     * */ 
     public function moveToFood(targetFood:Food):void 
     { 
      _vx += (targetFood.x - this.x)/_fishSwimSpeed; 
      _vy += (targetFood.y - this.y)/_fishSwimSpeed; 
      //food calculations, distance, angle etc 
      var a:Number = targetFood.x - x; 
      var b:Number = targetFood.y - y; 
      var ang:Number = Math.atan2(b, a); 
      //rotation to food 
      var foodLoc:Number = (ang * 180/Math.PI); 
      var foodFinalLoc:Number = foodLoc - rotation; 
      if (foodFinalLoc > 180) foodFinalLoc -= 360; 
        else if (foodFinalLoc < -180) foodFinalLoc += 360; 
      rotation += foodFinalLoc/10; 
      //acceleratin to food 

      //moving towards food. 
      _vx *= _fishDrag; 
      _vy *= _fishDrag; 
      this.x += _vx; 
      this.y += _vy; 
      //removing food when both hit boxes hit 
      if (hit.hitTestObject(targetFood.hit)) 
      { 
       foodropSound.play(); 
       foodDroppedArray.splice(foodDroppedArray.indexOf(targetFood), 1); 
       targetFood.removeSelf(); 
      } 

     } 
     /** 
     * Calculate Position 
     */ 
     public function swimAround():void 
     { 
      //move to a random destionation point. 
       _dx = this.x - _destinationX; 
       _dy = this.y - _destinationY; 
      // when the fish is near to the distance by * a new dest will be generated. 
      if (getDistance(_dx, _dy) < 200) 
      { 
       getRandomDestination(); 

      }else { 
       _vx += (_destinationX - this.x)/_fishSwimSpeed; 
       _vy += (_destinationY - this.y)/_fishSwimSpeed; 
       //calculation of distance to use for calculation of angle to face to 
       var a:Number = _destinationX - x; 
       var b:Number = _destinationY - y; 
       var ang:Number = Math.atan2(b, a); 

       //location to face to through the angle calculation. 
       var targetLoc:Number = (ang * 180/Math.PI); 
       var finalRoc:Number = targetLoc - rotation; 
       if (finalRoc > 180) finalRoc -= 360; 
        else if (finalRoc < -180) finalRoc += 360; 
       rotation += finalRoc/15; 
       //apply drag then move. 
       _vx *= _fishDrag; 
       _vy *= _fishDrag; 
       this.x += _vx; 
       this.y += _vy; 
      } 
     } 

     public function foodDropped(foodArray:Array):void 
     { 
      foodDroppedArray = foodArray; 
      trace("food have been dropped and lenghth is "+foodDroppedArray.length); 
     } 
     /** 
     *Get smallest value of food distance in this array 
     */ 
     private function getSmallestVal(a:Array):Food 
     { 
      //we assume first food is the smallest distance between fish 
      var n : Food = a[0]; 
      if (a.length == 1) 
      { 
       return a[0]; 
      } 
      else { 
       for each(var i : Food in a) 
       { 
        if (getDistance(this.x - i.x , this.y - i.y) < getDistance(this.x - n.x , this.y - n.y)) 
        { 
         n = i; 
        } 
       } 
       return n; 
      } 
     } 
     /** 
     * Get random food 
     */ 
     private function getRandomFood():Food 
     { 
      var i: int = foodDroppedArray.length; 
      var n : Number = Math.ceil(i * Math.random()) - 1; 
      trace(" in random food "+n); 
      return foodDroppedArray[n]; 


     } 

     /** 
     * Calculates a random destination based on stage size 
     */ 
     private function getRandomDestination():void 
     { 

      _destinationX = (Math.random()* _maxX); 

      _destinationY = (Math.random() * _maxY); 

     } 
     public function getDistance(delta_x:Number, delta_y:Number):Number 
     { 
      return Math.sqrt((delta_x*delta_x)+(delta_y*delta_y)); 
     } 



    } 

} 
+1

我认为问题在于,你正在将一堆运动概念混合在一起,这并不适合。您的加速度基于距离除以500-1500之间的随机数,这是我不太了解的。如果你想要,我可以写一个简单的抵达行为,在moveToFood期间留下拖延。 –

+0

嗨,分区号是随机产生的,这是为了给每个“鱼”一个不同的数字,通过这样做,我希望给每个“鱼”不同的移动速度。这个数字是用来产生缓动效果的,因为鱼越来越近,_vx和_vy会变得更小。现在你说了,我认为它不需要?因为我有* = _ fishDrag。是的,如果你能写一个给我看,并从中学习会很好。 – sutoL

回答

0

一个简单的解决方案是给每个鱼一个最大速度值,可使用到达功能找到鱼的期望的速度矢量,那么归一化矢量,如果它是大于最大加速度大。

将此应用于您的moveToFood方法会是这个样子:

// Deceleration Modifier, determines how fast a fish will slow before reaching target 
static private const _DECELERATION_FACTOR:Number = 0.3; 

private var _fishMaxSpeed:Number = 2; 
private var _speedVector:Point = new Point(); 

public function moveToFood(targetFood:Food):void 
{ 
    // Calculate fish's desired speed with arrive behavior 
    _speedVector.x = (targetFood.x - this.x) * _DECELERATION_FACTOR; 
    _speedVector.y = (targetFood.y - this.y) * _DECELERATION_FACTOR; 

    // Make sure speed isn't larger than fish's max speed 
    if (_speedVector.length > _fishMaxSpeed) { 
     _speedVector.normalize(_fishMaxSpeed); 
    } 

    //food calculations, distance, angle etc 
    var a:Number = targetFood.x - x; 
    var b:Number = targetFood.y - y; 
    var ang:Number = Math.atan2(b, a); 
    //rotation to food 
    var foodLoc:Number = (ang * 180/Math.PI); 
    var foodFinalLoc:Number = foodLoc - rotation; 
    if (foodFinalLoc > 180) foodFinalLoc -= 360; 
      else if (foodFinalLoc < -180) foodFinalLoc += 360; 
    rotation += foodFinalLoc/10; 

    //moving towards food 
    _vx = _speedVector.x; 
    _vy = _speedVector.y; 
    this.x += _vx; 
    this.y += _vy; 

    //removing food when both hit boxes hit 
    if (hit.hitTestObject(targetFood.hit)) 
    { 
     foodropSound.play(); 
     foodDroppedArray.splice(foodDroppedArray.indexOf(targetFood), 1); 
     targetFood.removeSelf(); 
    } 
} 

您可以修改减速因素不断得到不同的到达行为(甚至给每条鱼不同的一个),你可以随机每条鱼的最大速度也是如此。

加速移动物体是相当棘手的。这个解决方案意味着当向食物移动时,你完全无视加速度和阻力,这可能看起来不太好。也许这种加速行为的组合是最好的解决方案。

+0

到达和加速行为有什么不同?这不是它的目的吗?这是朝着某种东西迈进。 – sutoL

+0

嗯,是的,在某种程度上。平原到达行为可以保证您直接通过设置速度向目标物体移动,但只会在距离越来越近时降低速度。加速行为不能保证,因为当你开始加速朝向你的目标时,你可能正朝相反方向或正方向移动。试一试,我在我的示例中添加了_vx和_vy,你应该几乎可以将它放入代码并运行它。 –

+0

从这两个修改我可以看到的差异,到达是更多的静态运动,而加速正在加速朝着食物 – sutoL