actionscript 3 - AS3 में बाद में पुनर्निर्माण के लिए दृश्य वस्तु स्थानों को बचाने के लिए 'फ़ाइल' का उपयोग करना




actionscript-3 flash (4)

मैं निम्न जानकारी को बचाने के लिए एक्शन स्क्रिप्ट 3 में 'फ़ाइल' फ़ंक्शन का उपयोग करने का प्रयास कर रहा हूं:

मेरे पास दृश्य में ड्रैगएबल डिस्प्ले ऑब्जेक्ट्स भिन्न हैं, राशि और प्रकार भिन्न हो सकते हैं। मैं राशि और उनकी स्थिति को बचाने और फिर उन्हें भविष्य के सत्र में वापस लोड करना चाहता हूँ।

मैं कुछ भी सहेजने के लिए फ़ाइल का उपयोग करने के लिए संघर्ष कर रहा हूं, मैंने एडोब प्रलेखन खोजा है और मेरे सिर का उपयोग कैसे करना है इसका इस्तेमाल करना नहीं है I

मैंने अभी तक इसका उपयोग करते हुए कोई भी कोड विकसित नहीं किया है।

किसी भी सहायता की सराहना की जाएगी।

धन्यवाद।


आप सीधे एक फाइल में DisplayObject लिखने का प्रयास कर रहे हैं, फ्लैश इंजन द्वारा फ़्लैश ऑब्जेक्ट से रोका जा सकता है क्योंकि फ्लैश किसी ऑब्जेक्ट के डिफॉल्ट सीरियलाइजेशन को संभालता है। बाह्य संसाधन में एक DisplayObject को सहेजने के लिए, आपको उस ऑब्जेक्ट के वर्ग और वस्तुओं के किसी भी वर्ग पर IExternalizable को नियोजित करने की आवश्यकता होगी, जिसे आप स्टोर करने की योजना भी करेंगे। writeExternal कार्यान्वयन के लिए आवश्यक सभी डेटा को खरोंच से पुन: निर्माण करने के लिए आवश्यक सभी डेटा को सहेजना चाहिए, और readExternal जाना चाहिए नेस्टेड प्रदर्शन ऑब्जेक्ट्स पर addChild() को प्रदर्शित करके, या अन्य आंतरिक संरचनाओं में उन्हें जोड़कर कहा जाता है कि डिस्प्लेऑब्जेक्ट की अखंडता को पुनर्स्थापित करने के लिए readExternal भी तरीकों को नियोजित करना चाहिए होते हैं।

ध्यान दें, अन्य उत्तरों में XML या JSON के साथ कस्टम सीरियललाइज़ करने के लिए वैध अंक होते हैं, और इसमें लिंक शामिल हैं, विशेष रूप से, flash.utils.registerClassAlias हिस्सा।

एक उदाहरण: मान लीजिए कि आपके पास एक Board क्लास में ड्राइंग बोर्ड है, और आयताकारों का एक सेट है जिसे आप माउस का उपयोग करके खींच सकते हैं, जो कि आकार और रंग से भिन्न होता है आयत कस्टम बनाया MovieClip और अपने पास एक वर्ग नहीं है, लेकिन प्रत्येक MovieClip को उनके भेद को सरल बनाने के लिए color संपत्ति भी सौंपी जाती है। इसका मतलब है कि आपको Board क्लास पर IExternalizable को कार्यान्वित करने की आवश्यकता है। मान लीजिए कि Board क्लास में एक pieces सरणी होती है जिसमें नेस्टेड आयत के सभी लिंक होते हैं, और मापदंडों के रूप में प्रदान की जाने वाली चौड़ाई, ऊंचाई और रंग के आधार पर एक नया ठीक आकार का आयताकार बनाने की एक विधि। (आपके मामले में मिलने के लिए Board की डेटा संरचना के लिए और अधिक आवश्यकताएं हो सकती हैं, इसलिए बारीकी से देखें) तो, सीरियलाइजिंग Board की प्रक्रिया नेस्टेड एमसीएस से सभी आंकड़े इकट्ठा करने और इसे IDataOutput आपूर्ति की जाएगी, और Board एक उदाहरण को बहाल करने की प्रक्रिया को संग्रहीत डेटा को पुनः प्राप्त करना चाहिए, इसे खोजने के लिए पार्स करें कि कहां है, नेस्टेड एमसीएस को उसी तरह बनाते हैं जैसे कि वे संग्रहीत किए गए हैं, उन्हें ठीक से रखें, addChild() to self and rebuild the टुकड़े addChild() to self and rebuild the टुकड़ों addChild() to self and rebuild the पुनः addChild() to self and rebuild the

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 को संग्रहित करने की आवश्यकता है, क्योंकि उस एमसी की वास्तविक width डिफ़ॉल्ट लाइन मोटाई (1, 0.5 दोनों तरफ) से पारित होने से भिन्न होगी। एमसी के गुणों से x और y ठीक से प्राप्त हुए हैं, यद्यपि। इसलिए, बनाने में दोनों लाइनें जोड़कर createRectangle आवश्यक है।

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

