Помощь · Поиск · Пользователи · Календарь
Полная версия этой страницы: Капли дождя
Flash Zone Forum > Macromedia Flash > ActionScript
Rotwang
Нашел видеорок, там неплохой дождь анимируется программно, импортируя класс Tween. Решил повторить это дело на AS3, и облом mad.gif . Автор видеоурока делает также внутреннюю анимацию капли, когда она разбивается о землю. Но мне это не нужно, а просто надо, чтобы капли появлялись, пролетали определенное расстояние и исчезали.
Автор использует код
Код
stop();


X_start_point = random(750);
X_finish_point =  X_start_point + 30;

//random variable for finishing point (distance down the Y axis)
Y_finish_point = random(300) + 150;
///random variable for the length of decent (i.e. time of the animation in frames per second)
length_time = random(5) + 12;


import mx.transitions.Tween;
import mx.transitions.easing.*

new Tween( this, "_x" , None.easeNone , X_start_point, X_finish_point, length_time, false);

var particle_event:Object =  new Tween( this, "_y" , None.easeNone , 0, Y_finish_point, length_time, false);
particle_event.onMotionFinished = function(){
    
    // when the animation is finished, this timeline will "wait" on frame 2, untill prompted to come back to frame 1
    gotoAndStop(2);
    ///random variable used to determine which impact to play
    impact_var = random(3);
    
    if (impact_var == 0){
    particle.gotoAndPlay("impact1");
    }
    if (impact_var == 1){
    particle.gotoAndPlay("impact2");
    }
    if (impact_var == 2){
    particle.gotoAndPlay("impact3");
    }
    
}


А я делаю так
Код
import fl.transitions.Tween;
import fl.transitions.easing.*;


var X_start_point:Number = 0;
var X_finish_point =  X_start_point + 200;

var Y_finish_point:Number = 800

var length_time:Number = 100;

new Tween( this, "_x" , None.easeNone , X_start_point, X_finish_point, length_time, false);
var particle_event:Object =  new Tween( this, "_y" , None.easeNone , 0, Y_finish_point, length_time, false);


Вот в архиве 2 файла - мой и авторский. Поглядите, пожалуйста. Нажмите для просмотра прикрепленного файла
Мне главное непонятно - как присвоить мувику движение, описываемое в Tween.
chingachgoog
Хе.
Скажу честно. Никогда этот класс не использовал и даже понятия не имею как он работает (хотя кода с твинами переправил много).
Всегда делал свой конкретно-управляющий код через onEnterFrame, например. Ускорение при этом будет работать именно так, как хочу я (вплоть до эффекта "желе").
Или использовал ручные твины (там ускорение можно описать графиком - наврядли такое можно сделать классом твинов программно).
Rotwang
Решил пойти другим путем. Дождь создаю таким способом:
Код
var freqinms = 100 //Частота появления новых капель
var mytimer:Timer = new Timer(freqinms, 50);
mytimer.addEventListener(TimerEvent.TIMER, makeRain);
mytimer.start();

function makeRain(event:TimerEvent) {

    var drop:Clip = new Clip();  //Drop - имя класса капли
    drop.x = Math.random() * this.stage.stageWidth;
    drop.y = Math.random() * this.stage.stageHeight;
    this.addChild(drop);

}

Clip - связанный класс мувика, имитирующего каплю. Но вот незадача - дождь вместо того чтобы идти равномерно, постепенно нарастает, и, в конце концов флешка начинает тормозить. Какое решение, может быть, порекомендуете?
chingachgoog
Цитата(Rotwang @ 11.05.2009 - 17:01) *
Но вот незадача - дождь вместо того чтобы идти равномерно, постепенно нарастает, и, в конце концов флешка начинает тормозить.


А почему дождь должен идти равномерно? Вы же по одной капле добавляете каждые 100 мс и так 50 раз. Вот дождь и нарастает.
Если хотите равномерный дождь - выставьте все капли на стейдж сразу.

