我正在编写一个通用图形引擎,可以使用利润率优势在FP11上运行,也可以使用旧的软件blitting在FP10中工作。
所以,我想知道实现这个目标的最佳途径是什么?
首先我认为如果我将为FP11编译swf并且如果播放器的版本不是11则不会使用新类,一切都会正常工作。但是我错了。令我惊讶的是,我得到“VerifyError:错误#1014。如果我使用导入的FP11库运行代码,即使没有调用它们,也无法找到类flash.display3D :: Context3D”。
我认为只有在我尝试访问缺席课程时FP才会抛出此消息,但这是不对的。当我试图运行时,它会抛出错误.swf
那么,有什么办法吗?我考虑使用预加载器根据版本加载不同的SWF,但维护和编译2个不同的SWF非常混乱。
还有其他方法吗?
答案 0 :(得分:2)
如果您使用Flash(而不是Flex或其他工具),我相信您唯一的选择可能是条件编译。当我不得不在CS5中处理这个问题时,我找不到任何其他内容。
我最终做的是为各种配置定义了几个常量,然后我编译了几个版本的.swf。我在浏览器中根据播放器检测代码加载了正确的.swf文件。如果你想在Newgrounds等地方使用你的.swf,那真是一团糟。
答案 1 :(得分:1)
flash apis不向前兼容。如果你想要一个闪光灯11 api,你需要制作11+ swf闪光灯。这样做的原因是swf 10可以愉快地创建它自己的Stage3D类。如果它突然与swf 11中的内置类冲突,这将破坏向后兼容性。所以你只能有一个向后或向前的兼容性。
答案 2 :(得分:1)
修改强>
抱歉,我没有注意到您不想支持不同版本的库。在这种情况下,没有办法 - 当FP处理SWF的字节码时,当它找到未知的引用时,它会抛出VerifyError。当然,您可以使用getDefinitionByName()
和动态访问权限,但非常很慢。
为了最大限度地减少单独支持的代码量,可以使用具有主要功能的SWC和具有版本相关功能的SWF,因此在初始化阶段,lib的主类将检查FP版本并加载适当的SWF。
这称为动态链接,有一种方法:
创建所有依赖于玩家版本的功能(public interface MyInterface...
)的界面。此接口不应包含对依赖于版本的API的任何引用。将此接口(可能只是单个.as文件)编译到SWC中(让它为lib-intf.swc
)。
创建此接口的两个独立实现;第一个将使用新的API,第二个不会(它可能只是一个占位符,但也可能是一个替代实现)。稍后我们需要将这些实现编译为SWF,因此我们需要扩展Sprite
的主类。最简单的方法是使这些主类实现我们的接口(即public class MyImplementationA extends Sprite implements MyInterface...
,同样适用于MyImplementationB
)。它们只是空Sprites
,但它们将包含接口方法。
将这两个实现独立编译为单独的SW F (lib-a.swf
和lib-b.swf
)。编译时,在IDE中包含lib-intf.swc
作为外部库(-external-library-path
编译器参数或“外部”链接类型)。
现在,在编译根应用程序时,请将lib-intf.swc
作为常规库(-library-path
编译器参数或“合并到代码中”链接类型包含在IDE中)。根本不包括依赖于版本的类。因此,在根应用程序中,您将只引用与版本无关的接口。当您的应用程序启动时,请检查FP版本,并根据它使用Loader类加载适当的SWF。您必须将其加载到主应用程序域中,而不是它的子项(这是默认选项; more details)。
加载SWF后,将其强制转换为界面:var versionDependentImpl:MyInterface = loader.content as MyInterface
。请记住,我们的SWF的主要类实现了MyInterface
,因此这个演员可以使用。
就是这样 - 现在您可以使用您的实施:versionDependentImpl.someMethod()
。当然,someMethod
应该在MyInterface
。
因此,这里的技巧是从SWF文件动态加载实现。虽然根应用程序对这个SWF中的类一无所知,但我们可以使用它的主类的方法,因为我们使它实现了一个我们编译到根应用程序中的接口。
这种方法是可扩展的:例如,您可以定义具有返回其他接口的方法的主接口。您甚至可以将实现之间共享的具体类包含在lib-intf.swc
中,只要它们不使用依赖于版本的API即可。