代码改变世界

ActionScript 3.0 自写类整理笔记

2008-11-27 17:27  宝宝合凤凰  阅读(885)  评论(0)    收藏  举报
分包情况:
uploads/200803/31_174221_2.jpg


base包:基础包,用于存放初级应用类
bat包:应用包,用于存放高级应用类
com包:系统化包,用于存放系统化的高级应用模块类
exe包:框架包,用于存放框架方面的类
item包:项目包,用于项目上靠经验积累下的类
module包:组件包,用于存放组件的类

这段时间,我个人的情绪非常低落,为了摆脱这段时间的消极状态
因此开始整理在做项目中,碰到的种种问题,来整理出一套可用性高的类库
希望自己会坚持下去!
 
 
ActionScript 3.0 自写类整理笔记(二)——Dot类
今天刚刚写好,没做太多调试,望高手多多指正

flash效果:

拖拽物体1和物体2,就可以看到效果了

index.base.geom.Dot类讲解
基本功能:记录xy两点

构造函数
public function Dot(x_:Number = 0,y_:Number = 0,_isListen:Boolean = false)
前两个参数表示Dot的初始位置,第三个参数表示是否是一个功能性强的点
如果为false,当xy发生改变的时候,就不会发布事件,为true则会发布事件

bind 绑定显示对象方法
public function bind(_dis:DisplayObject,isInTime:Boolean = false):void
当Dot绑定到DisplayObject上之后,Dot的xy属性会随着_dis改变而改变
第一个参数为绑定的对象,第二个参数表示是否即时绑定
如果为false,Dot的xy属性不会随着_dis的改变而即时改变,但在获取Dot的xy属性,或者调用Dot的方法时,将会立即改变并且以_dis的xy属性为基准
如果为true,Dot的xy属性会随着_dis的改变而立即改变,如果isListen为true,还会即时发布xy改变的事件,那么等于可以侦听显示对象的xy属性,并且在改变后做出即时的反应

updata 刷新方法
public function updata():void
更新显示对象与Dot的xy属性

from 返回两点之间距离
public function from(_dot:Dot,isQuadrant:Boolean = false):Number
第一个参数表示,结束点,第二个参数表示,是否为真实距离
如果为false,返回的两点距离绝对是正数,指的是两点之间的绝对距离
如果为true,则返回相对坐标,那么是有可能的为负的!

angle 返回两点所形成的夹角
public function angle(_dot:Dot,isRadian:Boolean = false):Number
第一个参数表示,另外一个点,第二个参数表示,是否为弧度值
返回的角度是相对顺时间的真实角度值,具体的数值变化可以从上面的例子看出

quadrant 返回相对点所在的象限
public function quadrant(_dot:Dot,isMaster:Boolean = true):int
第一个参数表示另外一个点,第二个参数表示是否以该点为标准,具体请看示例
返回0,表示两点在同一条横着或者竖着的直线上
返回1,表示在第一象限,返回2表示第二象限………… 最高是第四象限。。
不知道象限是什么意思的,请看这 点击跳转"象限"的百度百科页面

clear 方法
public function clear():void
清空显示对象

length 属性(只读)
public function get length():Number
获取该点距0,0点的距离

x 属性
public function set x(num:Number):void
public function get x():Number
设置x属性,如果isListen为true,则会发布x改变的事件

y 属性
public function set y(num:Number):void
public function get y():Number
设置y属性,如果isListen为true,则会发布y改变的事件

isListener 属性
public var isListen:Boolean
指定设置isListen的值,是否为可侦听xy

举例:
上面的flash展示源代码
import index.base.geom.Dot;
import index.base.events.DotEvent;

var po1:Dot = new Dot(0,0,true);
var po2:Dot = new Dot(0,0,true);
po1.bind(p1,true);
po2.bind(p2,true);

po1.addEventListener(DotEvent.DOT_CHANGE,dotChangeFun);
po2.addEventListener(DotEvent.DOT_CHANGE,dotChangeFun);

function dotChangeFun(e:DotEvent):void{
  te.text = "物体1坐标:" + po1.x + "," + po1.y;
  te.appendText("\n物体2坐标:" + po2.x + "," + po2.y);
  te.appendText("\n两点之间距离:" + po1.from(po2));
  te.appendText("\n所形成的角度:" + po1.angle(po2));
  te.appendText("\n物体1所在象限:" + po1.quadrant(new Dot,false));
  te.appendText("\n物体2所在象限:" + po2.quadrant(new Dot,false));
  te.appendText("\n物体1对于物体2在象限:" + po2.quadrant(po1));
}

p1.addEventListener(MouseEvent.MOUSE_DOWN,p1MouseDownFun);
p2.addEventListener(MouseEvent.MOUSE_DOWN,p2MouseDownFun);

function p1MouseDownFun(e:MouseEvent):void{
  p1.startDrag();
  stage.addEventListener(MouseEvent.MOUSE_UP,p1MouseUpFun);
}

function p1MouseUpFun(e:MouseEvent):void{
  p1.stopDrag();
  stage.removeEventListener(MouseEvent.MOUSE_UP,p1MouseUpFun);
}

function p2MouseDownFun(e:MouseEvent):void{
  p2.startDrag();
  stage.addEventListener(MouseEvent.MOUSE_UP,p2MouseUpFun);
}

function p2MouseUpFun(e:MouseEvent):void{
  p2.stopDrag();
  stage.removeEventListener(MouseEvent.MOUSE_UP,p2MouseUpFun);
}

