关于使用SharedObject来缓存游戏图片或者swf文件资源到客户端本地的研究

目前市面上已经有很多游戏采用了把图片缓存到玩家客户端的做法,这种方法有利有弊,因为并不是所有的玩家都希望自己的电脑的某个角落被放入过多的缓存文件,久而久之造成电脑性能下降;但是总的来说这种技术还是好的:第一,webgame的总体资源也是有限的,不会有太大的容量占用,而且对于程序来说一般只缓存一些核心资源,比如使用很频繁的资源以及需要下载较长时间的大背景大图片或者容量稍大的swf文件等;第二,可以大幅度提升玩家第二次进入游戏的速度,某种意义上可以提升游戏体验度;

    好了,废话少说,下面直接说说怎么使用SharedObject来做到把图片或者swf文件缓存到客户端,并在第二次进入程序的时候直接使用缓存的数据还原成想要的原始图片或者swf文件;主要思想是:通过URLStream把显示对象加载进来获得其ByteArra的原始数据,然后通过shareObject把二进制保存到客户端的本地,那么下次进入程序的时候直接可以通过ShareObject获得上次保存的二进制数据,有了二进制数据,只需要通过Loader.loadByte()函数就可以把二进制数据转换成DisplayObject对象;

    1.首先我们使用SharedObject来写一个Cookie类:Cookie.as的代码如下:

  1. ////////////////////////////////////////////////////////////////////////////////   
  2. // WEBGAME Confidential    
  3. // Copyright 2011. All rights reserved.    
  4. //    
  5. // Cookie.as   
  6. // Summary // TODO Auto-generated summary stub   
  7. // Version 1.0   
  8. // Author txiejun   
  9. // Created Nov 4, 2011 10:46:36 PM   
  10. ////////////////////////////////////////////////////////////////////////////////   
  11. package aurora.store  
  12. {  
  13.     import flash.events.NetStatusEvent;  
  14.     import flash.net.SharedObject;  
  15.     import flash.net.SharedObjectFlushStatus;  
  16.     import flash.utils.getQualifiedClassName;  
  17.       
  18.     /** 
  19.      *   
  20.      * @author txiejun 
  21.      * @contact txiejun@126.com 
  22.      * @created Nov 4, 2011 10:46:36 PM 
  23.      */  
  24.     public class Cookie  
  25.     {  
  26.         private var _name:String = null;  
  27.         private var _path:String = null;  
  28.         private var _shdobj:SharedObject;  
  29.         private var flushStatus:String = null;  
  30.         /** 
  31.          *  minDiskSpace KB 空间的存储量 小于 minDiskSpace的数量将不会有提示框弹出 
  32.          */   
  33.         public var minDiskSpace:int = 0;  
  34.           
  35.         public function Cookie(name:String,path:String=null,minDiskSpace:int=0)  
  36.         {  
  37.             _name = name;  
  38.             _path = path;  
  39.             this.minDiskSpace = minDiskSpace;  
  40.             _shdobj = SharedObject.getLocal(name,_path);  
  41.         }  
  42.           
  43.         private function onFlushStatus(event:NetStatusEvent):void   
  44.         {  
  45.             switch (event.info.code)   
  46.             {  
  47.                 case "SharedObject.Flush.Failed":  
  48.                     trace(getQualifiedClassName(this)+".onFlushStatus() Error: Failed write SharedObject to disk.");  
  49.                     break;  
  50.             }  
  51.               
  52.             _shdobj.removeEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);  
  53.         }  
  54.           
  55.         private function flushValue():void  
  56.         {  
  57.             flushStatus =null;  
  58.             try   
  59.             {  
  60.                 flushStatus = _shdobj.flush(minDiskSpace);  
  61.             }   
  62.             catch (error:Error)   
  63.             {  
  64.                 trace(getQualifiedClassName(this)+".setCookie() Error: Could not write SharedObject to disk.");  
  65.             }  
  66.             if(flushStatus != null)   
  67.             {  
  68.                 switch(flushStatus)   
  69.                 {  
  70.                     case SharedObjectFlushStatus.PENDING:  
  71.                         trace(getQualifiedClassName(this)+".setCookie() Requesting permission to save value.");  
  72.                         _shdobj.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);  
  73.                         break;  
  74.                 }  
  75.             }  
  76.         }  
  77.           
  78.         public function getName():String  
  79.         {  
  80.             return _name;  
  81.         }  
  82.           
  83.         public function getPath():String  
  84.         {  
  85.             return _path;  
  86.         }  
  87.           
  88.         /** 
  89.          *  如果value==null 意味着删除此key 
  90.          *  如果此Key已经有值了,则原来的值被替换,并返回原来的值 
  91.          * @param key 
  92.          * @param value 
  93.          * @return  
  94.          *  
  95.          */       
  96.         public function setData(key:String,value:*):*  
  97.         {  
  98.             if(key == null)  
  99.             {  
  100.                 throw new ArgumentError("cannot put a value with undefined or null key!");  
  101.                 return undefined;  
  102.             }  
  103.             else if(value == null)  
  104.             {  
  105.                 return remove(key);  
  106.             }  
  107.             else  
  108.             {  
  109.                 var oldValue:* = getData(key);  
  110.                 _shdobj.data[key]=value;  
  111.                 flushValue();  
  112.                 return oldValue;  
  113.             }  
  114.         }  
  115.           
  116.         public function getData(key:String):*  
  117.         {  
  118.             if(!hasKey(key))  
  119.             {  
  120.                 return undefined;  
  121.             }  
  122.             else  
  123.             {  
  124.                 return _shdobj.data[key];  
  125.             }  
  126.               
  127.         }  
  128.           
  129.         public function remove(key:*):*  
  130.         {  
  131.             if(!hasKey(key))  
  132.             {  
  133.                 return null;  
  134.             }  
  135.             var temp:* = _shdobj.data[key];  
  136.             delete _shdobj.data[key];  
  137.             return temp;  
  138.         }  
  139.           
  140.         public function hasData(key:String):Boolean  
  141.         {  
  142.             if(!hasKey(key))  
  143.             {  
  144.                 return false;  
  145.             }  
  146.             else  
  147.             {  
  148.                 return _shdobj.data[key]!=null;  
  149.             }  
  150.         }  
  151.         public function hasKey(key:*):Boolean  
  152.         {  
  153.             return _shdobj.data.hasOwnProperty(key);  
  154.         }  
  155.         /** 
  156.          *  清除所有数据并从磁盘删除共享对象 
  157.          *  
  158.          */   
  159.         public function clear():void  
  160.         {  
  161.             _shdobj.clear();  
  162.         }  
  163.     }  
  164. }  