Возможно что и код mytimer.start() повторяется (если он написан в одном из фреймов таймлайна). Тогда капель будет не 50 а гораздо больше smile.gif
Тут тормоза неизбежны. Но если капель всего 50 и они тормозят - то надо смотреть анимацию и прочий код - причин для тормозов в приведенном куске кода нет.
Rotwang
Цитата(chingachgoog @ 12.05.2009 - 12:06) *
Возможно что и код mytimer.start() повторяется (если он написан в одном из фреймов таймлайна). Тогда капель будет не 50 а гораздо больше smile.gif

Да, так и есть, код на первом кадре. И он, видимо, повторяется. Как же исправить, куда его еще можно написать? Может, есть возможность каждый раз его снова запускать? Пусть нарастает только в течение 1 цикла, пока пройдет весь Timeline, а с первого кадра чтобы снова начинался.

Цитата
Если хотите равномерный дождь - выставьте все капли на стейдж сразу.

Это мне, значит, надо 50 экземпляров Clip выложить из библиотеки на сцену и в разных местах расставить?
chingachgoog
Цитата(Rotwang @ 12.05.2009 - 14:41) *
Да, так и есть, код на первом кадре. И он, видимо, повторяется. Как же исправить, куда его еще можно написать? Может, есть возможность каждый раз его снова запускать?


Не понимаю. Всего на таймлайне сколько кадров?

Цитата(Rotwang @ 12.05.2009 - 14:41) *
Пусть нарастает только в течение 1 цикла, пока пройдет весь Timeline, а с первого кадра чтобы снова начинался.


Чтобы начиналось все снова, надо сначала все старые мувики убить.

Цитата(Rotwang @ 12.05.2009 - 14:41) *
Это мне, значит, надо 50 экземпляров Clip выложить из библиотеки на сцену и в разных местах расставить?


Ну да, а в чем проблема? Или вы их вручную собрались расставлять? biggrin.gif
Rotwang
Цитата
Всего на таймлайне сколько кадров?

2704 blink.gif Дело в том, что там еще другая анимация, капля воды на стекле.

Цитата
Или вы их вручную собрались расставлять?

Через new Clip?

Цитата
надо сначала все старые мувики убить.

Осторожно спрошу: а как это? unsure.gif
chingachgoog
Цитата(Rotwang @ 12.05.2009 - 15:15) *
2704


Ну и выходит. Что в первом кадре срабатывает код с таймером. Проходит 2704 кадра и этот код с таймером срабатывает повторно. Сам собой.

Цитата(Rotwang @ 12.05.2009 - 15:15) *
Через new Clip?


Просто вместо цикла с таймером (растянутого по времени по таймлайну) сделайте цикл одного кадра (for, например)

Цитата(Rotwang @ 12.05.2009 - 15:15) *
Осторожно спрошу: а как это? unsure.gif


А как вы создаете мувик? Конгруэнтно этому есть и убивалка - removeChild.

add:

Надо только помнить про засаду с удалением из DisplayObjectContainer и сборкой мусора (см. п.9). Спасибо AVM2.
Rotwang
Цитата
Просто вместо цикла с таймером (растянутого по времени по таймлайну) сделайте цикл одного кадра (for, например)