下面是类的源代码
package index.base.geom{
  
  import flash.events.EventDispatcher;
  import flash.display.DisplayObject;
  
  import index.base.events.DotEvent;
  
  public class Dot extends EventDispatcher{
    
    private var _x:Number;
    private var _y:Number;
    private var dis:DisplayObject;
    
    public var isListen:Boolean;
    
    public function Dot(x_:Number = 0,y_:Number = 0,_isListen:Boolean = false){
      _x = x_;
      _y = y_;
      isListen = _isListen;
    }
    
    //绑定DisplayObject
    public function bind(_dis:DisplayObject,isInTime:Boolean = false):void{
      dis = _dis;
      updata();
      if(isInTime) dis.addEventListener("enterFrame",enterFrameFun);
    }
    
    //帧频繁事件
    private function enterFrameFun(e:Object):void{
      if(_x != dis.x) x = dis.x;
      if(_y != dis.y) y = dis.y;
    }
    
    //更新xy数据
    public function updata():void{
      if(dis != null){
        _x = dis.x;
        _y = dis.y;
      }
    }
    
    //计算该点与另外一点的距离
    public function from(_dot:Dot,isQuadrant:Boolean = false):Number{
      updata();
      var num:Number = Math.sqrt(Math.pow(_dot.x - _x,2) + Math.pow(_dot.y - _y,2));
      if(!isQuadrant) num = Math.abs(num);
      return num;
    }
    
    //计算该点与另外一点所形成的线段与水平线的夹角,按顺时间计算
    public function angle(_dot:Dot,isRadian:Boolean = false):Number{
      updata();
      var numx:Number = _dot.x - _x;
      var numy:Number = _dot.y - _y;
      var num:Number = Math.atan(numy/numx);
      if(!isRadian) num = num * 180 / Math.PI;
      return num;
    }
    
    //返回当前点处在另外一点的哪个象限中 或 返回另外一点处在当前点的哪个象限中
    public function quadrant(_dot:Dot,isMaster:Boolean = true):int{
      updata();
      if(_x == _dot.x || _y == _dot.y){
        return 0;
      }
      
      var num:int;
      var p1:Boolean = (_x - _dot.x) > 0;
      var p2:Boolean = (_y - _dot.y) > 0;
      num = isMaster ? (p1 ? (p2 ? 2 : 3) : (p2 ? 1 : 4)) : (p1 ? (p2 ? 4 : 1) : (p2 ? 3 : 2));
      
      return num;
    }
    
    //返回该点距0点的距离
    public function get length():Number{
      updata();
      var num:Number = Math.sqrt(Math.pow(_x,2) + Math.pow(_y,2));
      return num;
    }
    
    //清除显示对象
    public function clear():void{
      dis = null;
    }
    
    //改变X坐标
    public function set x(num:Number):void{
      _x = num;
      if(dis != null) dis.x = num;
      if(isListen) dispatchEvent(new DotEvent(DotEvent.DOT_CHANGE,true));
    }
    
    //设置X坐标
    public function get x():Number{
      updata();
      return _x;
    }
    
    //改变Y坐标
    public function set y(num:Number):void{
      _y = num;
      if(dis != null) dis.y = num;
      if(isListen) dispatchEvent(new DotEvent(DotEvent.DOT_CHANGE,true));
    }
    
    //设置Y坐标
    public function get y():Number{
      updata();
      return _y;
    }
  }
}

事件类的代码:
package index.base.events{
  
  import flash.events.Event;
  
  public class DotEvent extends Event{
    
    public static const DOT_CHANGE:String = "dotChange";
    
    public function DotEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false){
      super(type,bubbles,cancelable);
    }
  }
}
[最后修改由 sunbright, 于 2008-06-26 20:57:24]
评论Feed 评论Feed: http://www.xiaos8.com/feed.asp?q=comment&id=87
怎么一页才显示这么点文章?点快速检索查看更多的文章: 显示全部 | 评论: 9 | 排序 | 观看的: 1328
游客*
[ 2008-05-14 19:26:20 ]
好东西,为什么你的类都自定义事件来发送消息呢?不知道这样写哪里比较好,还希望指教下.谢谢.
sunbright
[ 2008-05-14 19:45:27 ]
统一管理啊,而且发布的事件,类型自己定义,也方便不会起冲突,如果事件是要加属性的,也可以做为事件属性
比如MouseEvent就有很多事件属性啊。
游客*
[ 2008-05-16 07:13:01 ]
MouseDown的时候你才 添加mouseUp事件 mouseup的时候你又删除up侦听事件 这样做有什么作用?
如果一直写在那会有什么坏处?
游客*
[ 2008-05-16 07:25:05 ]
在改变 p1 坐标的时候 po1 x 和y同时改变 自定义事件 DotEvent.DOT_CHANGE 会执行两遍
有没有办法让他执行一遍?
sunbright
[ 2008-05-16 09:10:08 ]
第一个问题可能说不清额。。。你可以尝试你所说的去写,在做项目的时候,你会发现有时候根本不会触发MOUSE_UP事件,那是因为你拖动的东西,当拖到某一个东西的下面的时候,松开鼠标的事件不是你当前拖动的东西触发的,而是盖在他上面的显示对象发出的,所以你接收不到MOUSE_UP事件,如果你在一开头就写上stage的鼠标弹起事件,那么你在任何地方弹起都会触发这个事件,肯定会出问题的,而且也消耗了无谓的资源。
sunbright
[ 2008-05-16 09:12:20 ]
第二个问题,你可以去看这个类的升级版
http://www.xiaos8.com/article.asp?id=96
将DOT_CHANGE事件是拆开发送的,分别变成了X_CHANGE和Y_CHANGE两个事件
游客*
[ 2008-05-16 10:32:43 ]
非常感谢您的解答 [yes]
bug辉
[ 2008-08-22 14:47:18 ]
发现这个FLASH 有个BUG 就是把1和2 随便一个 拉到 最下面 也就是 Y轴为负的方向再次拖拉 就不能拖拉的动了
sunbright
[ 2008-08-22 15:38:20 ]
不懂你的意思
 
该类的主要功能是把swf,jpg,png,gif等文件以字节的形式加载进来
以便于使用Loader.loadBytes方法,重复加载使用素材
如果图片格式为jpg,并且是渐进式格式jpeg,那么该类还可以帮助你边加载边显示

