动力男孩flash乐园

不抛弃、不放弃,梦想要迂回去实现~!
  • 首页
  • 我的座右铭
  • 我的作品
  • 留言聊天室
  • 动力男孩的诞生

存档

‘actionscript3.0学习笔记’ 分类的存档
603次浏览↓

为asdoc设定example

2009年12月16日 powerboy 2 条评论

  最近在学习用asdoc生成文档,我们在使用官方API文档的时候,都能看到有些类的底部会有关于这个类是如何使用的例子,他是如何做到的呢,其实用的就是这个指令:@includeExample xxx/example.as,在它后面跟的是例子的路径,但是有一点,我们不能因为想要写个小例子,就把它放在跟类相同的路径下吧,这会非常糟糕的,我们更希望把例子集中在一个文件夹下统一管理,有什么好办法吗,答案是肯定的。我们需要在编译语句后面加上-examples-path [盘符]:\[路径],它指的就是我们存放例子的路径,但是一定要记住,存放example的路径最好跟类文件的路径是一样的,这样管理起来更方便。比如我把框架放在d盘名为powerboy的目录下,框架里有个cn.pboy.control.Button的类,它的路径看起来像这样:d:\powerboy\cn\pboy\control\Button.as,现在我要对这个类添加例子,我想把例子统一放在d盘的examples文件夹下统一管理,那么路径应该是这样的:d:\examples\cn\pboy\control\ButtonExample.as,然后在命令行工具下把当前盘符设为d:\powerboy>,通过以下命名就可以编译了:asdoc -source-path . -doc-sources . -examples-path d:\examples

分类: actionscript3.0学习笔记, flash教程 标签: as3, 教程
642次浏览↓

一个由单例模式引发的问题

2009年11月14日 powerboy 4 条评论

  最近我用一个单例模式类LoginNetManager对socket进行了封装,里面有一个send方法,专门用户向服务器发送事件,写法如下:

1
2
	LoginNetManager.getInstance().addEventListener(NetEvent.SOCKET_ERROR,onConnectError);	
	LoginNetManager.getInstance().send(NetEvent.LS_MSG_ADDCONNECT);

这个就是向服务器发送其中一个事件信息的语句,但奇怪的问题出现了,我在flashIDE本地进行测试的时候,一切正常,但是当我放到虚拟路径下测试的时候,它就会提示说“无法找到空对象引用的属性或方法”,我一看,问题就出在第二行那个send的方法,难道说类还没有完全实例化的时候,程序就继续向下运行了?但是这里也不存在异步执行啊,无奈之下,我修改成一个延迟语句:

1
2
	LoginNetManager.getInstance().addEventListener(NetEvent.SOCKET_ERROR,onConnectError);
	setTimeout(getSocket,500);

我在getSocket方法中调用那条语句,问题就都解决了。这确实很蹊跷,我承认flash在本地运行与在网页中运行的时候,执行的是不同的flash player程序,但是从这个例子来讲,不同flash player之间的差异性还是显而易见的。

分类: actionscript3.0学习笔记 标签: as3
406次浏览↓

一个简单的问题——怎样使代码优化的更好呢?

2009年7月28日 powerboy 没有评论

  今天在公司,一同事问了我一个问题,我想写一个方法,当接收到任意长度整型数值的时候,我如何只保留首位,其他位全部置为0呢。我思考了几秒钟:你可以先把整型参数用String强类型转换,看看字符串的长度,这样你就能根据长度得到首位的数字,后面再根据长度补零就行了。这时他问道,可不可以不通过字符串转换,直接用整型来处理呢?于是我们开始研究:
第一种做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function encoder(num:int):int{
	var sNum:int = num;
	var count:int = 0;
	while(true){
		count++;
		sNum /= 10;
		if (sNum < 10){
			sNum = Math.floor(sNum);
			break;
		}
	}
	return decoder(sNum,count);
}
 
function decoder(num:int,step:int):int{
	var _num:int = num;
	for (var i:int = 0;i<step;i++){
		_num *= 10;
	}
	return _num;
}

经过测试,这种做法是没有问题的,但是这是不是最好的方法呢,当然不是,因为Math.floor()的原因肯定会导致效率下降一部分,有办法替换么,其实很简单,直接用int()转换一下就行了。这样是最优做法么,当然还不是,看看下面这段代码:

第二种做法:

1
2
3
4
5
6
7
8
9
10
function encoder(num:int):int{
	var i:int=num;
	var j:int=1;
	while(i>10)
	{
		j*=10;
		i=num/j;
	}
	return i*j;
}

