使用writeObject保存对象:使用此方法可以保存哪些对象?

时间:2016-11-22 21:04:01

标签: actionscript-3

我正在努力进入令人兴奋的byteArrays世界!

结束目标

我希望保存每个游戏元素的位置和其他属性(在这种情况下,突破克隆中的块)作为我的应用程序的关卡设计功能的一部分,并且还可以更轻松地设计游戏关卡。< / p>

当前方法

将自定义类实例(砖块)的Vector中的数据转换为ByteArray,并将该数据保存到文本文件中。它似乎就像这一点工作得很好(直到我成功将数据提取回Vector对象,因为保存的文本文件是纯gobbledygook)。

我通过将文本文件读入byteArray然后将writeObject()写入Vector来加载一个关卡设计,目的是让一个包含所有砖块的向量(这不起作用)。

问题

当我尝试运行我的加载函数时,文件加载,byteArray被数据“填充”,但当我尝试writeObject时,我得到所有这些错误(以下错误的一个副本)对于矢量中的每个砖块。

TypeError: Error #1034: Type Coercion failed: cannot convert Object@92cdcb9 to flash.geom.Point.
TypeError: Error #1034: Type Coercion failed: cannot convert Object@92cde09 to flash.geom.Point.
TypeError: Error #1034: Type Coercion failed: cannot convert Object@92df041 to flash.geom.ColorTransform.
TypeError: Error #1034: Type Coercion failed: cannot convert Object@92df161 to flash.geom.Point.
TypeError: Error #1034: Type Coercion failed: cannot convert Object@92df281 to flash.geom.Point.
TypeError: Error #1034: Type Coercion failed: cannot convert Object@92df431 to flash.media.SoundTransform.
TypeError: Error #2004: One of the parameters is invalid.

我的自定义砖类是Sprite类的扩展。但它还具有依赖于PointColorTransform对象的属性。奇怪的是,在我的自定义类中没有任何地方可以引用或使用SoundTransform ...所以这个错误看起来很奇怪。如果有人想看,我会发布我的自定义课程。

我的保存和加载方法

    private function saveLevelDesign(brVec:Vector.<LineTestBlock>):void{
        trace("save");
        var file:File = File.documentsDirectory; 
        file = file.resolvePath("AnimationFiles/brickLevels/lev_001.txt"); 
        fileStream.open(file,FileMode.WRITE);
        var bytes:ByteArray = new ByteArray();
        bytes = brickArrayToByteArray(brVec);
        //fileStream.close();
    }

    private function loadLevelDesign():void{
        trace("loadLevelDesign");
        var file:File = File.documentsDirectory;
        file = file.resolvePath("AnimationFiles/brickLevels/lev_001.txt");
        fileStream.open(file,FileMode.READ);
        file.addEventListener(IOErrorEvent.IO_ERROR,ioError);
        file.addEventListener(Event.COMPLETE, loaded); 
        file.load(); 
        //fileStream.open(file,FileMode.READ);          
    }

    private function ioError(ioE:IOErrorEvent):void{
        trace("oops",ioE);
    }

    private function loaded(e:Event):void{
        trace("loaded");
        var bytes:ByteArray = new ByteArray();
        fileStream.readBytes(bytes);
        trace(bytes.length,"bytes length"); // 0 bytes length
        var vec:Vector.<LineTestBlock> = new Vector.<LineTestBlock>;
        for (var i:int = 4; i < _playerTurn._brickArray.length; i++){
            vec.push(_playerTurn._brickArray[i]);
        }
        bytes.writeObject(vec);
        trace(bytes.length,"bytes length"); // 53516 bytes length

        destroyBricks(_playerTurn); // just removes all bricks on the stage 

        vec = byteArrayToBrickArray(bytes); // calling this function throws all those errors
        trace("vector length:",vec.length); // vector length 208 (this is the correct number of bricks, so that's good)
    }

我的字节转换方法

    private function byteArrayToBrickArray(bytes:ByteArray):Vector.<LineTestBlock>{
        bytes.position = 0;

        var blocks:Vector.<LineTestBlock> = bytes.readObject() as Vector.<LineTestBlock>;
        trace(bytes.position);
        return blocks;
    }

    private function brickArrayToByteArray(brVec:Vector.<LineTestBlock>):ByteArray{
        var bytes:ByteArray = new ByteArray();
        /*for (var i:int = 0; i < brVec.length; i++){
            if (brVec[i]._break == true){
                bytes.writeObject(brVec[i]);
            }
        }*/
        bytes.writeObject(brVec);
        return bytes;
    }

任何人都会看到我做错了什么,或者不理解某些事情?

2 个答案:

答案 0 :(得分:2)