index.base.net.byteLoader类讲解:
基本功能按字节加载图片,swf等

构造函数
public function ByteLoader(url:String = "")
如果传入了参数url,则立即执行加载!

load 加载方法
public function load(_url:String):void
开始加载,_url是加载的地址

updata 更新数据方法
public function updata():void
更新缓冲区的可读字节

close 关闭方法
public function close():void
类使用完毕,清除所有无用的数据,也可以用来强行关闭数据流,停止下载

data 属性
public var data:ByteArray
返回加载的字节

url 属性
public var url:String
返回加载的url

isLoad 属性(只读)
public function get isLoad():Boolean
返回是否有数据在加载

ProgressEvent.PROGRESS 事件
加载的过程中调度,并附带加载情况

Event.COMPLETE 事件
加载完毕调度

例子:
import index.base.net.ByteLoader;

var bl:ByteLoader = new ByteLoader;
bl.load("http://www.xiaos8.com/uploads/pro/50preso3a2.swf");
bl.addEventListener(Event.COMPLETE,completeFun);
bl.addEventListener(ProgressEvent.PROGRESS,progressFun);

function completeFun(e:Event):void{
  var loader:Loader = new Loader;
  loader.loadBytes(bl.data);
  addChild(loader);
  bl.removeEventListener(Event.COMPLETE,completeFun);
  bl.removeEventListener(ProgressEvent.PROGRESS,progressFun);
  bl.close();
  bl = null;
}

function progressFun(e:ProgressEvent):void{
  trace(e.bytesLoaded);
  //如果是渐进式格式的jpeg图片,那么在发布这个事件的时候读取字节,用Loader.loadBytes加载,就可以形成边加载边显示
}

源代码:
package index.base.net{
  
  import flash.events.EventDispatcher;
  import flash.events.ProgressEvent;
  import flash.events.Event;
  import flash.utils.ByteArray;
  import flash.net.URLStream;
  import flash.net.URLRequest;
  
  public class ByteLoader extends EventDispatcher{
    
    public var url:String;
    public var data:ByteArray;
    private var stream:URLStream;
    
    public function ByteLoader(url:String = ""){
      if(url != ""){
        load(url);
      }
    }
    
    //加载
    public function load(_url:String):void{
      url = _url;
      data = new ByteArray;
      stream = new URLStream;
      stream.load(new URLRequest(url));
      stream.addEventListener(Event.COMPLETE,completeFun);
      stream.addEventListener(ProgressEvent.PROGRESS,progressFun);
    }
    
    //加载中
    private function progressFun(e:ProgressEvent):void{
      if(stream.bytesAvailable == 0) return;
      updata();
      dispatchEvent(e);
    }
    
    //加载完成
    private function completeFun(e:Event):void{
      stream.removeEventListener(Event.COMPLETE,completeFun);
      stream.removeEventListener(ProgressEvent.PROGRESS,progressFun);
      updata();
      if(isLoad) stream.close();
      dispatchEvent(e);
    }
    
    //更新数据
    public function updata():void{
      if(isLoad) stream.readBytes(data,data.length);
    }
    
    //清除数据
    public function close():void{
      if(isLoad) stream.close();
      stream = null;
      data = null;
    }
    
    //获取是否有数据在加载
    public function get isLoad():Boolean{
      if(stream == null) return false;
      return stream.connected;
    }
  }
}
 
主要用途:
1、在用flash做项目的时候,把一些元件,通过设置链接类,然后使用这个类,通过getClass方法即可把这个素材拿下来
图片名称:图1(详见例1)
uploads/200804/02_230327_1.jpg

2、将许多许多的类分库到不同的swf中,然后通过调用swf,达到调用类库的功能,然后通过getClass来获取类(详见例2)

index.base.net.ClassLoader类讲解:
加载swf文件,并且通过调用getClass获取类,也可以获取命名空间或者函数的定义

构造函数
public function ClassLoader(obj:Object = null,lc:LoaderContext = null)
参数1可以是字符串,可以是ByteArray,如果为前者则采用load方法,后者采用loadBytes方法
参数2是创建带有指定 LoaderContext 对象的ClassLoader实例,LoaderContext 可以设置是否加载跨域文件,应用程序域等,详见官方LoaderContext类讲解!

load 方法
public function load(_url:String,lc:LoaderContext = null):void
加载文件
参数1是加载地址,参数2见构造函数

loadBytes 方法
public function loadBytes(bytes:ByteArray,lc:LoaderContext = null):void
加载字节文件
参数1是字节数据,参数2见构造函数

getClass 方法
public function getClass(className:String):Object
获取一个公共定义,可以是类,也可以是命名空间或者函数定义
参数1是获取class的完整包加类名,比如我们的这个类完整定义名称是 index.base.net.ClassLoader
详见例子

hasClass 方法
public function hasClass(className:String):Boolean
返回是否含有该公共定义
参数1见getClass方法

clear 方法
public function clear():void
清空

url 属性
public var url:String
获取url属性

loader 属性
public var loader:Loader
获取loader属性

/*********************************************/
例子1:
图片名称:图2
uploads/200804/02_232220_w.jpg

这是一个虚拟人物形象的动作包,其中包含了8种不同的动作
在使用ClassLoader加载这个swf的动作包后,即可使用getClass来调用这些素材,而且可以重复的new这些元件,来达到多次重复使用
import index.base.net.ClassLoader;

var cl:ClassLoader = new ClassLoader;
cl.load("main.swf");

cl.addEventListener(Event.COMPLETE,fun);

function fun(e:Event){
  var tmp = cl.getClass("drag");
  addChild(new tmp);  
}
/*********************************************/

例子2:
将设我有一个类库,有这么三个类
import index.base.net.ByteLoader;
import index.base.net.ClassLoader;
import index.base.geom.Dot;

var bl:ByteLoader;
var cl:ClassLoader;
var dot:Dot;
然后把它编译成swf

