我正在努力进入令人兴奋的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类的扩展。但它还具有依赖于Point
和ColorTransform
对象的属性。奇怪的是,在我的自定义类中没有任何地方可以引用或使用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;
}
任何人都会看到我做错了什么,或者不理解某些事情?
答案 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);
}
}