इसके साथ, Board क्रमबद्ध करना अधिक आसान हो जाता है

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 होगा क्योंकि इसे लिखे गए में लिखा गया था, और उसके बाद हमने जो संग्रह सूची को संग्रहित किया है उसे पुनर्निर्माण करने की प्रक्रिया शुरू कर दी है।

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
}

यदि आपके नेस्टेड MCs में एक वर्ग है जो IExternalizable भी कार्यान्वित IExternalizable , तो आप एक ही निर्देश, IExternalizable writeObject(pieces) में पूरी सरणी को सहेज सकते हैं, यह IExternalizable को सरणी के माध्यम से IExternalizable होगा, इसमें मौजूद सभी डेटा ढूंढें और किसी नेस्टेड ऑब्जेक्ट पर writeObject ऑब्जेक्ट को कॉल करें , अनिवार्य रूप से उस क्लास के writeExternal । इस तरह के एक addChild() को बहाल करने से प्रत्येक सूची को बहाल करने के लिए सरणी addChild() और addChild() को कॉल करके प्रदर्शन सूची को पुनर्निर्माण करना चाहिए।

और आखिरी लेकिन कम से कम, registerClassAlias() क्लास अलाइज registerClassAlias() को कस्टम ऑब्जेक्ट्स के किसी भी सीरियलाइज़ेशन या डिसेराइजेशन करने से पहले बुलाया जाना चाहिए। इन्हें कॉल करने के लिए सर्वश्रेष्ठ स्थान संभवत: आपके मुख्य ऑब्जेक्ट के कन्स्ट्रक्टर हैं, क्योंकि यह निश्चित रूप से किसी भी अन्य कोड से पहले आपको फोन किया जाएगा।


आपके पास पहले से ही कुछ उत्तर दिए गए हैं लेकिन आपके प्रश्न से, शायद आप बड़े संदर्भ को याद कर रहे हैं।

तो File वर्ग डिस्क पर एक फ़ाइल के लिए पथ का प्रतिनिधित्व करता है और FileStream वर्ग उस फ़ाइल को डेटा पढ़ने और लिखने में सक्षम बनाता है। ये उपयोग करना आसान है और वेब पर कई उदाहरण हैं। यहां एडोब से एक ट्यूटोरियल है: फाइल पढ़ना और लिखना

लेकिन क्या डेटा लिखना है और प्रारूप और डेटा प्रकार क्या है? ये अधिक महत्वपूर्ण और अधिक दिलचस्प सवाल हैं

सबसे आसान तरीका एक text आधारित प्रारूप का उपयोग करना है जैसे XML या JSON जहां आप चाहते हैं कि Sprites (या अन्य ऑब्जेक्ट्स) के गुणों को पढ़ते और लिखते हैं इसका एक फायदा यह है कि परिणामी फ़ाइल मानव पठनीय / संपादन योग्य पाठ फ़ाइल है। एक मामूली नुकसान यह है कि आपको यह निर्दिष्ट करने की आवश्यकता है कि कौन से प्रॉपर्टी सहेजने और पुनर्स्थापना करने और सरल डेटा प्रकार रूपांतरण (स्ट्रिंग इत्यादि, आदि) से निपटने के लिए है।

एक अधिक मजबूत दृष्टिकोण का प्रयोग करना है जिसे Serialization कहा जाता है, जहां एक संपूर्ण ऑब्जेक्ट की स्थिति को सहेजा और पुनर्स्थापित किया जाता है। यह अधिक जटिल है और कठिन नहीं है, संभवतः आपकी परियोजना की जरूरतों के लिए अतिरेक है। यहां अच्छे उदाहरण और चर्चाएं हैं , यहां और यहां

आपके मौजूदा प्रोजेक्ट और कौशल स्तर के लिए, मैं XML या JSON का उपयोग करने का सुझाव देता हूं यहां एक XML का उपयोग करते हुए ट्यूटोरियल है: लोड हो रहा है और प्रसंस्करण बाह्य XML फ़ाइलें