这段代码相信大家都能看懂,它的优化在哪呢?比之前少了一个循环,当然效率会大幅提升了。我们只需再添加一个变量作为被乘数,这样就减少了一个循环。这段代码基本已经是效率很高了,但其实如果你够细心的话,仍然可以再进行优化,就是这句:i=num/j;我们把它替换成i *= .1;为什么呢?因为在计算机内部,乘运算比除运算要快。让我们看一下测试结果吧:

1
2
3
4
5
6
7
8
9
(左边是乘运算,右边是除运算,单位:毫秒)
当循环100万次时:
1028  1070
1049  1065
1045  1063
1024  1074
当循环1000万次时:
10319  10784
10467  10625
分类: actionscript3.0学习笔记, 心情驿站 标签: as3
510次浏览↓

发现TextField一个bug

2008年12月27日 powerboy 没有评论

这个bug还是我无意中发现的,因为当时在测试官方帮助文档的一个关于parseCSS的例子,这段程序的目的是先加载外部css文件,然后单击场景中的文字,如果这时css文件加载完毕的话,会直接套用css样式。第一次单击的时候一切都是正常的,当我再次单击里面不同样式的文字时,他会把此文字的样式应用到其他文字上。起初我以为这时parseCSS的一个bug,后来当我利用绘图工具在场景中绘制一个文本框的时候再测试,就没有问题,这时我可以认定这绝对是TextField的bug。

分类: actionscript3.0学习笔记 标签: as3
491次浏览↓

addEventFrame一个说不清的问题

2008年12月18日 powerboy 1 条评论

关于MovieClip,官方有一个未公开的方法addEventFrame相信很多人都用过。在实际项目中,我也利用它解决了不少的问题,但是今天突然出现了一个怪现象,我在项目的某个环节设置了一段动画,动画mc里的第一帧已经加了stop(),在代码中加了很简单的两句话,

1
2
mc.play();
mc.addFrameScript(20,Run);

我的目的很简单,就是要在第21帧触发Run函数,但运行时发现影片始终停止在第一帧,似乎mc.play()并没有执行,然后我尝试注释掉了mc.addFrameScript(20,Run)这一句,再测试,发现影片play了,这就很奇怪。我把代码反复查了几遍都没发现问题,而且我新建一个fla测试这段代码,一切正常,有点不可理喻。后来我突然想到了一点,addFrameScript可以对多帧设置function,于是我抱着试试看的心态,把上面两句合并成了mc.addFrameScript(0,init,20,Run);在init函数中放了mc.play();然后测试,发现一切恢复正常了。解决方法是找到了,但是为什么之前的方法就失效了呢,至今我还没有找到答案。

分类: actionscript3.0学习笔记 标签: as3
606次浏览↓

在ActionScript 3和Flash Player 10中使用Vectors

2008年12月7日 powerboy 没有评论

最近想看看flashplayer10新增的Vector类到底是个什么东西,在百度搜到了千篇一律的文章之后,决定打开google搜索国外文章。下面这篇文章是我在Mike Chambers中找到的,在此翻译过来分享给大家。如要转载,请注明出处www.p-boy.cn,谢谢。

One of the new ActionScript features included in the Flash Player 10 Public Beta is the inclusion of a Vector class. Essentially, the Vector class is a typed Array, and in addition to ensuring your collection is type safe, can also provide (sometimes significant) performance improvements over using an Array.

一个ActionScript的新特性是在Flash Player 10 Public Beta中包含了Vector类。基本上,这个Vector类的数据类型是数组,除了确保你收集的是安全类型之外,还提供了优于数组的性能提升(有时是很明显的)。

Using the Vector class is pretty simple, and very similar to using an Array. In fact, the Vector class contains all of the same methods as the Array class. The main difference is how you instantiate it.

使用Vector非常的简单,和使用数组非常相似。事实上,Vector类包含了数组里所有的方法。主要的不同之处在于你怎样去实例化它。

For example, here is how you instantiate an Array:

例如,这里告诉你如何实例化一个数组:

1
2
3
var a:Array = new Array();
//or
var b:Array = [];

Here is an example of instantiating a Vector that contains int types:

这里是一个包含有int类型的Vector实例化的例子:

1
2
//var VARIABLENAME:Vector.<vectortype> = new Vector.<vectortype>();
var vector:Vector.<int> = new Vector.<int>();

Just as in an Array, you can initialize the Vector length to a specific size, by passing the length into the constructor:

就像数组一样,你可以对Vector的具体大小来实例化它的长度。通过长度来构造:

1
2
var size:int = 7;
var vector:Vector.<int> = new Vector.<int>(size);

However, the Vector has an additional constructor argument, which is a Boolean value that specifies whether the Vector size is fixed (true) or can be changed (false). The default value is false, and the property can be changed with the fixed property:

然而,Vector还有一个额外的变量,一个可以具体控制Vector长度是否可以改变的布尔值。默认是flash,这一特性可以由fixed属性去改变它。