2.通过上面的cookie.as类可以实现像普通浏览器的cookie那样的功能 在本地写入或者读出数据,一般是二进制数据,int,String,Object,xml等格式;这是一个工具类;

下面再贡献一个BitmapUtil.as工具类 主要作用是用来把二进制byteArray数据装换成DisplayObject显示对象;或者把一张Bitmap转换成二进制格式的数据;

BitmapUtil.as代码如下:

  1. ////////////////////////////////////////////////////////////////////////////////   
  2. // WEBGAME Confidential    
  3. // Copyright 2011. All rights reserved.    
  4. //    
  5. // BitmapUtil.as   
  6. // Summary // TODO Auto-generated summary stub   
  7. // Version 1.0   
  8. // Author txiejun   
  9. // Created Nov 4, 2011 1:57:07 PM   
  10. ////////////////////////////////////////////////////////////////////////////////   
  11. package aurora.graphic  
  12. {     
  13.     import flash.display.Bitmap;  
  14.     import flash.display.BitmapData;  
  15.     import flash.display.DisplayObject;  
  16.     import flash.display.Loader;  
  17.     import flash.display.LoaderInfo;  
  18.     import flash.display.Sprite;  
  19.     import flash.events.Event;  
  20.     import flash.events.IOErrorEvent;  
  21.     import flash.geom.Matrix;  
  22.     import flash.utils.ByteArray;  
  23.     import flash.utils.getQualifiedClassName;  
  24.       
  25.     /** 
  26.      * 
  27.      * @author txiejun 
  28.      * @contact txiejun@126.com 
  29.      * @created Nov 4, 2011 1:57:07 PM 
  30.      */  
  31.     public class BitmapUtil  
  32.     {  
  33.         public function BitmapUtil()  
  34.         {  
  35.         }  
  36.                   
  37.         /** 
  38.          *  把 ByteArray装换成DisplayObject 
  39.          * @param byteArray 
  40.          * @param callBack 
  41.          *  
  42.          */       
  43.         public static function toDisplayObject(byteArray:ByteArray,callBack:Function):void  
  44.         {  
  45.             if(byteArray==null)  
  46.             {  
  47.                 if(callBack!=null)  
  48.                 {  
  49.                     callBack.call(null,null);  
  50.                 }  
  51.                 return;  
  52.             }  
  53.                   
  54.             var loader:Loader = new Loader();  
  55.             var onCompleteHandler:Function = function(event:Event):void  
  56.             {  
  57.                 var loaderInfo:LoaderInfo = event.currentTarget as LoaderInfo;  
  58.                 var content:DisplayObject = loaderInfo.content;  
  59.                 loaderInfo.removeEventListener(Event.COMPLETE, onCompleteHandler);  
  60.                 loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIoErrorHandler);  
  61.                   
  62.                 if(callBack!=null)  
  63.                 {  
  64.                     callBack.call(null,content);  
  65.                 }  
  66.                 loader = null;  
  67.             }  
  68.             var onIoErrorHandler:Function = function(event:IOErrorEvent):void  
  69.             {  
  70.                 var loaderInfo:LoaderInfo = event.currentTarget as LoaderInfo;  
  71.                 loaderInfo.removeEventListener(Event.COMPLETE, onCompleteHandler);  
  72.                 loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIoErrorHandler);  
  73.                 trace(getQualifiedClassName(this)+".toDisplayObject() :"+event.text);  
  74.                 if(callBack!=null)  
  75.                 {  
  76.                     callBack.call(null,null);  
  77.                 }  
  78.             }  
  79.             loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);  
  80.             loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoErrorHandler);  
  81.             loader.loadBytes(byteArray);  
  82.         }  
  83.           
  84.     }  
  85. }  

