Разный код для разных версий Flash Player

Я пишу универсальный графический движок, который будет работать на FP11, используя преимущество крота, а также работает на FP10, используя старое программное обеспечение.

Итак, я задаюсь вопросом, как лучше всего достичь этого?

Сначала я подумал, что если я скомпилирую SWF для FP11 и не буду использовать новые классы, если версия проигрывателя не 11, все будет работать нормально. Но я был неправ. К моему удивлению, я получаю сообщение об ошибке "VerifyError: Ошибка № 1014. Не удается найти класс flash.display3D::Context3D", если я запускаю код с импортированными библиотеками FP11, даже если они не вызываются.

Я думал, что FP выдаст это сообщение только тогда, когда я попытаюсь получить доступ к отсутствующему классу, но это неправильно. Выдает ошибку только когда я пытаюсь запустить.swf

Так есть ли способ сделать это? Я думал о загрузке разных SWF-файлов в зависимости от версии с использованием preloader, но поддержка и компиляция двух разных SWF-файлов довольно запутанная.

Есть ли другие способы?

3 ответа

Если вы используете Flash (в отличие от Flex или какого-либо другого инструмента), я полагаю, что единственным вариантом может быть условная компиляция. Когда мне пришлось иметь дело с этим в CS5, я не мог найти ничего другого.

В итоге я определил несколько констант для различных конфигураций, а затем скомпилировал несколько версий.swf. Я загрузил правильный файл.swf на основе кода обнаружения игрока в браузере. Это действительно беспорядок, если вы хотите, чтобы ваш.swf находился в таких местах, как Newgrounds и т. Д.

редактировать

Извините, я не заметил, что вы не хотите поддерживать разные версии библиотеки. В этом случае нет никакого способа - когда FP обрабатывает байт-код SWF и когда он находит неизвестную ссылку, он выдает VerifyError. Конечно, вы можете использовать getDefinitionByName() и динамический доступ, но он очень медленный.

Чтобы минимизировать количество отдельно поддерживаемого кода, вы можете использовать SWC с основными функциями и SWF с функциями, зависящими от версии, поэтому на этапе инициализации основной класс вашей библиотеки будет проверять версию FP и загружать соответствующий SWF.


Это называется динамическое связывание, и есть способ:

  1. Создать интерфейс всех функций, зависящих от версии проигрывателя (public interface MyInterface...). Этот интерфейс не должен содержать ссылок на зависимые от версии API. Скомпилируйте этот интерфейс (это может быть только один файл.as) в SWC (пусть это будет lib-intf.swc).

  2. Создайте две независимые реализации этого интерфейса; первый будет использовать новые API, второй - нет (он может быть просто заполнителем, но также может быть альтернативной реализацией). Позже нам нужно скомпилировать эти реализации в SWF, поэтому нам нужны основные классы, которые расширяют Sprite, Самый простой способ сделать это - заставить эти основные классы реализовать наш интерфейс (т.е. public class MyImplementationA extends Sprite implements MyInterface...и то же самое для MyImplementationB). Они будут просто пустыми Sprites, но они будут содержать методы интерфейса.

  3. Скомпилируйте эти две реализации независимо в отдельные SWF(lib-a.swf а также lib-b.swf). При компиляции включайте lib-intf.swc как внешняя библиотека (-external-library-path параметр компилятора или "внешний" тип ссылки в IDE).

  4. Теперь, при компиляции вашего корневого приложения, включите lib-intf.swc как обычно библиотека (-library-path параметр компилятора или тип ссылки "объединены в код" в IDE). Не включайте зависящие от версии классы вообще. Таким образом, в корневом приложении у вас будут только ссылки на интерфейс, который не зависит от версии. Когда ваше приложение запускается, проверьте версию FP и, в зависимости от этого, загрузите соответствующий SWF с помощью класса Loader. Вам придется загрузить его в основной домен приложения, а не в его дочерний элемент (это вариант по умолчанию; более подробная информация).

  5. Когда SWF загружен, приведите его к интерфейсу: var versionDependentImpl:MyInterface = loader.content as MyInterface, Помните, что основные классы наших SWFs реализуют MyInterface, так что этот актерский состав будет работать.

  6. Вот и все - теперь вы можете использовать вашу реализацию: versionDependentImpl.someMethod(), Конечно, someMethod должны быть определены в MyInterface,

Итак, хитрость в том, чтобы динамически загружать реализацию из SWF-файла. Хотя корневое приложение ничего не знает о классах внутри этого SWF-файла, мы можем использовать методы его основного класса, потому что мы заставили его реализовать интерфейс, который мы скомпилировали в корневое приложение.

Этот подход является масштабируемым: например, вы можете определить основной интерфейс, у которого есть методы, которые возвращают другие интерфейсы. Вы даже можете включить конкретные классы, которые совместно используются реализациями, в lib-intf.swcДо тех пор, пока они не используют зависимые от версии API.

flash apis не поддерживает совместимость если вы хотите flash 11 api, вам нужно сделать flash 11+ swf. Причина этого в том, что SWF 10 может с радостью создать свой собственный класс Stage3D. если это вдруг конфликтует со встроенным классом в SWF 11, это нарушит обратную совместимость. так что вы можете иметь только одну, обратную или прямую совместимость.

Другие вопросы по тегам