我们另外建一个文件,来加载这个所谓的类库
import index.base.net.ClassLoader;

var cl:ClassLoader = new ClassLoader;
cl.load("main.swf");

cl.addEventListener(Event.COMPLETE,fun);

function fun(e:Event){
  var tmp1 = cl.getClass("index.base.net.ByteLoader");
  trace(tmp1)
  
  var tmp2 = cl.getClass("index.base.net.ClassLoader");
  trace(tmp2)
  
  var tmp3 = cl.getClass("index.base.geom.Dot");
  trace(tmp3)
}

/**
 * trace的结果:
 * [class ByteLoader]
 * [class ClassLoader]
 * [class Dot]
 */
我们的目的就达到了!
/*********************************************/

接下来是源代码!
package index.base.net{
  
  import flash.display.Loader;
  import flash.net.URLRequest;
  import flash.utils.ByteArray;
  import flash.events.Event;
  import flash.events.ProgressEvent;
  import flash.events.EventDispatcher;
  import flash.system.LoaderContext;
  
  public class ClassLoader extends EventDispatcher{
    
    public var url:String;
    public var loader:Loader;
    
    //构造函数
    public function ClassLoader(obj:Object = null,lc:LoaderContext = null) {
      if(obj != null){
        if(obj is ByteArray){
          loadBytes(obj as ByteArray,lc);
        }else if(obj is String){
          load(obj as String,lc);
        }else{
          throw new Error("参数错误,构造函数第一参数只接受ByteArray或String");
        }
      }
    }
    
    //加载
    public function load(_url:String,lc:LoaderContext = null):void{
      url = _url;
      loader = new Loader;
      loader.load(new URLRequest(url),lc);
      addEvent();
    }
    
    //加载字节
    public function loadBytes(bytes:ByteArray,lc:LoaderContext = null):void{
      loader = new Loader;
      loader.loadBytes(bytes,lc);
      addEvent();
    }
    
    //开始侦听
    private function addEvent():void{
      loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressFun);
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeFun);
    }
    
    //结束侦听
    private function delEvent():void{
      loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,progressFun);
      loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,completeFun);
    }
    
    //加载成功,发布成功事件
    private function completeFun(e:Event):void {
      delEvent();
      dispatchEvent(e);
    }
    
    //加载过程
    private function progressFun(e:ProgressEvent):void{
      dispatchEvent(e);
    }
    
    //获取定义
    public function getClass(className:String):Object {
      return loader.contentLoaderInfo.applicationDomain.getDefinition(className);
    }
    
    //是否含有该定义
    public function hasClass(className:String):Boolean {
      return loader.contentLoaderInfo.applicationDomain.hasDefinition(className);
    }
    
    //清除
    public function clear():void{
      loader.unload();
      loader = null;
    }
  }
}
 
 
ActionScript 3.0 自写类整理笔记(五)——ImageLoader类(附加篇)
跟ClassLoader差不多,但是不同的是,他是读取图片的BitmapData,然后可以多次
new Bitamap(ImagesLoader.data)
进行图片调用

多次使用图片,直接用ByteLoader也可以,但是他加载进来的是字节,还要通过loadBytes
但是加载进来的,却是一张图片,无法重复使用
虽说要用就loadBytes一下,就是一张图片,但是实际起来还是比较麻烦
那么这个类,就是帮助你把这些步骤全部省下,直接把BitmapData拿出来
你只需要,用一个引用值接住他
var bd:BitmapData = ImageLoader.data;
然后每次使用这张图片的时候
new Bitamap(ImagesLoader.data)
就行了

该类的具体用法就不详讲了,前面加过的ClassLoader类,在这个类里面都有,而且两个类连代码都没改什么。。
就是少了getClass,hasClass,而多了data属性。相信应该不是很难看懂

示例:
import index.base.net.ImageLoader;

var il:ImageLoader = new ImageLoader;

il.load("http://www.xiaos8.com/uploads/200804/02_230327_1.jpg");

il.addEventListener(Event.COMPLETE,fun);

function fun(e:Event){
  addChild(new Bitmap(il.data));
  trace(il.loader)
  trace(il.url)
}

源代码:
package index.base.net{
  
  import flash.display.Loader;
  import flash.display.BitmapData;
  import flash.net.URLRequest;
  import flash.utils.ByteArray;
  import flash.events.Event;
  import flash.events.ProgressEvent;
  import flash.events.EventDispatcher;
  import flash.system.LoaderContext;
  
  public class ImageLoader extends EventDispatcher{
    
    public var url:String;
    public var loader:Loader;
    public var data:BitmapData;
    
    //构造函数
    public function ImageLoader(obj:Object = null,lc:LoaderContext = null) {
      if(obj != null){
        if(obj is ByteArray){
          loadBytes(obj as ByteArray,lc);
        }else if(obj is String){
          load(obj as String,lc);
        }else{
          throw new Error("参数错误,构造函数第一参数只接受ByteArray或String");
        }
      }
    }
    
    //加载
    public function load(_url:String,lc:LoaderContext = null):void{
      url = _url;
      loader = new Loader;
      loader.load(new URLRequest(url),lc);
      addEvent();
    }
    
    //加载字节
    public function loadBytes(bytes:ByteArray,lc:LoaderContext = null):void{
      loader = new Loader;
      loader.loadBytes(bytes,lc);
      addEvent();
    }
    
    //开始侦听
    private function addEvent():void{
      loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressFun);
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeFun);
    }
    
    //结束侦听
    private function delEvent():void{
      loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,progressFun);
      loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,completeFun);
    }
    
    //加载成功,发布成功事件
    private function completeFun(e:Event):void {
      data = loader.content["bitmapData"];
      delEvent();
      dispatchEvent(e);
    }
    
    //加载过程
    private function progressFun(e:ProgressEvent):void{
      dispatchEvent(e);
    }
    
    //清除
    public function clear():void{
      loader.unload();
      loader = null;
      data = null;
    }
  }
}
 