1
2
3
4
var size:int = 7;
var fixed:Boolean = true
var vector:Vector.<int> = new Vector.<int>(size, fixed);
vector.fixed = !fixed;

Keep in mind, that if fixed is set to true, then you cannot call any Vector methods that change the length, such as pop(), push(), shift(), etc…

谨记,一旦fixed属性被设置为true,你就不能用Vector的其他方法来改变它的长度,比如pop(), push(), shift()等等。

Vectors are also type safe, so while with an Array you can store multiple types:

Vectors也是安全类型,而数组可以存储多种数据类型:

1
2
3
4
5
6
7
8
9
var s:String = "I am a string";
var d:Date = new Date();
var n:Number = 1138
var a:Array = new Array();
a[0] = s;
a[1] = d;
a[2] = n;
 
trace(a[1] is Date); //true

You will get a compile time TypeError with a Vector:

在编译Vector时你会得到TypeError错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
var s:String = "I am a string";
var d:Date = new Date();
var n:Number = 1138
var v:Vector.<string> = new Vector.<string>;
v[0] = s;
v[1] = d;
v[2] = n;
 
trace(v[1] is Date); //false
 
//Compile time errors:
//Implicit coercion of a value of type Date to an unrelated type String.
//Implicit coercion of a value of type Number to an unrelated type String.

Other than that, working with a Vector is pretty much the same as working with an Array. The APIs are the same, and you can access items directly via their index.

除了Vector运行起来和Array一样漂亮之外,APIs也是相同的,并且你能够通过索引直接访问它们的项目。

1
2
3
4
5
6
7
8
9
10
var vector:Vector.<int> = new Vector.<int>();
 
var rand:Number;
for(var i:int = 0; i < 1000000; i++)
{
	rand = (Math.floor(Math.random() * 1000000) as int);
	vector.push(rand);
}
 
trace(vector[7]);

One last thing to keep in mind is that a Vector is basically a dense array. This means that all items in the Vector must have either a value or null.

最后一点需要注意的是Vector是一个密集型数组,这意味着里面所有的项目必须存在值或者null。

For example, with an Array, you can do this:

例如,利用Array,你可以这样做:

1
2
3
var a:Array = new Array();
a[0] = "foo";
a[6] = "bar";

But if you try that with a Vector:

但是如果你尝试用Vector做同样的操作的话:

1
2
3
var v:Vector.<string> = new Vector.<string>();
v[0] = "foo";
v[6] = "bar";

You will get a RangeError at runtime.

在运行时你会得到RangeError。

The fix is to initialize the Vector length:

实例化固定长度的Vector:

1
2
3
var v:Vector.<string> = new Vector.<string>(7);
v[0] = "foo";
v[6] = "bar";

Below is an example that shows a difference in performance in looping over a million numbers in a collection. Keep in mind that this is one specific test, and depending on your use case, performance improvements may be greater or smaller.

下面这个例子展示了运行超过一百万次循环的不同之处。记住这只是一个特殊的测试,这取决于你所使用的机器,结果可能会偏大或者偏小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package
{
	import flash.display.Sprite;
 
	public class VectorTest extends Sprite
	{
		private static const NUM_LOOPS:int = 5;
		public function VectorTest()
		{
 
			var vector:Vector.<int> = new Vector.<int>();
			var array:Array = new Array();
 
			//populate data
			var rand:Number;
			for(var i:int = 0; i < 1000000; i++)
			{
				rand = (Math.floor(Math.random() * 1000000) as int);
				vector.push(rand);
				array.push(rand);
			}
 
			var sTime:Number = getMilliseconds();
			loopArray(array);
			trace("Loop Array Avg (5) : " + ((getMilliseconds() - sTime)/NUM_LOOPS));
 
			sTime = getMilliseconds();
			loopVector(vector);
			trace("Loop Vector Avg (5) : " + ((getMilliseconds() - sTime)/NUM_LOOPS));
 
		}
 
		private function getMilliseconds():Number
		{
			return (new Date()).getTime();
		}
 
		private function loopArray(a:Array):void
		{
			var len:Number = a.length;
 
			var n:int;
			for(var i:int = 0; i < NUM_LOOPS; i++)
			{
				for(var k:int = 0; k < len; k++)
				{
					n = a[k];
				}
			}
		}
 
		private function loopVector(v:Vector.<int>):void
		{
			var len:Number = v.length;
 
			var n:int;
			for(var i:int = 0; i < NUM_LOOPS; i++)
			{
				for(var k:int = 0; k < len; k++)
				{
					n = v[k];
				}
			}
		}
	}
}

On my machine, I get this output:

哦,我在自己的机器上得到了以下输出结果:

1
2
Loop Array Avg (5) : 115.8
Loop Vector Avg (5) : 108.8

