Smooth Custom AS3 Movieclip repel功能

时间:2010-10-30 06:55:58

标签: flash actionscript-3 function physics movieclip

我为2个动画片段编写了这个击退函数(下面),我用定时器而不是enter_frame听众(速度)来调用它,但是它有倾向而不是很平滑。我怎样才能平滑动作?我在考虑可能会添加某种填充或其他东西,但是idk ......任何帮助都会非常感激。

Thanx:)

function repel(mover2, mover) {
    var xdiff:Number = mover2.x - mover.x;
    var ydiff:Number = mover2.y - mover.y;
    var dist:Number = Math.sqrt(xdiff*xdiff + ydiff*ydiff);

    if (dist < (mover2.width/2 + mover.width/2)){
        var angle:Number = Math.atan2(ydiff, xdiff);

        if ((mover.x - Math.cos(angle)*10) - (mover.width/2) > minx && (mover.x - Math.cos(angle)*10) + (mover.width/2) < maxx) {
            mover.x -= (Math.cos(angle)*10)*1;
        }
        if ((mover.y - Math.sin(angle)*10) - (mover.height/2) > miny && (mover.y - Math.sin(angle)*10) + (mover.height/2) < maxy) {
            mover.y -= (Math.sin(angle)*10)*1;
        }
        if ((mover2.x - Math.cos(angle)*10) - (mover2.width/2) > minx && (mover2.x - Math.cos(angle)*10) + (mover2.width/2) < maxx) {
            mover2.x += (Math.cos(angle)*10)*1;
        }
        if ((mover2.y - Math.sin(angle)*10) - (mover2.height/2) > miny && (mover2.y - Math.sin(angle)*10) + (mover2.height/2) < maxy) {
            mover2.y += (Math.sin(angle)*10)*1;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

我不确定你想要达到什么样的排斥效果,但你可以将你的代码建立在一个简单的物理原理上:两个质量之间的引力。您可以在wikipedia上详细了解相关信息。这是公式(来自维基百科):

F = G * (m1 * m2) / r²

F是两点质量之间的重力的大小,
G是引力常数(约9.81 m /s²),
m1是第一点质量的质量,
m2是第二点质量的质量,和 r是两点质量之间的距离。

如果您不想计算质量(即两个对象的质量均为1),您可以简化此操作:

F = G / r²

这很好,但正如定义所说,F只是力的大小,即你不知道方向,只知道数量。要获得方向,你需要一些矢量:

F_12 = - G /r_12²* ru_12

其中:

F_12是由于物体1而在物体2上的力的矢量 G仍然是重力常数
r_12是对象1和对象2之间的距离 ru_12是从对象1到对象2的单位向量。

查看this site以获得关于向量的平滑介绍,并将自己从所有这些三角函数中解放出来。

但请注意,重力是一种吸引力。您可以通过反转方向轻松地将其更改为排斥力。

实施

好的,足够理论。我已经实现了一个模拟这个的函数。

//make sure you set your initial conditions
obj2.vx = 0;
obj2.vy = 0;

function repel(obj1:MovieClip, obj2:MovieClip) {

    var G:Number = 100; // gravitationnal constant. You can play with this to get more or less force.
    var res:Number = 0.9; //a coeffient which reduce the speed when the object hits a wall.

    //this is a vector from obj1 pointing to obj2
    var distVector:Point = new Point();
    distVector.x = obj2.x - obj1.x;
    distVector.y = obj2.y - obj1.y;

    var distance:Number = Math.sqrt(distVector.x*distVector.x + distVector.y*distVector.y);
    //a unit vector is a vector of length 1
    var unit:Point = distVector.clone();
    unit.x /= distance;
    unit.y /= distance;

    //here's the actual formula
    var force:Point = new Point();
    force.x = G / (distance*distance) * unit.x;
    force.y = G / (distance*distance) * unit.y;

    //we don't have any mass, so a = F
    var ax:Number = force.x;
    var ay:Number = force.y;

    //simple integration
    obj2.vx += ax;
    obj2.vy += ay;

    obj2.x += obj2.vx;
    obj2.y += obj2.vy;

    // bounce to stage dimension
    if(obj2.x < 0){
        obj2.x = 0;
        obj2.vx = -res*obj2.vx;
    }

    if(obj2.x > stage.stageWidth){
        obj2.x = stage.stageWidth;
        obj2.vx = -res*obj2.vx;
    }

    if(obj2.y < 0){
        obj2.y = 0;
        obj2.vy = -res*obj2.vy;
    }

    if(obj2.y > stage.stageHeight){
        obj2.y = stage.stageHeight;
        obj2.vy = -res*obj2.vy;
    }

}

要使用它,请定期呼叫驱逐。请注意,obj1不会受到模拟的影响。在我的原型中,obj1跟随鼠标。

尝试并告诉我你的想法。

另外,使用Timer类并不比以任何方式监听ENTER_FRAME更快。有关更好的理解,请参阅this article及其两篇相关文章。