ActionScript 3.0 自写类整理笔记(六)——疑难杂症汇总
在做项目的时候,总会碰到很多,奇奇怪怪的问题,看了这篇文章相信会有些帮助,虽然不是很全面,但只要是我碰到过的问题,就分享给大家!但是也怕有些想不起了。。尽力额、、

==================== 气 死 你 的 分 割 线 ====================

1、数组的排序问题:Array.sort()方法
大家都经常用排序,一般都是字符串排序什么的,都不会发现什么的,现在来看一个有趣的现象
var a:Array = [7,3,32,64,96,13,42];
a.sort();
trace(a);
//输出:13,3,32,42,64,7,96
奇怪了,为什么排序出来的东西是个这样的。。
分析为什么:仔细看一下,会发现每个数字的第一个数字,的确是按排序放好的:1,3,3,4,6,7,9
为什么会这样呢?仔细来看看Array的官方文档
Array.sort()官方解释
默认情况下,Array。sort() 按以下方式进行排序:
1、排序区分大小写(Z 优先于 a)。
2、按升序排序(a 优先于 b)。
3、修改该数组以反映排序顺序;在排序后的数组中不按任何特定顺序连续放置具有相同排序字段的多个元素。
4、元素无论属于何种数据类型,都作为字符串进行排序,所以 100 在 99 之前,这是因为 "1" 的字符串值小于 "9" 的字符串值。
不难发现,第4条说明了,默认是以字符串进行排序,而不是以字符串排序,难怪会出现这样的结果额
那么应该如何排序才会出现我们要的答案呢?
var a:Array = [7,3,32,64,96,13,42];
a.sort(Array.NUMERIC);
trace(a);
//输出:3,7,13,32,42,64,96
加的这个参数是什么东西额。。仔细看看帮助文档吧。。
然后Array提供了几个常量分别是:
Array官方文档
CASEINSENSITIVE : uint = 1 [static] 指定 Array 类排序方法为不区分大小写的排序。
DESCENDING : uint = 2 [static] 指定 Array 类排序方法为降序排序。
NUMERIC : uint = 16 [static] 指定 Array 类排序方法为数值(而不是字符串)排序。
RETURNINDEXEDARRAY : uint = 8 [static] 指定排序返回的数组包含数组索引。
UNIQUESORT : uint = 4 [static] 指定 Array 类排序方法的唯一排序要求。
==================== 气 死 你 的 分 割 线 ====================

2、Loader.load加载图片,显示不出来
这个问题可以一笔带过额。。很多人都碰到过,其实是因为你没有加checkPolicyFile
如果确定图片跨域了,那么加载图片的时候,应该这样写
var loader:Loader = new Loader;
var request:URLRequest= new URLRequest(url);
var lc:LoaderContext = new LoaderContext(true);
loader.load(request, lc):
加的这个new LoaderContext(true),可以去参考官方帮助文档
这个构造函数可以传三个参数
第一参数:指定是否去加载跨域文件
第二参数:指定要使用的应用程序域
第三参数:指定要使用的安全沙箱

==================== 气 死 你 的 分 割 线 ====================

3、flash嵌入代码
经常出问题,比如打开窗口会被阻止,flash游戏做方向键的,屏幕会跟着动等类似问题
我也经常碰到这样的问题,花时间研究了一下
注意第一个,嵌入代码中有一个使flash透明的参数,不要把它设置成透明,那么很多问题都可以解决,不信的话,大家可以试试,还有很多不常用的属性,有些可以阻止flash某些方法的使用,很烦人的,特别是某些博客,公开平台等,传flash之后,他在嵌入代码中会加一些这样的属性,那么flash有很多事情都不能做
另外还有一个就是,如果是从flash中弹出新窗口,设置成不透明也会被阻止,但是在当前窗口打开,就不会
这是我在做项目的时候,碰到的问题,以及我的解决方法,如果有高人有更好的办法,一定要告诉我额。。。

==================== 气 死 你 的 分 割 线 ====================

4、mask遮罩层
mask这个属性相信很多人看过帮助文档之后,不会仔细去看,特别是熟悉AS2的setMask的人
当然包括我自己也放过这样的错误,因此在此提起,希望各位新手在学习的时候,把帮助文档看清楚
AS3帮助文档中DisplayObject类的mask属性
mask 属性
mask:DisplayObject [read-write]
语言版本 : ActionScript 3.0
Player 版本 : Flash Player 9
调用显示对象被指定的 mask 对象遮罩。 要确保当舞台缩放时蒙版仍然有效,mask 显示对象必须处于显示列表的活动部分。 但不绘制 mask 对象本身。 将 mask 设置为 null 可删除蒙版。
要能够缩放遮罩对象,它必须在显示列表中。 要能够拖动蒙版 Sprite 对象(通过调用其 startDrag() 方法),它必须在显示列表中。 要为基于 sprite 正在调度的 mouseDown 事件调用 startDrag() 方法,请将 sprite 的 buttonMode 属性设置为 true。
根据帮助文档的说法,如果要缩放遮罩层,就必须把遮罩层放在相应的显示列表中,也就是addChild(mask)
比如:我现在使用的是
stage.scaleMode = StageScaleMode.SHOW_ALL;
如果说你的遮罩层没有addChild那么,在缩放窗口的时候,mask是不会改变宽高;反之加入了显示列表,就会跟着窗口一起缩放
mask的拖拽和点击等事件也是如此!
综上所述:设置遮罩层最佳做法是放到显示列表,当然不排除有特别作用的

另外,你把mask的属性清空,本来被做为遮罩层的,就可以看的到了,否则是看不到遮罩层的

==================== 气 死 你 的 分 割 线 ====================