(译者注:在我的机器上输出的是
Loop Array Avg (5) : 26.6
Loop Vector Avg (5) : 18.2
看来我的机器比他的快很多,哈哈)

分类: actionscript3.0学习笔记, 我翻译的英文资料 标签: as3, 新闻, 翻译
1,511次浏览↓

又发现个Sprite和MovieClip之间的区别

2008年10月8日 powerboy 2 条评论

我们在刚开始学习as3的时候,尤其是对于一个从as2转型到as3的人来说,可能最先遇到的一个问题就是,sprite是个什么东西呢?原来你会发现,原来sprite就是一个轻量型的clip,它没有时间轴的概念,在开发项目的时候,如果用不到时间轴的话,我们尽量用Sprite而不用MovieClip,可以提高程序的执行效率。但是今天我又有了一个新发现,不说了,先卖个关子,嘿嘿!先给大家讲讲我是怎么遇到问题的。

在有些程序中,我们需要动态生成一个列表,列表中的每一个项(Item)包含有若干种属性,当点击某个项的时候,我们需要将这些属性推送出去。最初我就是用Sprite生成了一个列表,但是加属性的时候提示无法访问未定义属性。如下:

  1. var ball:Sprite = new Sprite();
  2. ball.act = 1;
  3. addChild(ball);
  4. trace(ball.act);//这里就会报错

在用as2开发项目的时候,这种情况是不会出现的,这里当时憋了我好一阵子,后来想了想,只能先建一个子类继承Sprite,然后在子类中添加属性,这样在建立影片的时候,直接生成这个子类的实例。这个过程很简单,但是毕竟多了一个步骤,感觉很不爽。有一次我在场景中绘制了一个图形,直接添加了属性,居然能够正常输出,开始以为是继承了我的那个子类的缘故,检查了一遍发现不是。我突然心声一念,场景中的图形不就是MovieClip么,那我在程序中生成一个MovieClip的话,理论上应该也是没问题的(之前一直没有注意过这个问题),于是我赶紧测试,验证一下想法,果然不出所料。以后在做项目的时候,什么时候该用Sprite,心里就更有数了,有效的运用他们的特性可以事半功倍的。

本文结束。

分类: actionscript3.0学习笔记 标签: as3
531次浏览↓

8、生成和处理事件机制

2008年9月3日 powerboy 没有评论

在以往的as2当中,基本上只有组件能够发送事件,平时的程序中基本上都是这种类似

  1. xxx.onLoad=function(){}

的回调函数形式,甚至利用onEnterFrame来模拟不断侦听的效果,而as3中提供的解决方案是DOM3事件处理机制,它包括注册侦听器、发送事件、侦听事件、移除侦听器4个步骤。

这是一个小例子:

下面我根据自己的思路来分析一下这个过程。当我们建立一个对象且让他具有发送事件的能力,就必须让他继承EventDispatcher类。下面的这个Teacher类,有一个teach方法,它会产生一个TeachEvent事件并且利用dispatchEvent将其推送出去。

下载: Teacher.as
  1. //事件发送者类
  2. package {
  3. import flash.events.EventDispatcher;
  4. public class Teacher extends EventDispatcher {
  5.  
  6. public var name:String;
  7.  
  8. public function Teacher(nm:String) {
  9. name = nm;
  10. }
  11.  
  12. public function teach(txt:Object,value:String):void{
  13. var teachevent:TeachEvent = new TeachEvent();
  14. teachevent.lesson = value;
  15. txt.text = teachevent;
  16. dispatchEvent(teachevent);
  17. }
  18. }
  19. }

那么这个TeachEvent到底是什么呢?其实就是我们自定义的一个事件类,首先这个类要继承Event事件类,Event的构造函数是这样的:Event(type:String, bubbles:Boolean = false, cancelable:Boolean = false) ;再利用public static const建立一个事件类型,因此我们在TeachEvent的构造函数中需要加上这句:super(TEACH_LESSON);他就意味着将事件类型TEACH_LESSON传递给父类Event的构造函数。

然后需要重写toString和clone这两个方法,在重写toString方法的时候需要用到formatToString,对于formatToString官方的解释是:在自定义 Event 类中实现 toString() 方法的实用程序函数。其实说白了将toString的返回结果按自定义的格式覆盖了一遍。之后在重写clone方法时需要注意的一点是为了和实例状态保持一致,不要忘了将自定义的方法写进去。

