Разный код для разных версий Flash Player - PullRequest
1 голос
/ 08 декабря 2011

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

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

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 08 декабря 2011

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

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

1 голос
/ 23 января 2013

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

Извините, я не заметил, что вы не хотите поддерживать разные версии библиотеки. В этом случае нет никакого способа - когда 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. Скомпилируйте эти две реализации независимо в отдельные SW F s (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. Помните, что основные классы наших SWF-файлов реализуют MyInterface, поэтому это приведение будет работать.

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

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

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

1 голос
/ 29 января 2012

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

...