Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему  
Старый 08.03.2011, 10:06
maxkar вне форума Посмотреть профиль Отправить личное сообщение для maxkar Найти все сообщения от maxkar
  № 5  
Ответить с цитированием
maxkar

Регистрация: Nov 2010
Сообщений: 497
Цитата:
Получается во время обхода всех элементов массива - я выдергивал из него один элемент - массив сжимался - и на следующем обходе я "терял" один элемент?
Да, все правильно. По действию код был эквивалентен
Код AS3:
for (var i : int = 0; i < aBlt.length; i++)
    if (...)
        aBlt.splice(aBlt.indexOf(aBlt[i]), 1);
При удалении в позицию i перемещался следующий элемент (i+1), после чего i увеличивалось. Т.е. "следующий" элемент пропускался. Причем я еще не уверен, что на самом деле код итерации for each должен быть эквивалентен предыдушему (не особо искал в документации правда). А если он может быть не эквивалентен, то изменения при итерации могут иметь и еще более непредсказуемые эффекты.

Цитата:
Но чем помогает slice?
Со slice эквивалентный код становится примерно следующим:
Код AS3:
var tmp : Array = aBlt.slice();
for (var i : int = 0; i < tmp.length; i++)
    if (checkIntersection(tmp[i]))
        aBlt.splice(aBlt.indexOf(tmp[i]));
В этом коде tmp - это новая копия aBlt, ничем не связанная со своим оригиналом. Ну а так как ее изменений в цикле не производится, то все работает предсказуемо.

Цитата:
slice выполняется каждый раз в начале цикла?
Да, в начале каждой итерации. "Эквивалент" кода чуть выше.

Хотя в вашем случае slice все таки тяжеловат. Лишняя копия, затем поиск в массиве (хотя и быстрый) и удаление. Можно проще, с явной итерацией по индексу:
Код AS3:
var idx : int = 0;
while (idx < aBlt.length) {
    if (checkIntersection(aBlt[i])
        aBlt.splice(i, 1);
    else
        idx++;
}
Итерация по индексу явно позволяет показать, когда выполнять сдвиг, а когда - нет.

В вашем конкретном случае есть и еще один принципиально отличный от приведенных выше вариант. Он использует то, что пули отсортированы по горизонтали и если какая-то пуля еще не долетела до стенки, все остальные тоже не долетели. Тогда проверка идет только по одному элементу:
Код AS3:
while (aBlt.length > 0 && checkIntersection(aBlt[0])) {
    var m : MovieClip = aBlt.shift(); // удаляет первый элемент из aBlt
    m.fnHit();                     
    this.removeChild(m);
}
При выбранной стратегии удаления этот способ будет гораздо лучше - он не проверяет лишние элементы. При той же гипотезе отсортированности, но большом количестве пуль, которые могут одновременно пересекать стену, можно экономить и количество удалений:
Код AS3:
var firstMiss : int = 0;
while (firstMiss < aBlt.length && checkIntersection(aBlt[0]))
    firstMiss++;
if (firstMiss > 0)
    for each (var m : MovieClip in aBlt.splice(0, firstMiss)) {
        m.fnHit();                     
        this.removeChild(m);
    }
В ряде случаев вызов fnHit и removeChild не писал, там восстановление их должно быть очевидно.

Выбирать в данном случае стоит тот вариант, котороый вам понятнее

Создать новую тему   Часовой пояс GMT +4, время: 10:11.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 10:11.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.