下载: TeachEvent.as
  1. package {
  2. import flash.events.Event;
  3. public class TeachEvent extends Event {
  4.  
  5. public static const TEACH_LESSON:String = "讲课";
  6. private var _lesson:String;
  7.  
  8. public function TeachEvent() {
  9. super(TEACH_LESSON);
  10. }
  11.  
  12. public function set lesson(ls:String):void{
  13. _lesson = ls;
  14. }
  15.  
  16. public function get lesson():String{
  17. return _lesson;
  18. }
  19.  
  20. override public function toString():String{
  21. return formatToString("TeachEvent","type","bubbles","cancelable","eventPhase","lesson");
  22. }
  23.  
  24. override public function clone():Event{
  25. var teachEvent:TeachEvent = new TeachEvent();
  26. teachEvent._lesson = _lesson;
  27. return teachEvent;
  28. }
  29. }
  30. }

这里我建了一个Student类,比较简单,在侦听方法listenTeacher里面为什么接受的参数是(e:TeachEvent,…arg)后面会讲到。

下载: Student.as
  1. package {
  2. import flash.display.Sprite;
  3. public class Student extends Sprite{
  4. public function Student(){}
  5. public function listenTeacher(e:TeachEvent,...arg):void {
  6. arg[0].text = e.target.name+"今天讲了"+arg[1];
  7. }
  8. }
  9. }

下面这个是文档类,首先分别建立了Teacher和Student实例,并且注册侦听器让学生来听老师讲课。当我们在输入文本框填入讲课的内容后点击“讲课”按钮,便执行teach方法将讲课内容推送出去。

下载: EventExample.as
  1. package {
  2. import flash.text.TextField;
  3. import flash.display.Sprite;
  4. import flash.display.MovieClip;
  5. import flash.events.MouseEvent;
  6. import flash.events.Event;
  7. public class EventExample extends Sprite {
  8.  
  9. private var teacher:Teacher;
  10. private var student:Student;
  11. var Handler:Function;
  12. public function EventExample() {
  13. teacher = new Teacher("老师");
  14. student = new Student();
  15.  
  16. //学生在老师那里注册了“讲课”事件的侦听,执行了listenTeacher
  17. Handler = JEventDelegate.create(student.listenTeacher,txt3,txt1.text);
  18. teacher.addEventListener(TeachEvent.TEACH_LESSON,Handler);
  19.  
  20. txt1.addEventListener(Event.CHANGE,changeHandler);
  21. teachBtn.buttonMode = true;
  22. teachBtn.addEventListener(MouseEvent.CLICK,click);
  23. }
  24. private function changeHandler(e:Event){
  25. Handler = JEventDelegate.create(student.listenTeacher,txt3,txt1.text);
  26. }
  27. private function click(e:MouseEvent):void{
  28. teacher.removeEventListener(TeachEvent.TEACH_LESSON,Handler);
  29. teacher.addEventListener(TeachEvent.TEACH_LESSON,Handler);
  30. teacher.teach(txt2,txt1.text);
  31. }
  32. }
  33. }

ok,大致思路就是这样,这里我要捎带的提一下JEventDelegate类,是一个网友写的,这里我借用一下。它的主要作用就是为了解决给侦听器传参的问题,这就是为什么我前面的侦听器函数要写成Handler = JEventDelegate.create(student.listenTeacher,txt3,txt1.text);这种形式的原因,student.listenTeacher是我们自定义的侦听器函数,后面两个是需要传入的参数。因此在Student类的侦听方法里面需要写成listenTeacher(e:TeachEvent,…arg)。…arg是一个对象,把传入的参数都按顺序保存进来了,我们只要像访问数组一样访问它就可以了。

下载: JEventDelegate.as
  1. package {
  2. public class JEventDelegate {
  3. public function JEventDelegate() {
  4. }
  5. public static function create(f:Function,...arg):Function {
  6. var F:Boolean=false;
  7. var _f:Function=function(e:*,..._arg){
  8.    _arg=arg
  9. if(!F){
  10. F=true
  11. _arg.unshift(e)
  12. }
  13. f.apply(null,_arg)
  14.   };
  15. return _f;
  16. }
  17. public static function toString():String {
  18. return "Class JEventDelegate";
  19. }
  20. }
  21. }

以上就是我的个人心得,如果有理解不当的地方,欢迎各位visiters批评指正。

下载源文件:EventExample.rar

分类: actionscript3.0学习笔记 标签: as2, as3
594次浏览↓

7、事件流机制的3个阶段

2008年9月2日 powerboy 5 条评论

根据个人的学习体会,我做了大致以下总结。事件流机制主要分为3个阶段:捕获阶段、目标阶段、冒泡阶段。

1、捕获阶段:当发出一个事件对象以后,flash player会从根容器也就是舞台开始,逐层向下寻找,直到找到最内层的目标对象(target)为止。因此从舞台目标对象一直到目标对象的所有父容器都属于捕获阶段。

2、目标阶段:当找到最内层目标对象的时候,就属于目标阶段。