5、莫名其妙的mc
你使用Loader加载进来的mc,如果里面是动画,或者带有声音
你加载进来,就算你不addChild,他也在播放的,而且有时候你控制他stop,还控制不了。。
解决方案是:加stop(),做动画素材的时候,尽量把关键动画都做在主场景帧上,那么程序中就可以控制动画了
置于声音,还真是个头疼的东西,当然使用mc的同样管理方案也是可以的,但是我建议,把声音做到库中
然后使用ClassLoader把声音拿下来,然后用程序控制声音。

==================== 气 死 你 的 分 割 线 ====================

6、幽灵般的容器
一个容器,当被addChild后,你就可以直观的看得到他,但是你又removeChild,很多人都认为这样,容器就不存在了,实则不然,他还存在
比如你做一个飞机游戏,飞机爆炸后,你就会removeChild它,但是这样做是不够的,他依然还存在那个位置,而且x,y值是依然不变的
如果飞机上还写了碰撞检测,如果这时候有子弹飞过来,依然会算碰撞成功,还有很多类似的例子
个人建议:两个办法,简单的游戏嘛,可以设个全局逻辑值,当确定不需要在碰撞检测,把这个值变成false,每次检测碰撞,也检查一下这个值,就行了
第二个办法是复杂一点的,扩展容器类,侦听他的removedFromStage,removed事件和addedToStage,added事件,如果加入了,则容器中某个值等于true,反之是false
这个属性就可以叫 返回是否被加入显示对象
当然还有其他的办法,比如检查容器的contains方法,可以检查出当前容器中是否含有容器,如果removeChild,那么你检查结果就是不存在

==================== 气 死 你 的 分 割 线 ====================

oh。。先写这么多,肯定不是很完全。。一下子我也没办法把我在项目中碰到的任何问题搬出来。。想起来,我在继续写。。
 


index.base.func.OutDisplay类讲解:
当对象再一次触发某事件的时候,判断是否在事件范围内,如果不在则调度Event.CANCEL事件

构造函数
public function OutDisplay(_type:String,_dis:DisplayObject,...objs)
第一个参数:侦听类型
第二个参数:作用范围,一般来说都是用Stage作为范围,当然也有用在其他地方的
第三,四……个参数:可以拥有_type事件的对象
实例化后,侦听_dis的_type事件,每当触发_type事件,就开始判断事件目标是否存在objs中,或者objs中某项的子集显示对象,如果有则没有反应,如果没有则发出Event.CANCEL事件

add方法
public function add(...objs):Array
增加可以拥有_type事件的对象

objects属性(只读)
public function get objects():Array
返回可以拥有_type事件的对象列表

clear方法
public function clear(isDispatch:Boolean = false):void
清除类里面的侦听,以及引用
第一个参数:如果为true,那么调用clear之后会发出Event.CANCEL,反之没反应!默认为false

例子:
下面是展示flash的源代码,这只是一个简单应用,如果写复杂一点,也可以写出真正的快捷菜单
import index.base.func.OutDisplay;

var menu:Menu = new Menu;
menu.mc1.addEventListener(MouseEvent.MOUSE_OVER,mouseOverFun);
menu.mc2.addEventListener(MouseEvent.MOUSE_OVER,mouseOverFun);
menu.mc3.addEventListener(MouseEvent.MOUSE_OVER,mouseOverFun);
menu.mc4.addEventListener(MouseEvent.MOUSE_OVER,mouseOverFun);
addChild(menu);

function mouseOverFun(e:MouseEvent){
  var m:Menu = new Menu;
  m.x = e.currentTarget.x + e.currentTarget.parent.x;
  m.y = e.currentTarget.y + e.currentTarget.parent.y;
  addChild(m);
  
  var out:OutDisplay = new OutDisplay(MouseEvent.MOUSE_OVER,stage,e.currentTarget);
  out.addEventListener(Event.CANCEL,cancelFun);
  out.add(m);
  
  m = null;
  out = null;
}

function cancelFun(e:Event):void{
  var out:OutDisplay = e.currentTarget as OutDisplay;
  var tmpAr:Array = out.objects;
  removeChild(tmpAr[1]);
  out.removeEventListener(Event.CANCEL,cancelFun);
  
  tmpAr = null;
  out = null;
}

类的源代码:
package index.base.func{
  
  import flash.display.DisplayObject;
  import flash.display.DisplayObjectContainer;
  import flash.events.Event;
  import flash.events.EventDispatcher;
  
  public class OutDisplay extends EventDispatcher{
    
    //保存所有对象
    private var objAr:Array;
    //保存侦听类型
    private var type:String;
    //保存侦听范围
    private var dis:DisplayObject;
    
    //构造函数
    public function OutDisplay(_type:String,_dis:DisplayObject,...objs){
      type = _type;
      objAr = objs;
      dis = _dis;
      dis.addEventListener(_type,fun);
    }
    
    //事件处理
    private function fun(e:Event):void{
      for(var i:uint = 0;i<objAr.length;i++){
        if(e.target == objAr[i]) return;
        if(objAr[i] is DisplayObjectContainer){
          if(objAr[i].contains(e.target)) return;
        }
      }
      dis.removeEventListener(type,fun);
      dispatchEvent(new Event(Event.CANCEL));
    }
    
    //添加对象
    public function add(...objs):Array{
      for(var i:int = 0; i < objs.length; i ++){
        objAr.push(objs[i]);
      }
      return objects;
    }
    
    //获取对象列表
    public function get objects():Array{
      return objAr;
    }
    
    //卸载
    public function clear(isDispatch:Boolean = false):void{
      if(isDispatch) dispatchEvent(new Event(Event.CANCEL));
      dis.removeEventListener(type,fun);
      objAr = null;
    }
    
  }
}
ActionScript 3.0 自写类整理笔记(八)——Direction类和Dot类

关于该例子的教程请关注第九篇笔记!
因为即将出Direction类与Dot类的实战使用教程,因此本篇文章只对Direction类的方法属性讲解和Dot的更新部分讲解

首先是
index.base.game.Direction类
作用:控制飞机游戏,坦克游戏,或者一些和方向有关的方向按键操作

