使用“文件"保存场景对象位置以便稍后在 AS3 中重建 [英] Using 'File' to save scene object locations to rebuild later in AS3

查看:14
本文介绍了使用“文件"保存场景对象位置以便稍后在 AS3 中重建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 ActionScript 3 中的文件"函数来保存以下信息:

I am attempting to use the 'File' function in ActionScript 3 to save the following information:

我在场景中有不同的可拖动显示对象,数量和类型可能会有所不同.我想保存数量和它们的位置,然后在以后的会话中加载它们.

I have varying draggable display objects in the scene, the amount and type can vary. I want to save the amount and their position and then load them back in a future session.

我正在努力使用 File 来保存任何东西,我已经搜索了 Adob​​e 文档,但不知道如何使用它.

I am struggling to use File to save anything, I have searched the Adobe documentation and cannot get my head round how to use it.

我还没有使用它开发任何代码.

I have not yet developed any code using it.

任何帮助将不胜感激.

谢谢.

推荐答案

您正在尝试将 DisplayObject 直接写入文件,由于 Flash 处理默认序列化的方式,Flash 引擎阻止了这种情况的任何对象.为了将 DisplayObject 保存到外部资源中,您需要使用 IExternalizable 在该对象的类以及您计划存储的任何对象类上.writeExternal 的实现应该保存从头开始重建所述对象所需的所有数据,并且readExternal 还应该使用方法来恢复所述DisplayObject 通过对嵌套显示对象执行 addChild(),或将它们添加到对象可能包含的其他内部结构中.

You are trying to write a DisplayObject into the file directly, this is prevented by Flash engine due to the way Flash handles default serialization of any object. In order to save a DisplayObject into the external resource, you need to employ IExternalizable on that object's class and any class of objects you will plan to store as well. The implementation of writeExternal should save all data required to rebuild the said object from scratch, and readExternal should also employ methods to restore the integrity of said DisplayObject by performing addChild() on nested display objects, or adding them into other internal structures that object might contain.

注意,其他答案包含使用 XML 或 JSON 进行自定义序列化的有效点,还包含需要导入的链接,特别是 flash.utils.registerClassAliasflash.utils.getDefinitionByName 非常需要从序列化数据块重新创建结构.

Note, other answers contain valid points for doing a custom serialization with XML or JSON, and also contain links to requires import, in particular, flash.utils.registerClassAlias and flash.utils.getDefinitionByName are gravely needed to recreate the structure from a serialized data chunk.

示例:假设您在 Board 类中有一个绘图板,以及一组可以使用鼠标拖动的矩形,它们的大小和颜色各不相同.矩形是定制的 MovieClip 并且没有自己的类,但是每个 MovieClip 还分配了一个 color 属性以简化它们的区别.这意味着您只需要在 Board 类上实现 IExternalizable.我们还假设 Board 类有一个 pieces 数组,其中包含指向嵌套矩形的所有链接,以及一种基于宽度、高度和颜色创建新的适当大小的矩形的方法,如下所示参数.(你的情况可能对Board的数据结构有更多要求,所以请密切关注)所以,序列化Board的过程将是收集所有数据从嵌套的 MC 并将其按顺序填充到提供的 IDataOutput 中,恢复 Board 实例的过程应该检索存储的数据,解析它以找到什么位置,创建嵌套的 MC 与它们存储的一样,正确定位它们,addChild() 自我并重建pieces` 数组.

An example: Let's say you have a drawing board in a Board class, and a set of rectangles that you can drag by using mouse, that differ by size and color. Rectangles are custom made MovieClips and don't have a class of their own, but each MovieClip is also assigned a color property to simplify their distinction. This means you need to implement IExternalizable on Board class only. Let's also assume Board class has a pieces array that contains all links to nested rectangles, and a method to create a new properly sized rectangle based on width, height and color supplied as parameters. (There might be more requirements to the data structure of Board to meet in your case, so watch closely) So, the process of serializing Board will be to collect all the data from nested MCs and stuff it in order into IDataOutput supplied, and the process of restoring an instance of Board should retrieve stored data, parse it to find what is where, create the nested MCs to be the same like they've been stored, position them properly, addChild() to self and rebuild thepieces` array.

