PDA

Просмотр полной версии : программная анимация рандомного движения


dashaaa
01.12.2008, 12:49
Добрый день,

подскажите, как заставить мувиклип "вибрировать" на одном месте. То есть плавно сдвигаться на небольшое расстояние в произвольном направлении, потом возвращаться назад, и снова, без остановки, двигаться уже в другом направлении.

Лучшее, чего мне удалось достичь - это вот
FunnyAnimation = new Tween(this, "_x", Regular.easeInOut, this._x, initX+x_shift, duration, true);
FunnyAnimation1 = new Tween(this, "_y", Regular.easeInOut, this._y, initY+y_shift, duration, true);
FunnyAnimation.onMotionFinished = function () {
this.yoyo();
}
FunnyAnimation1.onMotionFinished = function () {
this.yoyo();
}


Но здесь нет никакой случайности в направлении движения - туда-сюда-туда-сюда...

NoCD
01.12.2008, 13:44
то есть нужно просто рандомное движение в какое нибудь из четырех направлений, пока не дойдет до точки никуда не должен сворачивать??

dashaaa
01.12.2008, 14:07
По идее да

NoCD
01.12.2008, 15:27
Надеюсь то, что нужно.
Если переделать пример, то можно с помощью точек регистрации задать движение мувику

dashaaa
02.12.2008, 13:44
NoCD, большое спасибо за пример и за внимание к вопросу!
Я только сегодня увидела ответ, поэтому вчера сама тоже до чего-то дошла.
Во-первых, предположительно, анимация с помощью класса Tween более плавная, чем если писать координаты, куда мувику переместиться (и удобнее - легко варьировать скорость движения в секундах).
Поэтому, я сделала вот так:
import mx.transitions.Tween;
import mx.transitions.easing.*;
import mx.utils.Delegate;
class Ball extends MovieClip {
var initX:Number;
var initY:Number;
var FunnyAnimation:Tween;
var FunnyAnimation1:Tween;
var duration:Number = 2;
var comeBack:Boolean = false;
// максимальный сдвиг от начального положения. Можно сделать больше, для наглядности анимации
static var vibrShift = 10;
var lastShift:Number = 0;
var yo:Boolean = false;

function funAnimProlong() {
FunnyAnimation1.onMotionFinished = null;
FunnyAnimation.onMotionFinished = null;
Vibration();
}
public function shift(x_shift:Number, y_shift:Number):Void {
FunnyAnimation = new Tween(this, "_x", None.easeNone, this._x, initX+x_shift, duration, true);
FunnyAnimation1 = new Tween(this, "_y", None.easeNone, this._y, initY+y_shift, duration, true);
FunnyAnimation.onMotionFinished = Delegate.create(this, funAnimProlong);
}
public function Vibration():Void {
var direct:Number = Math.floor(Math.random()*4);
if (direct == lastShift) {direct = (direct+1)%4;}
lastShift = direct;
var shX:Number = 5+Math.floor(vibrShift*Math.random());
var shY:Number = 5+Math.floor(vibrShift*Math.random());
switch (direct) {
case 0 :shift(shX,shY);break;
case 1 :shift(shX,(-1)*shY);break;
case 2 :shift((-1)*shX,shY);break;
case 3 :shift((-1)*shX,(-1)*shY);break;
}
}
public function Ball() {
initY = this._y;
initX = this._x;
Vibration();
}
}
Вот здесь можно лицезреть результат: 20971

И, пока мувиклипов, которые двигаются таким образом мало (25) всё работает хорошо. Но когда их 100 начинаются подёргивания. Но мне-то нужно 100 :wacko:
Может можно переписать как-нибудь, чтобы не дёргалось? Вообще-то правильность функции funAnimProlong() вызвает у меня сомнения :rolleyes:
И ещё вопрос - можно ли сделать чтобы анимация из одной точки в другую была не по прямой, а по какой-нибудь плавной линии?

goarcade
02.12.2008, 17:46
Не поленился и набросал код моего подхода, т.к. задача показалась интересной:) надеюсь он будет полезным!

import flash.geom.Point;


var ballList:Array = new Array();

for(var i:Number=0;i<100;i++)
{
var w:Number = 550;
var h:Number = 400;
ballList.push(createBall(w/10*(i%10)+w/20,h/10*Math.floor(i/10)+h/20));
}

function onEnterFrame():Void
{
for(var i:Number=0;i<ballList.length;i++)
{
steer(ballList[i]);
if(ballList[i].position.subtract(ballList[i].target).length<10)
{
createTarget(ballList[i],20);
}
}
}


function steer(mc:MovieClip):Void
{
var target:Point = mc.target;
var position:Point = mc.position;
var velocity:Point = mc.velocity;

var max_speed:Number = mc.max_speed;

var target_offset:Point = target.subtract(position)
var ramped_speed:Number = max_speed * (target_offset.length/10)
var clipped_speed:Number = Math.min(ramped_speed, max_speed)
var desired_velocity:Point = target_offset.clone();
desired_velocity.normalize(desired_velocity.length*(clipped_speed / target_offset.length));


velocity = mc.velocity.add(truncate (desired_velocity.subtract(velocity), 0.5));
truncate (velocity, max_speed)


position = position.add(velocity);

mc._x = position.x;
mc._y = position.y;
mc.position = position;
mc.velocity = velocity;
}
function createBall(x:Number,y:Number):MovieClip
{
var mc:MovieClip = createEmptyMovieClip("ball"+getNextHighestDepth(),getNextHighestDepth());
mc.beginFill(0xffffff*Math.random());
drawRect(mc,5);
mc.endFill();

mc._x = x;
mc._y = y;

mc.position0 = new Point(x,y);
mc.position = new Point(x,y);
mc.target = new Point(x,y);
mc.velocity = new Point(0,0);
mc.max_speed = 3;
return mc;
}


function createTarget(mc:MovieClip,r:Number):Void
{
mc.target = new Point(mc.position0.x+Math.random()*r-r/2,mc.position0.y+Math.random()*r-r/2);
}


function truncate(p:Point,maxLength:Number):Point
{
if(p.length>maxLength)p.normalize(maxLength);
return p;
}

function drawRect(mc:MovieClip, r:Number):Void {
mc.moveTo(-r,-r);
mc.lineTo( r,-r);
mc.lineTo( r, r);
mc.lineTo(-r, r);
}

dashaaa
03.12.2008, 14:37
goarcade, получилось очень круто :D
Похоже, даже, что это решение будет нормально и без тормозов работать в реальной задаче (там каждый мувик не просто фигура, а две наложенные друг на друга картинки, и таких мувиков там около 40)
А ещё, после того как я почитала Ваш код, Point, со всеми своими методами, стал моим любимым классом (раньше мы не встречались) %)
В общем, бурные апплодисменты и огромное спасибо! :yahoo: