流畅的 Custom AS3 Movieclip 排斥功能

发布于 2024-09-30 09:06:26 字数 1277 浏览 9 评论 0原文

我为 2 个影片剪辑编写了这个排斥函数(如下),并从计时器而不是 Enter_frame 侦听器(速度)调用它,但它有抖动的倾向并且不是很平滑。怎样才能让动作流畅?我想也许添加某种填充或其他东西,但我不知道......任何帮助将不胜感激。

谢谢:)

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;
        }
    }
}

I wrote this repel function (below) for 2 movieclips and I call it from a timer instead of an enter_frame listener (speed), but it has the tendency to jerk and not be very smooth. How can I smooth the movements? I was thinking maybe adding some sort of padding or something, but idk...Any help would be greatly appreciated.

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;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别闹i 2024-10-07 09:06:26

我不确定您想要实现什么样的排斥效果,但您可以将代码基于一个简单的物理原理:两个质量之间的引力。您可以在 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 的单位向量。

查看此站点了解顺利地介绍了向量,并将自己从所有这些三角学的东西中解放出来。

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

实施

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

//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;
    }

}

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

尝试一下并告诉我你的想法。

附带说明一下,使用 Timer 类并不比以任何方式监听 ENTER_FRAME 更快。请参阅本文及其两篇相关文章以更好地理解。

I'm not sure exactly what kind of repelling effect you want to achieve, but you can base your code on a simple physic principle : the gravitational force between two mass. You can read more about it on wikipedia. Here's the formula (from wikipedia) :

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

F is the magnitude of the gravitational force between the two point masses,
G is the gravitational constant (about 9.81 m/s²),
m1 is the mass of the first point mass,
m2 is the mass of the second point mass, and
r is the distance between the two point masses.

You can simplify this if you don't want to account mass (i.e. both object have a mass of 1) :

F = G / r²

This is great, but as the definition says, F is only the magnitude of the force, i.e. you don't know the direction, only the amount. To get the direction, you'll need some vector :

F_12 = - G / r_12² * ru_12

Where :

F_12 is the vector of the force on object 2 due to object 1.
G is still the gravitationnal constant
r_12 is the distance between object 1 and object 2.
ru_12 is the unit vector from object 1 to object 2.

Check out this site for a smooth introduction on vectors and liberate yourself from all this trigonometric stuff.

But note that the gravitationnal force is an attraction force. You can easily change this to a repulsion force by inverting its direction.

Implementation

Alright, enough about theory. I've implemented a function which simulate this.

//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;
    }

}

To use it, call repel at a regular interval. Note that obj1 will not be affected by the simulation. In my prototype, obj1 follow the mouse.

Try it and tell me what you think.

On a side note, using the Timer class is not faster than listening to ENTER_FRAME in any way. See this article and its two related articles for a better understanding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文