这两个工具类写好了以后,就可以开始写主程序了;

ShareObjectTest.as文件如下:

 

  1. ////////////////////////////////////////////////////////////////////////////////   
  2. // WEBGAME Confidential    
  3. // Copyright 2011. All rights reserved.    
  4. //    
  5. // ShareObjectTest.as   
  6. // Summary // TODO Auto-generated summary stub   
  7. // Version 1.0   
  8. // Author txiejun   
  9. // Created Nov 5, 2011 12:31:10 AM   
  10. ////////////////////////////////////////////////////////////////////////////////   
  11. package  
  12. {  
  13.     import aurora.graphic.BitmapUtil;  
  14.     import aurora.store.Cookie;  
  15.       
  16.     import flash.display.DisplayObject;  
  17.     import flash.display.Sprite;  
  18.     import flash.display.StageAlign;  
  19.     import flash.display.StageScaleMode;  
  20.     import flash.events.Event;  
  21.     import flash.events.IOErrorEvent;  
  22.     import flash.net.URLRequest;  
  23.     import flash.net.URLStream;  
  24.     import flash.utils.ByteArray;  
  25.       
  26.       
  27.     /** 
  28.      * 
  29.      * @author txiejun 
  30.      * @contact txiejun@126.com 
  31.      * @created Nov 5, 2011 12:31:10 AM 
  32.      */  
  33.     public class ShareObjectTest extends Sprite  
  34.     {  
  35.         private var assests:Array = ["mc_1.swf","img_1.png"];  
  36.         private var cookie:Cookie ;  
  37.         private var index:int = 1;  
  38.         public function ShareObjectTest()  
  39.         {  
  40.             super();  
  41.             if(stage)  
  42.             {  
  43.                 stage.align = StageAlign.TOP_LEFT;  
  44.                 stage.scaleMode = StageScaleMode.NO_SCALE;  
  45.                 stage.stageFocusRect = false;  
  46.             }  
  47.               
  48.             cookie = new Cookie("ShareObjectTest");  
  49. //          cookie.clear();   
  50.             loadAssest(assests[index]);  
  51.         }  
  52.           
  53.         private function loadAssest(url:String):void  
  54.         {  
  55.             //检查是否已经加载过资源   
  56.             if(cookie.hasData(url))  
  57.             {  
  58.                 //获得缓存的二进制数据   
  59.                 var byteArray:ByteArray = cookie.getData(url);  
  60.                 //转换成显示对象   
  61.                 BitmapUtil.toDisplayObject(byteArray,onLoaded);  
  62.                 trace("url",url,"already loaded");  
  63.             }  
  64.             else  
  65.             {  
  66.                 //加载二进制数据   
  67.                 var urlstream:URLStream = new URLStream();  
  68.                 urlstream.addEventListener(Event.COMPLETE,onStreamComplete);  
  69.                 urlstream.addEventListener(IOErrorEvent.IO_ERROR,onIOError);  
  70.                 urlstream.load(new URLRequest(url));  
  71.                 trace("url",url,"need load");  
  72.             }  
  73.               
  74.         }  
  75.         private function onLoaded(content:DisplayObject):void  
  76.         {  
  77.             this.addChild(content);  
  78.             content.x = index*100;  
  79.             content.y = index*50;  
  80.             trace("onLoaded ",assests[index]);  
  81.         }  
  82.         private function onStreamComplete(event:Event):void  
  83.         {  
  84.             var urlstream:URLStream = event.currentTarget as URLStream;  
  85.             urlstream.removeEventListener(Event.COMPLETE,onStreamComplete);  
  86.             urlstream.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);  
  87.               
  88.             var byteArray:ByteArray = new ByteArray();  
  89.             urlstream.readBytes(byteArray);  
  90.             //转换成显示对象   
  91.             BitmapUtil.toDisplayObject(byteArray,onLoaded);  
  92.             //保存二进制数据到本地客户端   
  93.             cookie.setData(assests[index],byteArray);  
  94.             trace("cookie.setData",assests[index]);  
  95.         }  
  96.           
  97.         private function onIOError(event:IOErrorEvent):void  
  98.         {  
  99.             var urlstream:URLStream = event.currentTarget as URLStream;  
  100.             urlstream.removeEventListener(Event.COMPLETE,onStreamComplete);  
  101.             urlstream.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);  
  102.               
  103.         }  
  104.     }  
  105. }  

通过上面的三个类就可以运行起来,这里还需要准备两张资源:分别是mc_1.swf和img_1.png 确定放置到正确的路径下面,然后运行程序:这儿可以通过ShareObjectTest里面的index来改变究竟要加载那种类型的资源以供你测试,你可以看到当你第一次运行这个程序的时候,他的执行结果trace类似于下面:

 

 

  1. url img_1.png need load  
  2. cookie.setData img_1.png  
  3. onLoaded  img_1.png  


但是第二次以后再运行的时候,得到的trace结果是:

 

 

  1. url img_1.png already loaded  
  2. onLoaded  img_1.png  


可以看出来,第二次是使用的缓存到客户端的二进制数据了,从而我们想要的效果已经达到!

posted @ 2012-07-02 17:45  as爱好者  阅读(1000)  评论(2编辑  收藏  举报