public class Board extends Sprite implements IExternalizable {
    private var pieces:Array;
    public function createRectangle(_width:Number,_height:Number,color:uint):MovieClip {
        var mc:MovieClip=new MovieClip();
        mc.graphics.beginFill(color);
        mc.graphics.drawRect(0,0,_width,_height);
        mc.graphics.endFill();
        mc.color=color;
        pieces.push(mc);
        return mc;
    }

对数据结构的改进已经可见 - 您需要将传递的 _width_height 存储在 MC 中的某处,因为实际的 width> 的 MC 将与默认线宽(1,两侧为 0.5)传递的不同.不过,xy 是从 MC 的属性中正确检索的.因此,需要将这两行都添加到 createRectangle 中.

A refinement to data structure is already visible - you need to store the passed _width and _height in the MC somewhere, because the actual width of that MC will differ from what's passed by the default line thickness (1, 0.5 on either side). x and y are properly retrieved from MC's properties, though. So, adding both lines into createRectangle is necessary.

mc._width=_width;
mc._height=_height;

有了这个,序列化 Board 变得更加容易.

With this, serializing the Board becomes more easy.

public function writeExternal(output:IDataOutput):void {
    var pl:int=pieces.length; // cache
    output.writeInt(pl); // assuming we keep this array in integral state
    for (var i:int=0;i<pl;i++) {
        var _mc:MovieClip=pieces[i];
        output.writeDouble(_mc.x); // this is usually not rounded when dragging, so saving as double
        output.writeDouble(_mc.y);
        output.writeDouble(_mc._width);
        output.writeDouble(_mc._height);
        output.writeInt(_mc._color);
    }
    // if anything is left about the "Board" itself, write it here
    // I'm assuming nothing is required to save
}

要恢复,您需要从IDataInput按照与writeExternal中写入的相同顺序读取数据,然后进行处理重建我们存储的显示列表.

To restore, you need to read the data out of IDataInput in the very same order as it was written in writeExternal and then process to rebuilding the display list we've stored.

public function readExternal(input:IDataInput):void {
    // by the time this is called, the constructor has been processed
    // so "pieces" should already be an instantiated variable (empty array)
    var l:int;
    var _x:Number;
    var _y:Number;
    var _width:Number;
    var _height:Number;
    var _color:uint;
    // ^ these are buffers to read data to. We don't yet have objects to read these into
    input.readInt(l); // get pieces length
    for (var i:int=0;i<l;i++) {
        input.readDouble(_x);
        input.readDouble(_y);
        input.readDouble(_width);
        input.readDouble(_height);
        input.readInt(_color);
        // okay we got all the data representing the rectangle, now make one
        var mc:MovieClip=createRectangle(_width,_height,_color);
        mc.x=_x;
        mc.y=_y;
        addChild(mc); // createRectangle does NOT have addchild call
        // probably because there are layers for the parts to be added to
        // I'm assuming there are no layers here, but you might have some!
        // pieces array is populated inside createRectangle, so we leave it alone
    }
    // read all the data you have stored after storing pieces
}

如果您的嵌套 MC 有一个类也实现了 IExternalizable,您可以将整个数组保存在单个指令中,writeObject(pieces),这将使 Flash遍历数组,找到它包含的所有数据,并在任何嵌套对象上调用 writeObject,本质上是为数组中的每个实例调用该类的 writeExternal 函数.恢复这样的数组应该包括通过遍历数组并在每个恢复的实例上调用 addChild() 来重建显示列表.

In case your nested MCs have a class that also implements IExternalizable, you can save the entire array in a single instruction, writeObject(pieces), this will make Flash walk through the array, find all data it contains and call writeObject on any nested object, essentially calling that class's writeExternal function for each of the instance in the array. Restoring such an array should include rebuilding the display list by walking the array and calling addChild() on each of the restored instances.

最后但并非最不重要的一点是,应该在对自定义对象进行任何序列化或反序列化之前调用 registerClassAlias().调用它们的最佳位置可能是您的主对象的构造函数,因为它肯定会在您的应用程序包含的任何其他代码之前被调用.

And last but not the least, registerClassAlias() should be called prior to doing any serialization or deserialization of custom objects. Best place to call these is probably your main object's constructor, as this will surely be called before any other code your application contains.

这篇关于使用“文件"保存场景对象位置以便稍后在 AS3 中重建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