सहेजने के लिए अपनी सारी वस्तुओं को मानते ही एक ही माता-पिता से संबंधित हैं, आप इन पंक्तियों के साथ कुछ भी कर सकते हैं:

सबसे पहले, एक क्लास फ़ाइल बनाएं (चलिए कॉल करें SaveData.as और इसे अपनी प्रोजेक्ट डायरेक्टरी की जड़ में डाल दिया है)। यह उस डेटा का वर्णन करेगा जिसे आप सहेजना चाहते हैं:

package 
{
    import flash.geom.Rectangle;

    public class SaveData 
    {
        public var bounds:Rectangle; //to save where an object is on the stage
        public var classType:Class; //to save what kind of object it is

        //you could add in more proterties, like rotation etc


        public function SaveData() {

        }
    }
}

इसके बाद, आपके फ़ंक्शन को बचाने के लिए, ऐसा कुछ करें:

    //this will hold all your data
    //a vector is the same as an array only all members must be of the specified type
    var itemList:Vector.<SaveData> = new Vector.<SaveData>();

    //populate the array/vector with all the children of itemContainer
    var tmpItem:SaveData;
    //loop through all children of item container
    for (var i:int = 0; i < itemContainer.numChildren; i++) {
        tmpItem = new SaveData(); //create a new save record for this object
        tmpItem.bounds = itemContainer.getChildAt(i).getBounds(itemContainer); //save it's bounds
        tmpItem.classType = getDefinitionByName(itemContainer.getChildAt(i)) as Class; //save it's type
        itemList.push(tmpItem);  //add it to the array
    }

    //Now you have an array describing all the item on screen

    //to automatically serialize/unserialize, you need this line (and you need to register every class nested in SaveData that isn't a primitive type - which would just be Rectangle in this case
    registerClassAlias("SaveData", SaveData);
    registerClassAlias("flash.geom.Rectangle", Rectangle);

    //create a new File to work with
    var file:File = File.applicationStorageDirectory; //or whatever directory you want
    file.resolvePath("saveData.data"); //or whatever you want to call it
    var fileStream:FileStream = new FileStream();
    fileStream.open(file, FileMode.WRITE);
    fileStream.writeObject(itemList); //write the array to this file
    fileStream.close();

अब, इसे वापस में लोड करने के लिए:

    var itemContainer:Sprite = new Sprite(); //however you initialize this
    addChild(itemContainer);

    var file:File = File.applicationStorageDirectory;
    file.resolvePath("saveData.data");
    var fileStream:FileStream = new FileStream();
    fileStream.open(file, FileMode.READ);
    var itemList:Vector.<SaveData> = fileStream.readObject() as Vector.<SaveData>;
    fileStream.close();

    //now that you've read in the array of all items from before, you need to recreate them:
    var tmpItem:DisplayObject;
    var tmpClass:Class;
    //loop through all items in the array, and create a object
    for (var i:int = 0; i < itemList.length; i++) {
        tmpClass = itemList[i].classType; //The type of item
        tmpItem = new tmpClass() as DisplayObject; //create the item

        //now move the item to it's former position and scale
        tmpItem.x = itemList[i].x;
        tmpItem.y = itemList[i].y;
        tmpItem.width = itemList[i].width;
        tmpItem.height = itemList[i].height;

        //add the item back to the parent
        itemContainer.addChild(tmpItem);
    }

यदि आप आयात के बारे में सुनिश्चित नहीं हैं, तो वे यहां हैं:

import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.registerClassAlias;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;

var bytes:ByteStream;
var filename:String = "mySaveFile.sav";    

//[...] //initialize byte stream with your data 

//get a reference to where you want to save the file 
//(in this example, in the application storage directory, 
//which is fine if you don't need to move the save file between computers

var outFile:File = File.applicationStorageDirectory;
outFile = outFile.resolvePath(fileName);

//create a file output stream, which writes the byte stream to the file 
var outStream:FileStream = new FileStream();
outStream.open(outFile, FileMode.WRITE);
outStream.writeBytes(bytes, 0, bytes.length);
outStream.close();


//to load the file:
var inFile:File = File.applicationStorageDirectory;
inFile = inFile.resolvePath(fileName);

bytes = new ByteArray();

var inStream:FileStream = new FileStream();
inStream.open(inFile, FileMode.READ);
inStream.readBytes(bytes);
inStream.close();