3、冒泡阶段:从最内层目标对象开始,逐层向上寻找直到找到舞台根容器为止,这个过程就是冒泡阶段。

注意:两个和事件目标相关的属性(target:最内层显示对象,currentTarget:当前侦听事件的容器)

下面是我个人做的小例子:

下载: Bubble.as
  1. /**
  2.  * 作者:powerboy[动力男孩]  http://www.p-boy.cn
  3.  * 日期: [08.9.2]
  4.  * 备注:事件流机制的3个阶段
  5.  */
  6. package {
  7. import flash.display.Sprite;
  8. import flash.display.DisplayObject;
  9. import flash.display.DisplayObjectContainer;
  10. import flash.text.TextField;
  11. import flash.text.TextFieldAutoSize;
  12. import flash.events.MouseEvent;
  13. public class Bubble extends Sprite {
  14.  
  15. private var txt:TextField;
  16.  
  17. public function Bubble() {
  18. txt = new TextField();
  19. txt.multiline = true;
  20. txt.border = true;
  21. txt.width = 500;
  22. txt.height = 150;
  23. txt.x = 20;
  24. txt.y = 200;
  25. addChild(txt);
  26.  
  27. var roundRect:RoundRect=new RoundRect();
  28. roundRect.name = "roundRect";
  29. roundRect.fill(0x000000);
  30.  
  31. var ellipse:Ellipse=new Ellipse();
  32. ellipse.name = "ellipse";
  33. ellipse.fill(0x00ff00);
  34. ellipse.move(20,20);
  35.  
  36. var circle:Circle=new Circle();
  37. circle.name = "circle";
  38. circle.fill(0x0000ff);
  39. circle.move(100,80);
  40.  
  41. addChild(roundRect);
  42. roundRect.addChild(ellipse);
  43. ellipse.addChild(circle);
  44.  
  45. roundRect.addEventListener(MouseEvent.MOUSE_OVER,roundRectRollOverHandler,true);
  46. ellipse.addEventListener(MouseEvent.MOUSE_OVER,ellipseRollOverHandler,true);
  47. circle.addEventListener(MouseEvent.MOUSE_OVER,circleRollOverHandler,true);
  48.  
  49. roundRect.addEventListener(MouseEvent.MOUSE_OVER,roundRectRollOverHandler);
  50. ellipse.addEventListener(MouseEvent.MOUSE_OVER,ellipseRollOverHandler);
  51. circle.addEventListener(MouseEvent.MOUSE_OVER,circleRollOverHandler);
  52. }
  53.  
  54. private function roundRectRollOverHandler(e:MouseEvent):void {
  55. handleStage(e.target.name,e.currentTarget.name,e.eventPhase);
  56. }
  57. private function ellipseRollOverHandler(e:MouseEvent):void {
  58. handleStage(e.target.name,e.currentTarget.name,e.eventPhase);
  59. }
  60. private function circleRollOverHandler(e:MouseEvent):void {
  61. handleStage(e.target.name,e.currentTarget.name,e.eventPhase);
  62. }
  63. private function handleStage(target:String,currentTarget:String,eventPhase:Number):void{
  64. var str:String;
  65. switch(eventPhase){
  66. case 1:
  67. str = "捕获阶段 ↓";
  68. break;
  69. case 2:
  70. str = "目标阶段 →";
  71. break;
  72. case 3:
  73. str = "冒泡阶段 ↑";
  74. break;
  75. }
  76. txt.appendText("最内层显示对象:"+target+"  当前侦听事件的容器:"+currentTarget+"  事件流机制:"+str+"\n");
  77. txt.scrollV = txt.maxScrollV;
  78. }
  79. }
  80. }
  81.  
  82. import flash.display.Sprite;
  83. import flash.events.MouseEvent;
  84. import flash.display.DisplayObjectContainer;
  85. class MyShape extends Sprite {
  86.  
  87. public function MyShape() {
  88.  
  89. }
  90. protected function drawing():void {
  91. }
  92.  
  93. public function fill(color:uint):void {
  94. this.graphics.beginFill(color);
  95. drawing();
  96. this.graphics.endFill();
  97. }
  98. public function move(x:int,y:int):void {
  99. this.x = x;
  100. this.y = y;
  101. }
  102. }
  103. //圆角矩形
  104. class RoundRect extends MyShape {
  105. public function RoundRect() {
  106. super();
  107. }
  108. override protected function drawing():void {
  109. this.graphics.drawRoundRect(0,0,200,50,10,10);
  110. }
  111. }
  112. //椭圆形
  113. class Ellipse extends MyShape {
  114. public function Ellipse() {
  115. super();
  116. }
  117. override protected function drawing():void {
  118. this.graphics.drawEllipse(0,0,200,50);
  119. }
  120. }
  121. //圆形
  122. class Circle extends MyShape {
  123. public function Circle() {
  124. super();
  125. }
  126. override protected function drawing():void {
  127. this.graphics.drawCircle(0,0,50);
  128. }
  129. }