构造函数:
public function Direction(_area:InteractiveObject,isSole:Boolean = false,_up:uint = 38,_down:uint = 40,_left:uint = 37,_right:uint = 39)
参数一:方向键的作用区域,如果_area当前不是焦点,那么是侦听不到键盘事件的,一般这儿都是使用Stage做为作用区域
参数二:是否为单向事件触发,如果为false,那么按了什么键就是什么,可以同时触发上和左等两个或者两个以上的事件,反之以最后按的那个键为准
参数三,四,五,六:按键的键值,默认为38,40,37,39,分别是方向键的上下左右!

start方法:
public function start():void
开始捕获事件,当触发构造函数,将自动执行start方法

stop方法:
public function stop():void
停止捕获事件

setKey方法:
public function setKey(num:uint,vars:uint):void
设置按键键值
参数一:方向键标识,请参考该类的常量属性
参数二:按键键值

常量属性:
public static const UP:uint = 0;
public static const DOWN:uint = 1;
public static const LEFT:uint = 2;
public static const RIGHT:uint = 3;
分别代表:上下左右的方向键标识

clear方法:
public function clear():void
清除所有方向记录

area属性:
public var area:InteractiveObject
返回作用区域

sole属性:
public var sole:Boolean
返回是否单向操作

DirectionEvent.DO事件:
当有方向键是按下去的时候,则会发布事件,事件中含有up,down,left,right,4个属性,分别表示哪几个键是按下去的!

==================== 气 死 你 的 分 割 线 ====================

Dot类在前面的整理笔记中,曾经说过,这次是更新类的方法和属性
增加了旋转属性,并且可以计算当前方向的某距离后的点

以下只对更新的方法和属性进行讲解:其他的请看老的整理笔记:

go方法:
public function go(num:Number,isChange:Boolean = false):Dot
参数一,表示面向旋转方向前进多少的距离
参数二,表示是否也跟新该点基于num变化之后的点坐标

clear方法:
public function clear():void
清空绑定对象的引用

r 属性:
public function set r(num:Number):void
public function get r():Number
旋转属性的设置,如果isListener值为真,则改变旋转值会触发R_CHANGE的事件

Direction类源代码:
package index.base.game{
  
  import flash.events.EventDispatcher;
  import flash.events.KeyboardEvent;
  import flash.events.Event;
  import flash.display.InteractiveObject;
  
  import index.base.events.DirectionEvent;
  
  public class Direction extends EventDispatcher{
    
    //方向表示
    public static const UP:uint = 0;
    public static const DOWN:uint = 1;
    public static const LEFT:uint = 2;
    public static const RIGHT:uint = 3;
    
    //作用区域
    public var area:InteractiveObject;
    //是否单向
    public var sole:Boolean;
    
    //上下左右键值
    private const directionAr:Array = new Array(4);
    
    //是否上下左右
    private var _up:Boolean = false;
    private var _down:Boolean = false;
    private var _left:Boolean = false;
    private var _right:Boolean = false;
    
    public function Direction(_area:InteractiveObject,isSole:Boolean = false,_up:uint = 38,_down:uint = 40,_left:uint = 37,_right:uint = 39){
      area = _area;
      sole = isSole;
      directionAr[UP] = _up;
      directionAr[DOWN] = _down;
      directionAr[LEFT] = _left;
      directionAr[RIGHT] = _right;
      start();
    }
    
    //开始获取事件
    public function start():void{
      area.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
      area.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
      area.addEventListener(Event.ENTER_FRAME,onEnterFrame);
    }
    
    //事件帧频繁触发
    private function onEnterFrame(e:Event):void{
      var num:uint = Number(_up) + Number(_down) + Number(_left) + Number(_right);
      if(num == 0){
        return;
      }
      
      var eve:DirectionEvent = new DirectionEvent(DirectionEvent.DO);
      eve.up = _up;
      eve.down = _down;
      eve.left = _left;
      eve.right = _right;
      dispatchEvent(eve);
    }
    
    //停止获取事件
    public function stop():void{
      area.removeEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
      area.removeEventListener(KeyboardEvent.KEY_UP,onKeyUp);
      area.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
    }
    
    //鼠标按下去事件
    private function onKeyDown(e:KeyboardEvent):void{
      key(e.keyCode,true)
    }
    
    //鼠标弹上来事件
    private function onKeyUp(e:KeyboardEvent):void{
      key(e.keyCode,false)
    }
    
    //变化状态
    private function key(num:uint,isDown:Boolean):void{
      switch(num){
        case directionAr[UP]:
          if(sole) clear();
          _up = isDown;
        break;
        case directionAr[DOWN]:
          if(sole) clear();
          _down = isDown;
        break;
        case directionAr[LEFT]:
          if(sole) clear();
          _left = isDown;
        break;
        case directionAr[RIGHT]:
          if(sole) clear();
          _right = isDown;
        break;
      }
    }
    
    //设置按钮
    public function setKey(num:uint,vars:uint):void{
      directionAr[num] = vars;
    }
    
    //清空按键
    public function clear():void{
      _up = _down = _left = _right = false;
    }
  }
}

DirectionEvent类源代码:
package index.base.events{
  
  import flash.events.Event;
  
  public class DirectionEvent extends Event{
    
    public var up:Boolean;
    public var down:Boolean;
    public var left:Boolean;
    public var right:Boolean;
    
    public static const DO:String = "do";
    
    public function DirectionEvent(type:String){
      super(type);
    }
  }
}

