模拟中物体的移动

Posted

技术标签:

【中文标题】模拟中物体的移动【英文标题】:Movement of Objects in a simulation 【发布时间】:2011-09-09 00:23:51 【问题描述】:

我目前正在制作一个带有鱼的闪光“池塘”,并且我能够将食物颗粒添加到池塘中,我应该如何让我的鱼移动到食物 x,y 位置?所以它会很平滑,而不是将我的鱼的 x,y 位置设置为食物颗粒的 x,y 位置。

还有学习如何让我的鱼自己移动的好地方吗? 类似于http://abowman.com/google-modules/fish/

鱼类

package  

    import flash.display.MovieClip;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.filters.DropShadowFilter;
    /**
     * ...
     * @author Z
     * Fish class, makes fishes behaviors, find food.
     */
    public class Fish extends MovieClip
    
        private var stageReference:Stage;
        private var foodArray :Array = new Array();
        public function Fish(stageReference:Stage) 
        
            this.stageReference = stageReference;
            x = stageReference.stageWidth / 2;
            y = stageReference.stageHeight / 2;
            setUpShadow()

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

        

        public function loop(e:Event):void
        
            if (y - 15 < foodArray.pop.y && y + 15 > foodArray.pop.y)
                moveToFood();

        
        public function moveToFood():void
        

        
        public function addFoodTarget(foodTarget:Food):void
           
            foodArray.push(foodTarget);
        
        public function setUpShadow():void
        
            //http://blog.0tutor.com/post.aspx?id=103
            //First we declare an object, a dropshadow filter and name it my_shadow for further reference.
            var my_shadow:DropShadowFilter = new DropShadowFilter();
            //Now we apply some properties to our new filters object, this first property is the color, and we set that to black, as most shadows are.
            my_shadow.color = 0x000000;
            //These next two properties we set, are the position of our dropshadow relative to the object,
            //This means 8 px from the object on both the x and y axis.
            my_shadow.blurY = 8;
            my_shadow.blurX = 8;
            //And here we set an angle for the dropshadow, also relative to the object.
            my_shadow.angle = 150;
            //Setting an alpha for the shadow. This is to set the strength of the shadow, how "black" it should be.
            my_shadow.alpha = .5;
            //and here we set the distance for our shadow to the object.
            my_shadow.distance = 15; 
            //Now we define an array for our filter with its properties to hold it. This will be the final object we refer to when we need to apply it to something.
            var filtersArray:Array = new Array(my_shadow);
            //The last step is to take our movie clip that we made at the beginning, so we take our object and apply the filtersArray.
            filters = filtersArray;

        
    


食品类

package  

    import flash.display.MovieClip;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.filters.DropShadowFilter;
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    /**
     * ...
     * @author Z
     * food class
     */
    public class Food extends MovieClip
    
        private var stageReference:Stage;
        private var foodDisperseSpeed:Number = 0.4;

        public function Food(stageReference:Stage,xPos:Number,yPos:Number) 
        
            x = xPos;
            y = yPos;
            this.stageReference = stageReference;
            addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
        

        private function loop(e:Event):void
        
                if(Math.random() > 0.5)
                x -= foodDisperseSpeed;
                else
                y -= foodDisperseSpeed;

        

        public function removeSelf():void
        
            removeEventListener(Event.ENTER_FRAME, loop);

            if (stageReference.contains(this))
                stageReference.removeChild(this);

        

    


【问题讨论】:

【参考方案1】:

这应该准确地解释如何移动你的对象。显然,您需要将 Sprite 更改为您用于鱼/食物/等的任何类别。您的鱼对象要么需要速度属性。如:public var speed:int = 5;或者你可以在你的主要模拟中为所有的鱼定义一个。 (我更喜欢自己有变速鱼)

    // This can be done faster but this is to show you how it works.
    public function moveObject(obj:Sprite, target:Sprite):void
    
        // We start by getting the distances along the x and y axis
        var dx:Number = target.x - obj.x;
        var dy:Number = target.y - obj.y;

        // Basic distance check with pythagorean theorem. We don't need
        // to get the Square Roots because if it is smaller squared it
        // will still be smaller once we get the square roots and thus
        // will just be a waste of time.
        if (dx * dx + dy * dy < obj.speed * obj.speed)
        
            // Since we are within one time step of speed we will go past it
            // if we keep going so just lock the position in place.
            obj.x = target.x;
            obj.y = target.y;
        
        else
        
            // we aren't there yet so lets rock.

            // get the angle in radians given the distance along the x and y axis.
            var angleRads:Number = Math.atan2(dy, dx);

            // get our velocity along the x and y axis
            // NOTE: remember how the flash coordinate system is laid out.
            // we need to calc cos along the x and sin along the y.
            var vx:Number = Math.cos(angleRads) * obj.speed;
            var vy:Number = Math.sin(angleRads) * obj.speed;

            // now that we have our speeds we can add it to the objects 
            // current position and thus create a nice smooth movement per
            // frame.
            obj.x += vx;
            obj.y += vy;

            // This will lock the rotation of the object to the direction
            // the object is traveling in.
            // NOTE: don't forget when you make your objects that for flash
            // rotation of Zero = pointing to the right (+x)
            obj.rotation = angleRads * 180 / Math.PI;
        
    

希望对您有所帮助,有任何问题欢迎提问。

编辑: 您无需在 Sprite 或 MovieClip 中添加对舞台的引用,他们已经可以访问该舞台。

【讨论】:

一个问题,在我的食物课上,每种食物在掉到池塘里时都会产生“漂浮”的效果,我是否能够跟踪它不断变化的 x,y坐标? 是的,这段代码将直接指向目标对象的当前 x 和 y 位置。 我在哪里可以读到关于让我的鱼 z 旋转以面对食物的信息?我的数学很烂,我真的不明白上面的数学计算。 这段代码将为您旋转它们,不幸的是,数学并没有比这更简单。我这只是混合了一点三角的基本几何图形。使用代码你应该能够弄清楚它是如何工作的。我不确定你在 Z 轴上旋转以使它们面对食物是什么意思。他们应该已经这样做了,因为你在 2d 中只有 x,y 没有 z。如果您尝试在其中一个 3D API 中执行此操作,则会遇到更大的数学问题。【参考方案2】:

这是一种快速简便的方法来完成您所追求的事情:

public function moveToFood(food:Food):void

    x -= (x - food.x) / 40;
    y -= (y - food.y) / 40;

如果想做得更好一点,您可能需要查看自己的小型人工智能来寻找鱼(例如挑选最近的食物,以恒定的速度向它移动,然后开始以它为食)。

【讨论】:

我可以知道 /40 是干什么用的吗? 这里发生的事情是它得到鱼和食物之间沿 x 和 y 轴的距离,然后从当前 x 和 y 除以 40 减去它。基本上,如果这是横向移动100 像素,而您使用 /2 代替,您的移动将是(每帧):50px、25px、12.5px、6.25px 等。它提供了一种“缓入”效果。【参考方案3】:

您可以使用几个 Tween 对象来调整鱼的 x/y 坐标,以便它们向食物移动。很好的是,您可以通过这种方式轻松获得缓入/缓出效果。

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/transitions/Tween.html

【讨论】:

【参考方案4】:

在http://www.greensock.com/tweenlite/ 下载 tweenLite 库并将其添加到您的项目中。

然后你可以像这样调用 tweenlite:

TweenLite.to(fish, timeToGoToFood, x: food.x, y: food.y, ease: yourEasing);

缓动可以从 tweenLite 的一些预编程缓动函数中选择。我认为 Cubic.easeout 或 Cubic.easein 最适合你的鱼。 :)

【讨论】:

以上是关于模拟中物体的移动的主要内容,如果未能解决你的问题,请参考以下文章

模拟物体的惯性滚动

基于.NET的机械运动模拟应用开发

unity物理引擎浅谈

如何制作一个不会不加速物体的力SpriteKit Swift

XNA (MonoGame) 世界空间和物体运动

模拟退火算法