源文件下载:Bubble.rar

分类: actionscript3.0学习笔记 标签: as3
718次浏览↓

6、as3类的向上转换和向下转换

2008年9月1日 powerboy 2 条评论

这里浅谈一下我个人的学习体会。之前一直在用as2做项目,很少用到继承(extends)。通过最近一段时间的研究,明白了继承复用所带来的优点,下面讲到的只是其中一个方面,其他方面还需要不断的体会和研究,下面给大家分享一下我的心得。

向上转换:一个对象既看成属于自身的数据类型,又可以看成属于自己所有父类的类型。如果把一个对象当成它的父类来使用,就被称作向上转换。

向下转换:并不是把父类当作子类来使用,而是当把一个子类对象传递给一个父类数据类型使用时,可以将它再还原成子类对象,就被称作向下转换。

下面是一个小例子:

首先建立一个Human(人)类,其中human是将要添加到场景中的对象,由于这是一个抽象类,我们需要有子类来继承它,所以把human的访问控制符定义为protected。之后在构造函数中根据子类传来的显示容器将其实例化,drawing方法留空,用来让子类重写,因为不同的子类drawing方法是不同的。我们把所有子类所共同具有的fill(填充颜色)、move(显示位置)方法放到Human类中。

下载: Human.as
  1. package
  2. {
  3. import flash.display.Shape;
  4. import flash.display.DisplayObjectContainer;
  5. public class Human
  6. {
  7. protected var human:Shape;
  8.  
  9. public function Human(parent:DisplayObjectContainer) {
  10. human = new Shape();
  11. parent.addChild(human);
  12. }
  13.  
  14. protected function drawing():void{}
  15.  
  16. public function fill(color:uint):void{
  17. human.graphics.beginFill(color,0.5);
  18. drawing();
  19. human.graphics.endFill();
  20. }
  21.  
  22. public function move(x:Number,y:Number):void{
  23. human.x = x;
  24. human.y = y;
  25. }
  26. }
  27. }

下面建立一个WhiteHuman(白人)类,让它来继承父类Human,在构造函数中加入super意味着当执行子类构造函数的时候,自动调用其父类的构造函数,之后我们在子类中重写(override)drawing方法。

下载: WhiteHuman.as
  1. package
  2. {
  3. import flash.display.Shape;
  4. import flash.display.DisplayObjectContainer;
  5. public class WhiteHuman extends Human
  6. {
  7. public function WhiteHuman(parent:DisplayObjectContainer) {
  8. super(parent);
  9. }
  10.  
  11. override protected function drawing():void{
  12. human.graphics.drawCircle(0,0,10);
  13. }
  14. }
  15. }

再定义一个BlackHuman(黑人)类,道理同上。

下载: BlackHuman.as
  1. package
  2. {
  3. import flash.display.Shape;
  4. import flash.display.DisplayObjectContainer;
  5. public class BlackHuman extends Human
  6. {
  7.  
  8. public function BlackHuman(parent:DisplayObjectContainer) {
  9. super(parent);
  10. }
  11.  
  12. override protected function drawing():void{
  13. human.graphics.drawCircle(0,0,30);
  14. }
  15. }
  16. }

下面这段代码大致的思想就是,先随机建立10个人类,当随机数大于0.5,就建立白人对象,反之建立黑人对象,并将这些对象放入一个数组中。然后将其一个个弹出并逐个分析,每次的弹出的结果会保存到someBody中,它的数据类型是Human。后面对someBody进行判断,根据向下转换原则,数据类型跟哪个子类吻合,就作为这个子类并进入相应的处理方法中使用,这里处理WhiteHuman的是hand1方法,处理BlackHuman的是hand2方法。同时为了对比向上转换的使用方法,我在每次弹出数组元素的时候,建立了WhiteHuman的实例BH,并用hand3方法来处理它,但是和之前两个方法不同的是,hand3只接受传来的Human类型。