Dot类源代码:
package index.base.geom{
  
  import flash.events.EventDispatcher;
  import flash.display.DisplayObject;
  
  import index.base.events.DotEvent;
  
  public class Dot extends EventDispatcher{
    
    private var _x:Number;
    private var _y:Number;
    private var _r:Number;
    private var dis:DisplayObject;
    
    public var isListen:Boolean;
    
    public function Dot(x_:Number = 0,y_:Number = 0,r_:Number = 0,_isListen:Boolean = false){
      _x = x_;
      _y = y_;
      _r = r_;
      isListen = _isListen;
    }
    
    //绑定DisplayObject
    public function bind(_dis:DisplayObject,isInTime:Boolean = false):void{
      dis = _dis;
      updata();
      if(isInTime) dis.addEventListener("enterFrame",enterFrameFun);
    }
    
    //帧频繁事件
    private function enterFrameFun(e:Object):void{
      if(_x != dis.x) x = dis.x;
      if(_y != dis.y) y = dis.y;
      if(_r != dis.rotation) r = dis.rotation;
    }
    
    //更新xy数据
    public function updata():void{
      if(dis != null){
        _x = dis.x;
        _y = dis.y;
        _r = dis.rotation;
      }
    }
    
    //计算该点向R方向前进某距离后的点
    public function go(num:Number,isChange:Boolean = false):Dot{
      updata();
      var yx:Number = Math.tan(_r * Math.PI / 180);
      var tmpx:Number = num / Math.sqrt(Math.pow(yx,2) + 1);
      var tmpy:Number = tmpx * yx;
      var n:int = Number(Math.abs(_r) <= 90) * 2 - 1;
      var dot:Dot = new Dot(_x + tmpx * n,_y + tmpy * n,_r);
      if(isChange){
        x = dot.x;
        y = dot.y;
      }
      return dot;
    }
    
    //计算该点与另外一点的距离
    public function from(_dot:Dot,isQuadrant:Boolean = false):Number{
      updata();
      var num:Number = Math.sqrt(Math.pow(_dot.x - _x,2) + Math.pow(_dot.y - _y,2));
      if(!isQuadrant) num = Math.abs(num);
      return num;
    }
    
    //计算该点与另外一点所形成的线段与水平线的夹角,按顺时间计算
    public function angle(_dot:Dot,isRadian:Boolean = false):Number{
      updata();
      var numx:Number = _dot.x - _x;
      var numy:Number = _dot.y - _y;
      var num:Number = Math.atan(numy/numx);
      if(!isRadian) num = num * 180 / Math.PI;
      return num;
    }
    
    //返回当前点处在另外一点的哪个象限中 或 返回另外一点处在当前点的哪个象限中
    public function quadrant(_dot:Dot,isMaster:Boolean = true):int{
      updata();
      if(_x == _dot.x || _y == _dot.y){
        return 0;
      }
      
      var num:int;
      var p1:Boolean = (_x - _dot.x) > 0;
      var p2:Boolean = (_y - _dot.y) > 0;
      num = isMaster ? (p1 ? (p2 ? 2 : 3) : (p2 ? 1 : 4)) : (p1 ? (p2 ? 4 : 1) : (p2 ? 3 : 2));
      
      return num;
    }
    
    //返回该点距0点的距离
    public function get length():Number{
      updata();
      var num:Number = Math.sqrt(Math.pow(_x,2) + Math.pow(_y,2));
      return num;
    }
    
    //清除显示对象
    public function clear():void{
      dis = null;
    }
    
    //改变旋转值
    public function set r(num:Number):void{
      _r = num;
      if(dis != null) dis.rotation = num;
      if(isListen) dispatchEvent(new DotEvent(DotEvent.R_CHANGE,true));
    }
    
    //改变旋转值
    public function get r():Number{
      updata();
      return _r;
    }
    
    //改变X坐标
    public function set x(num:Number):void{
      _x = num;
      if(dis != null) dis.x = num;
      if(isListen) dispatchEvent(new DotEvent(DotEvent.X_CHANGE,true));
    }
    
    //设置X坐标
    public function get x():Number{
      updata();
      return _x;
    }
    
    //改变Y坐标
    public function set y(num:Number):void{
      _y = num;
      if(dis != null) dis.y = num;
      if(isListen) dispatchEvent(new DotEvent(DotEvent.Y_CHANGE,true));
    }
    
    //设置Y坐标
    public function get y():Number{
      updata();
      return _y;
    }
  }
}

DotEvent类源代码:
package index.base.events{
  
  import flash.events.Event;
  
  public class DotEvent extends Event{
    
    public static const X_CHANGE:String = "xChange";
    public static const Y_CHANGE:String = "yChange";
    public static const R_CHANGE:String = "rChange";
    
    public function DotEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false){
      super(type,bubbles,cancelable);
    }
  }
}
[最后修改由 sunbright, 于 2008-06-25 20:22:44]
评论Feed 评论Feed: http://www.xiaos8.com/feed.asp?q=comment&id=96
怎么一页才显示这么点文章?点快速检索查看更多的文章: 显示全部 | 评论: 6 | 排序 | 观看的: 2017
看客*
[ 2008-08-04 23:34:29 ]
请问:var tmpx:Number = num / Math.sqrt(Math.pow(yx,2) + 1);
var tmpy:Number = tmpx * yx;
var n:int = Number(Math.abs(_r) <= 90) * 2 - 1;

这三句具体什么意思?~~~~~~
sunbright
[ 2008-08-05 00:06:35 ]
数学公式计算
过客*
[ 2008-08-05 11:03:46 ]
var tmpx:Number = num / Math.sqrt(Math.pow(yx,2) + 1);

为什么要计算tmpx=num/((yx的平方+1)开根号)?~~~请指教~~谢谢~~
sunbright
[ 2008-08-05 11:42:43 ]
通过简化式子得来的

具体是个什么式子简化而来,我也不记得了,反正这个结果是经过演算得到的
bug辉
[ 2008-08-21 14:39:46 ]
我对这一句
dispatchEvent(eve); 不是太懂 看了帮助
还是不理解其意思

能解释一下吗?
sunbright
[ 2008-08-21 14:55:34 ]
调度事件,让外面的类可以通过addEventListener侦听到该事件
这是AS3基本的事件模型,如果不太明白,建议先看看AS3事件模型