如果您同时编写IExternalizable和{{1},那么实现DisplayObject或不是ByteArray的任何对象都可以保存在readExternal中并从中恢复。方法正确。如果一个对象没有实现writeExternal,Flash将尝试使用代码可见的公共组件来编写它,并通过以相同的顺序将读取的值分配给公共属性来读取它。通常,您应该使用比IExternalizable更复杂的任何接口。因此,您需要在Vector.<int>类中实现IExternalizable,只编写和读取所需的属性。此外,您只能将此方法用于具有空构造函数的对象,因为在LineTestBlock中首先构造对象,然后分配值。

The manual on IExternalizable。由于某种原因,你无法从普通的类树访问它,但它就在那里,界面正在工作。

我会通过将所有向量IDataInput.readObject等封装到一个类中来改变您的方法,比如SoundTransform,然后在其中实现Level,然后将其写入所有简单的数据类型按顺序排列(记得在数据之前写入向量的长度!),然后从字节数组中读取自身并同时重建所有内部数据结构。一个例子:

IExternalizable

最后,您可能需要在应用初始化的某个位置执行flash.net.registerClassAlias()调用,以便将import flash.utils.*; public class Level implements flash.utils.IExternalizable { private var blocks:Vector.<LineTestBlock>; // something extra public function writeExternal(output:IDataOutput):void { var l:int=blocks.length; output.writeInt(l); for (var i:int=0;i<l;i++) { //write all the blocks[i]'s properties in order to output } // same approach to write all the extra properties } public function readExternal(input:IDataInput):void { var l:int=input.readInt(); blocks=new Vector.<LineTestBlock>(); for (var i:int=0;i<l;i++) { // first read all the properties into any local variables in the VERY SAME order they were written // then create an instance of LineTestBlock var block:LineTestBlock=new LineTestBlock(...); // required parameters for the constructor should be read before creating object // then fill remaining properties to the created instance blocks.push(block); // and reconstruct the array } // same approach to every property that was saved // reconstruct everything else that's depending on the data read } } 识别为可序列化的类。

答案 1 :(得分:1)

bytes.readObject()返回一个Object。 所以问题是关于将Object转换为Vector.<LineTestBlock>,因此您必须将其转换为自己

private function byteArrayToBrickArray(bytes:ByteArray):Vector.<LineTestBlock>{
    bytes.position = 0;

    // Edit : readObject() only presents an Object
    var blocks:Object = bytes.readObject();
    trace(bytes.position);

    /* you have to convert all step by step
     at first we have to assume blocks as a vector
     best way to searching its items is using _for key in_
    */
    var converted:Vector.<LineTestBlock> = new Vector.<LineTestBlock>(blocks.length);
    for (var key:String in blocks) {
        converted.push(objectToLineTestBlock(blocks[key]));
    }
    return converted;
}

因为我不知道你的LineTestBlock类的结构,我不能完全提供“objectToLineTestBlock”函数

以下是模拟LineTestBlock类的示例

我自己的LineTestBlock Class

public class LineTestBlock
{
    public var w:int;
    public var loc:Point;
    public var stf:SoundTransform;

    public function LineTestBlock(_w:int, _loc:Point, _stf:SoundTransform)
    {
        w = _w;
        loc = _loc;
        stf = _stf;
    }
}

测试解决方案的主要类。

我所做的只是将所有对象转换为它们的真实含义 bytearray.readObject()将所有类转换为纯对象

public class ByteTest extends Sprite
{
    public function ByteTest()
    {
        var save_vector:Vector.<LineTestBlock> = new Vector.<LineTestBlock>();
        var block_item1:LineTestBlock = new LineTestBlock(200, new Point(-1, 1), new SoundTransform(0.5));
        var block_item2:LineTestBlock = new LineTestBlock(400, new Point(-2, 2), new SoundTransform(0.25));
        save_vector.push(block_item1);
        save_vector.push(block_item2);
        var load_vector:Vector.<LineTestBlock>;

        var bytes:ByteArray = new ByteArray();

        bytes.writeObject(save_vector);
        // trace(bytes.position);
        load_vector = objectToLineTestVector(bytes);
        // now test to check if everything is OK
        trace(load_vector[1].stf.volume); // must print 0.25
    }
    public function objectToLineTestVector(bytes:ByteArray):Vector.<LineTestBlock> {
        bytes.position = 0;
        var loadedObject:Object = bytes.readObject();
        var blocks:Vector.<LineTestBlock> = new Vector.<LineTestBlock>();
        for (var key:String in loadedObject) {
            blocks.push(objectToLineTestBlock(loadedObject[key])); // loadedObject[key] is a block_item1 and could be converted
        }
        return blocks;
    }
    public function objectToLineTestBlock(obj:Object):LineTestBlock {
        return new LineTestBlock(obj.w, objectToPoint(obj.loc), objectToSoundTransform(obj.stf));
    }
    public function objectToPoint(obj:Object):Point {
        return new Point(obj.x, obj.y);
    }
    public function objectToSoundTransform(obj:Object):SoundTransform {
        return new SoundTransform(obj.volume);
    }

}