下载: People.as
  1. package {
  2. import flash.display.Sprite;
  3. public class People extends Sprite {
  4. private var _array:Array = new Array();
  5. public function People() {
  6. createShape();
  7. var num = _array.length;
  8. for (var i=0; i<num; i++) {
  9. var someBody:Human = popShape();
  10. var WH:WhiteHuman= new WhiteHuman(this);
  11. //向下转换
  12. if (someBody is WhiteHuman){
  13. hand1(someBody as WhiteHuman);
  14. }
  15. if (someBody is BlackHuman){
  16. hand2(someBody as BlackHuman);
  17. }
  18. //向上转换
  19. hand3(WH as Human);
  20. }
  21. }
  22. private function createShape():void {
  23. for (var i = 0; i<10; i++) {
  24. if (Math.random()>0.5) {
  25. addShape(new WhiteHuman(this));
  26. } else {
  27. addShape(new BlackHuman(this));
  28. }
  29. }
  30. }
  31. private function addShape(target:Human):void {
  32. _array.push(target);
  33. }
  34. private function popShape():Human {
  35. return _array.pop();
  36. }
  37. private function hand1(target:WhiteHuman):void {
  38. target.fill(0xffffff);
  39. target.move(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());
  40. }
  41. private function hand2(target:BlackHuman):void {
  42. target.fill(0x000000);
  43. target.move(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());
  44. }
  45. private function hand3(target:Human):void {
  46. target.fill(0x0000ff);
  47. target.move(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());
  48. }
  49. }
  50. }

通过测试,上面的例子可以正常运行。以后我们可以在实际的工作中灵活运用,根据传来的参数,不同的类型放到不同的处理方法中去,增加程序的灵活性。

源文件下载:People.rar

分类: actionscript3.0学习笔记 标签: as3
下一页
RSS 订阅
  • Google
  • 有道
  • 鲜果
  • 抓虾
  • My Yahoo!
  • newsgator
  • Bloglines
  • 哪吒

分类列表

  • actionscript3.0学习笔记 (16)
  • air学习笔记 (6)
  • alternativa3D (3)
  • AS2疑难杂症 (1)
  • Box2D (3)
  • flash教程 (5)
  • flex学习笔记 (3)
  • 心情驿站 (24)
  • 我收集的flash 8.0资料 (3)
  • 我收集的flash 9.0资料 (3)
  • 我收集的文章 (21)
  • 我的AS2实验室 (4)
  • 我的AS3实验室 (9)
  • 我的新闻 (17)
  • 我的相册 (6)
  • 我翻译的英文资料 (7)
  • 日语学习 (2)
  • 英语学习 (2)

最近发表

  • 浅谈工具的意义
  • “小小便利店”终于上线啦
  • 禁止按tab时焦点从flash切换到地址栏
  • 隐藏Flex滚动条的箭头和滑竿
  • 为asdoc设定example
  • 一个测试睡眠的例子
  • Box2D——入门教程
  • Box2D——shoot Demo
  • 一个由单例模式引发的问题
  • 给图像加水印

最近评论

  • 空谷的回响 发表于 一个测试睡眠的例子
    我的QQ:373131285,希... »
  • manyu 发表于 一个测试睡眠的例子
    请给我发一份吧~我也在学习~谢谢... »
  • Brooks 发表于 mp3播放器 beta2.0(开源)
    好像不能下啊,楼主给我发一份吧,... »
  • velika 发表于 Box2D——shoot Demo
    刚开始学Box2d。发一份源码来... »
  • velika 发表于 一个测试睡眠的例子
    我也想要一份源码,谢谢15337... »
  • velika 发表于 一个测试睡眠的例子
    正在学BOX2D,楼主帮了我大忙... »
  • sky 发表于 一个测试睡眠的例子
    房主,你太强了,非常值得我学习,... »
  • GGGG 发表于 Box2D——shoot Demo
    zswrhua@163.com ... »
  • kirahua 发表于 Box2D——shoot Demo
    我也正在学习用BOX2D 做游戏... »
  • sans 发表于 Box2D——shoot Demo
    楼主很厉害哦,正在学box2d呢... »
  • 下一页 »

存档

  • 2010年五月 (2)
  • 2010年二月 (1)
  • 2009年十二月 (2)
  • 2009年十一月 (4)
  • 2009年十月 (1)
  • 2009年九月 (2)
  • 2009年八月 (2)
  • 2009年七月 (4)
  • 2009年五月 (3)
  • 2009年三月 (3)
  • 2009年二月 (2)
  • 2009年一月 (8)
  • 2008年十二月 (10)
  • 2008年十一月 (7)
  • 2008年十月 (4)
  • 2008年九月 (7)
  • 2008年八月 (8)
  • 2008年七月 (4)
  • 2008年六月 (5)
  • 2008年五月 (11)
  • 2008年四月 (14)
  • 2008年三月 (8)
  • 2008年二月 (12)

友情链接

  • alan新浪博客
  • sunbright
  • 云风Blog
  • 嘎嘎在东京
  • 张毅君/工长君
  • 永明则名
  • 海峡IT网
  • 闪界
  • 雷晟的新浪博客
  • 鼠标炸弹
置顶 WordPress
版权所有 © 2008-2010 动力男孩flash乐园 京ICP备09048608号
主题由 NeoEase 提供, 通过 XHTML 1.1 和 CSS 3 验证.Powered by WordPress