Код
for(var i:int = 0; i<100; i++){
    var drop:Clip = new Clip();
    drop.x = Math.random() * this.stage.stageWidth;
    drop.y = Math.random() * this.stage.stageHeight;
    this.addChild(drop);

Но как же все-таки убивалку сделать? Если написать в последний кадр this.removeChild(drop) то ничего не происходит, а если я пишу со счетчиком:
Код
for(var i:int = 0; i<100; i++){
       this.removeChild(drop);
}
, то получается A conflict exists with definition i in namespace internal. ohmy.gif
chingachgoog
У вас мувик делается анонимно, т.е. просто как new Clip(), соответственно он получает имя автоматически типа instanceXXX.
Убить можно по ссылке на мувик, по его имени или по глубине.
Раз вы все равно делаете локальную ссылку var drop:Clip, то и заносите ее в какой-нибудь массив, а потом берите оттуда ссылку и убивайте сам мувик из DisplayObjectContainer командой removeChild, а потом и саму ссылку командой delete.
Rotwang
Цитата(chingachgoog @ 13.05.2009 - 19:46) *
Раз вы все равно делаете локальную ссылку var drop:Clip, то и заносите ее в какой-нибудь массив

chingachgoog, вы имеете в виду поместить все мувики в один массив? Я делаю так:
Код
for(var i:int = 0; i<3; i++){
    var drop:Clip = new Clip();  //Drop - имя класса капли
    drop.x = Math.random() * this.stage.stageWidth;
    drop.y = Math.random() * this.stage.stageHeight;
    this.addChild(drop);
    var array:Array = new Array(drop);
    trace(array);
    trace(array.length);
]
и у меня создается столько массивов, сколько мувиков, т.е. 100. Мне теперь их нужно как-то объединить в один, или что?
chingachgoog
Мувики можно поместить только в один "массив" - DisplayObjectContainer smile.gif
А вам надо поместить в массив ссылки на мувики.
Что-то типа:
Код
var array=[]
for(var i:int = 0; i<3; i++){
    ...
    var drop:Clip = new Clip();  //Drop - имя класса капли
    array.push(drop)
...


А какой смысл плодить такую же тучу безымянных массивов с одним элементом внутри?
Смысл же в том, чтобы потом пройтись циклом по массиву и получить ссылки на мувики.

Rotwang
Тогда создается 3 массива, но с разным числом элементов
Код
[object Clip]
[object Clip],[object Clip]
[object Clip],[object Clip],[object Clip]
А надо ведь, чтобы в каждом массиве был только 1 элемент?


Вроде, разобрался! Делаю вот что для создания массива:
Код
var array:Array=new Array();
array = [];
for(var i:int = 0; i<20; i++){
    var drop:Clip = new Clip();  //Drop - имя класса капли
    array.push(drop);
    drop.x = Math.random()* this.stage.stageWidth;
    drop.y = Math.random()* this.stage.stageHeight;
    this.addChild(drop);
    trace(array[i]);

для удаления:
Код
for(var i:int = 0; i<20; i++){
        this.removeChild(array[i]);
    }
Так?
Вот только не знаю, что это за конструкция - array = []; smile.gif
chingachgoog
Rotwang, попробуйте разделить вашу задачу на две:
1) Создайте клип и удалите его
2) Создайте массив из N элементов и научитесь добавлять/извлекать из него элементы

Полезно также подумать над сигнатурой метода:

контейнер.removeChild(ссылка_на_мувик_в_контейнере)

PS
Код
Тогда создается 3 массива, но с разным числом элементов


Отчего же разных? Это один массив, на разных стадиях выполнения цикла.

Код
А надо ведь, чтобы в каждом массиве был только 1 элемент?


Нет. Как раз нужен один массив. (это просто моя идея, можно все сделать по-другому)
В этом одном массиве будут ссылки на все мувики. Соответственно вы сможете потом ПОЛУЧИТЬ эти ссылки, которые у вас до этого безвозвратно пропадали (кроме последней).

NB!
Мне не трудно написать готовый код, но я всегда вспоминаю Сороса и его притчу о рыбе и удочках. Тем более, вы, Rotwang, стараетесь именно ИЗУЧИТЬ AS3, что похвально.
chingachgoog
Я в вас верил smile.gif

Цитата(Rotwang @ 14.05.2009 - 20:05) *
Вот только не знаю, что это за конструкция - array = []; smile.gif


Это литерал.

[] = new Array()

Вроде в хелпе, да и вашего Мука это есть.


Rotwang
chingachgoog, а ведь то, что я написал в предыдущем посте, работает rolleyes.gif.


Работает-то работает, но вот дождь при этом способе получается какой-то однообразный. Вот если использовать таймер, как я делал сначала, дождь сильнее похож на настоящий, т.к. капли появляются более рандомно. Но вот как бы придумать механизм удаления мувиков при использовании таймера?

Цитата
Мне не трудно написать готовый код, но я всегда вспоминаю Сороса и его притчу о рыбе и удочках.

Вы совершенно правы, код надо писать только в самом крайнем случае, когда я уже совсем не понимаю. wink.gif
chingachgoog
Я бы саму каплю сделал рандомной и не парился.
Rotwang
Цитата(chingachgoog @ 15.05.2009 - 12:25) *
Я бы саму каплю сделал рандомной и не парился.

То есть?
chingachgoog
Цитата(Rotwang @ 15.05.2009 - 13:35) *
То есть?


Я не знаю, что есть у вас мувик-капля.
Наиболее простой случай - это мувик-анимация капли (полет сверху вниз). Соответственно имеем N кадров мувика.
Пишем код, когда при первом запуске мы запускаем мувик со случайного значения из интервала 1-N.
Далее мувик даже не надо удалять - просто перемещаем его в новое случайное место, когда капля упадет до конца.
Rotwang
Цитата(chingachgoog @ 15.05.2009 - 12:47) *
Наиболее простой случай - это мувик-анимация капли (полет сверху вниз).

Да, у меня именно такой случай. 15 кадров полет капли.
Вот, что я наделал:
Код
var frame:int = Math.floor(Math.random()*15);
gotoAndPlay(frame);
trace(frame);

Эту радость я пишу в первый фрейм капли. Но по-моему, ничего не изменилось.
chingachgoog
Цитата(Rotwang @ 15.05.2009 - 15:10) *
Да, у меня именно такой случай. 15 кадров полет капли.
Вот, что я наделал:
Код
var frame:int = Math.floor(Math.random()*15);
gotoAndPlay(frame);
trace(frame);

Эту радость я пишу в первый фрейм капли. Но по-моему, ничего не изменилось.


По идее все правильно и должно работать.
Возможно тут нельзя использовать тип Int, но проверить не могу - у меня сейчас компилятор под AVM2 что-то глючит.
Rotwang
chingachgoog, а может я на таймлайн что-нибудь не дописал?
Вот все, что у меня в кодах:
Таймлайн, 1-й кадр
Код
var array:Array=new Array();
array = [];
for(var i:int = 0; i<20; i++){
    var drop:Clip = new Clip();  //Drop - имя класса капли
    array.push(drop);
    drop.x = Math.random()* this.stage.stageWidth;
    drop.y = Math.random()* this.stage.stageHeight;
    this.addChild(drop);

    trace(array[i]);
}


Таймлайн, последний кадр
Код
for(var n:int = 0; n<20; n++){
        this.removeChild(array[n]);
    }


Первый кадр мувика "Капля"
Код
var frame:Number = Math.floor(Math.random()*15);
gotoAndPlay(frame);
trace(frame);

Если есть время, посмотрите, как по-вашему, рандомно это или нет?Нажмите для просмотра прикрепленного файла
chingachgoog
Тогда лучше так:

Таймлайн, 1-й кадр

Код
var array:Array = [];
for(var i:int = 0; i<20; i++){
    var drop:Clip = new Clip();  //Drop - имя класса капли
    array.push(drop);
    this.addChild(drop);
}


Таймлайн ... а остальных кадров на таймлайне нет вообще smile.gif

Первый кадр мувика "Капля"

Код
x = Math.random()* this.stage.stageWidth;
y = Math.random()* this.stage.stageHeight;
var frame:Number = Math.floor(Math.random()*15);
gotoAndPlay(frame);


когда надоест включаете убивалку

Код
for(var n:int = 0; n<20; n++){
        this.removeChild(array[n]);
        delete array[n]
    }

Rotwang
chingachgoog, благодарю вас, вот мы наконец-то добили эту тему. laugh.gif
Но остался у меня вопрос. Как работает эта конструкция:
Код
x = Math.random()* this.stage.stageWidth;
y = Math.random()* this.stage.stageHeight;
var frame:Number = Math.floor(Math.random()*15);
gotoAndPlay(frame);


Здесь просто икс и игрек. Вроде непонятно, чему они присваиваются. Как объяснить?
chingachgoog
Цитата(Rotwang @ 15.05.2009 - 22:45) *
Здесь просто икс и игрек. Вроде непонятно, чему они присваиваются. Как объяснить?


Просто this можно иногда (из лени) не писать - если знать всю цепочку видимости.
В данном случае ФП видит переменную x на таймлайне и начинает ее проверять. Если ничего иного вы с x не намудрили, то скоро ФП в цепочке видимости обнаружит геттер/сеттер x у DisplayObject (который есть предок MovieClip).

NB!
У Мука это вроде на с.101 описано.
Русская версия IP.Board © 2001-2011 IPS, Inc.