转载:如何在FlashMX2004里使用新的面向对象编程方式 作者:Peter Parente 来源:闪客帝国

gyscsdn 2004-12-15 09:36:50
翻译:xfykzz

概要

在网上有很多关于Flash编程的指南和可视化组件.然而我还没有看到关于Flash编程"最佳方法"这方面的文章,或者简单来说,关于Flash的正确地编程方法.这完全是可行的,因为关于在Flash环境下的面向对象设计局限已经被讨论多次了.然而,在Flash的最新版,也就是Flash MX 2004,引进了动作脚本2.0--一种符合ECMA(European Computer Manufacturers Association,欧洲计算机制造商协会)为JavaScript2推荐使用的标准,而且有点儿像Java.使用这种新的框架,在Flash中讨论高效地设计完全是可能的.

在本篇文章中,我打算介绍一下针对AS2.0的,虽然很基本,但很实用地设计方式.我决定从创建一个很简单地例子开始构筑整个思路.当完成了这个设计原型后,我将讨论一些最初的设计思想.而且当我们遇到一些复杂一点儿的例子时,我会做相应讲解.

前言

您首先需要安装2004,它可以在Macromedia的网站上下载.完全版也能在线购买.记得在安装完后重启,使得Flash Player 7 插件能顺利装好.

前瞻

通过一些参数,可以看到这就是我们将要制作的程序.很简单,但是它可以使我们看到AS2.0的不同特性.鼠标划过场景可以看到chasers是怎样工作的.点击并拖动小球可以手工移动它们.

第一步

通过以下步骤建立一个新项目:
1 、运行Flash2004,如果您使用的是试用版,请选择专业模式.
2 、选择"File->New"(文件->新建...)然后选择"Flash Project"(Flash 项目).或者,选项初始界面里的"Flash Project"(Flash 项目).
3 、为该项目命名为Demo.flp并保存.
4 、点击该项目名称旁边的小箭头来打开项目面板.它应该是屏幕右侧.如果在本文中提到的其它面板没有出现在屏幕内,您可以通过"Window"(窗口)菜单来调出它们.

现在该建立我们的文件了:
1 、选择"File->New"(文件->新建...)然后选择"Flash Document"(Flash文档),并保存到项目文件的同目录下,命名为Demo.fla.
2 、再次选择"File->New"(文件->新建...),选择"ActionScript File"(AS脚本文件).保存为Bouncer.as.
3 、现在建立另外两个AS脚本文件,保存并命名为Chaser.as和Scalable.as

最后,把所有的文件加入到项目工作区里:
1 、点击项目面板里左上角的黄色盒子图标,选择"添加文件..."菜单选项.
2 、选项所有刚刚创建的文件,点击"确定"

创建图形

下面我们要为demo创建必要的图形元素.我把图形做得很简单,这样我们就可以把注意力集中到代码上.但是您也完全可以把它做得更美观一点儿,只要您按照以下步骤:
1 、选择"Demo.fla"标签,这在工作区顶端.
2 、点击时间轴上的小箭头,把它折叠.这样可以使工作区更大.
3 、用快捷键Ctrl+L打开"Library面板"(库面板),或者从"Window"(窗口)菜单打开它.并把它放在屏幕右侧.
4 、点击该面板左下角的像一页纸的按钮,新建一个库对象,并给它起个名字"bouncer_mc"然后在"behavior"(行为)选项里选择"MovieClip"(影片剪辑).一般它会以(0,0)为初始坐标.唯一要求就是该元件的注册点须在该图像的正中.画个图,或者导入位图,或者从其它地方粘贴个什么图来,随你便.

我们还需要一个元件.创建另一个影片剪辑并命名为"chaser_mc".图像是什么样儿的随你,只要保证注册点在它的几何中心就可以了.

初始化代码

既然所有的资源都创建好了,我们现在可以把注意力转移到AS的编程上面来.我们将从面向对象编程的简单结构开始,逐步说明:继承,整合,以及接口.

继承
Flash MX 2004支持用户从单一类中继承.无论超类是自定义还是Flash自带的类.例如,我们可以继承MovieClip类,以及它的全部方法.这使得我们有机会自添加方法给库中对象.

...全文
71 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
hbzxlin 2005-01-14
  • 打赏
  • 举报
回复
好东西,谢谢楼主!
gyscsdn 2004-12-15
  • 打赏
  • 举报
回复
思考

继承在多次实验与对象关联中运行得很好.
继承的缺点是每个对象的类的行为在事先已经定义好了.每一个该对象的实例都是一样的,毫不例外.但是假如我想要一其中一个实例与另一个类关联,或者是取消关联,就不行了.除非我重建一个对象,或者修改该继承类中代码.

整合

整合是在面向对象编程里最有用的.我们可以把影片剪辑对象作为参数传递给另一个自定义类,并在该类里重定义事件方法,实例化该类来达到控制影片剪辑的目的.例如.我们可以新建一个参数中含有影片剪辑的类.这样,我们可以在运行时灵活控制一个实例,而不是在设计时就定死(比如继承).

现在我们要新建一个类来实现鼠标跟随.这次我们将使用整合,而不是继承.它们将在运行时被连接,而不是像继承那样在设计时就连接好了.

1 、切换到"Chaser.as"
2 、输入以下代码:

//原文注释略
class Chaser {
private var speed:Number;
private var graphic:MovieClip;
//event handler called once per frame
private function onEnterFrame() {
//move the chaser closer to the mouse cursor
this.graphic._x += (this.graphic._parent._xmouse - this.graphic._x)*speed;
this.graphic._y += (this.graphic._parent._ymouse - this.graphic._y)*speed;
}
//constructor
function Chaser(s:Number, g:MovieClip) {
this.speed = s;
this.graphic = g;
//(原文注释略)
var self = this;
this.graphic.onEnterFrame = function() {self.onEnterFrame()};
}
}
(注意其构造函数第二个参数类型为MovieClip)

下一步得使我们的对象在AS中可见(可以用attachMovie创建):
1 、打开库面板
2 、右击chaser_mc对象并选择"链接..."
3 、勾选"导出为动作脚本"
4 、注意不要像上面Bouncer那样连接Chaser!

现在我们要写点儿在运行时执行的代码示例:
1 、切换到"Demo.fla"
2 、打开动作面板
3 、选中时间轴第一帧
4 、输入以下代码:

//dynamically add mouse chasers to the movie
for(var i:Number=1; i < 10; i++) {
//create the chaser graphic
c = this.attachMovie('chaser_mc', 'chaser'+i, i);
//create the chaser class that will control the graphics
obj = new Chaser(0.05*i, c);
}(注意最后一句bj = new Chaser(0.05*i, c); 第二个参数是我们创建的对影片剪辑对象)

现在按Ctrl+Enter执行看看,每一个对象有不同的速度作鼠标跟随.

思考

整合使得在运行时改变对象行为变得十分容易,我们可以在运行时任意添加对象到Chaser类中.这也避免了个别例外情况的不好处理.这比死板的继承灵活多了.

当然,整合也有缺点.第一点,如果我们要定义更多的属性(比如_x,_y,_width,_height,etc),我们不得不创建更多函数去定义,这使得工作量加大(我觉得不算问题).

第二点,不能同时使得某一对象被赋于两个类中的方法.比如现在我们创建另一个类Fader,并在其中定义了onEnterFrame方法. 我们没有办法使得Fader与Chaser类中的onEnterFrame方法同时被赋予某一对象,因为如果我们那样做,后一个类的onEnterFrame方法会覆盖前一个.

第二个问题我们可以解决,通过一些额外的代码来使得对象支持重复定义的代码都能够执行(即观察模式).许多Flash MX 2004里的组件就使用了这样的事件处理接口.更多相关内容可以查阅设计模式版块.

接口

AS2.0不支持多个继承.它使用"接口"这个概念来完成 类似工作.在接口里只声明类的方法而没有实际内容.实际内容依靠具体化该接口的类来实现.

下面我们创建一个名为Scalable的接口然后让Chaser类来具体实现它.这个接口将声明一个可以调整对象大小的函数.

1 、切换到Scalable.as
2 、输入以下代码:


//代码注释略
interface Scalable {
//scale the width and height of an object by a factor
public function Scale(w:Number, h:Number);
}
//(注意第一行用interface声明,而不是Class,最后一行只有方法声明而没有内容)
现在我们在Chaser类中具体化该方法:

1 、 修改Chaser类中的代码和Demo.as第一帧里的代码,被修改部分已经标蓝.

class Chaser implements Scalable {
private var speed:Number;
private var graphic:MovieClip;
public function Scale(w:Number, h:Number) {
//scale the width and height of the graphic by a factor
this.graphic._width *= w;
this.graphic._height *= h;
}
...

//dynamically add mouse chasers to the movie
for(var i:Number=1; i < 10; i++) {
//create the chaser graphic
c = this.attachMovie('chaser_mc', 'chaser'+i, i);
//create the chaser class that will control the graphics
obj = new Chaser(0.05*i, c);
obj.Scale(1.0/i, 1.0/i)
}(注意类定义第一行:class Chaser implements Scalable { 表示接口的实现)

最后按Ctrl+Enter测试一下该影片看看,运行得缓慢的实例将比运行得快的大(正如上面看到的那样)


gyscsdn 2004-12-15
  • 打赏
  • 举报
回复
现在我们创建一个类,它可以使我们的bouncer对象能在场景内弹来弹去,而且用户能够随意拖拽.我们要写的类将继承于MovieClip类,以便该类可以直接与bouncer_mc对象连接:
1 、选中"Bouncer.as"标签.
2 、把以下代码输出并保存:

/*
This example shows how a class can inherit from the built-in type MovieClip.
Any class that inherits from this type can be attached to a movie clip object
in the library. When an instance of such a movie clip is placed on the stage,
either programmatically or at runtime, an instance of the class is
automatically created and acts as the ActionScript interface to the
MovieScript object. This example causes any movie clip in the library to
bounce around on the stage at a random speed.
The inheritance approach to controlling stage objects with classes is the most
common, mainly because it is simple to implement. Just extend MovieClip with
new functionality and link it to a library object. However, this approach
limits a library object to a single class of functionality that is fixed at design time.
*/
class Bouncer extends MovieClip {
//实例变量
private var y_vel:Number;
private var x_vel:Number;
private var x_min:Number;
private var x_max:Number;
private var y_min:Number;
private var y_max:Number;
private var dragging:Boolean = false;
//构造器
public function Bouncer() {
//为注册点确定一个范围
var halfWidth = this._width/2;
var halfHeight = this._height/2;
var clipBounds = _root.getBounds();
this.x_min = clipBounds.xMin + halfWidth;
this.y_min = clipBounds.yMin + halfHeight;
this.x_max = clipBounds.xMax - halfWidth;
this.y_max = clipBounds.yMax - halfHeight;
//选择一个随机方向开始移动这个MC.
this.x_vel = Math.floor(Math.random()*21)-10;
this.y_vel = Math.floor(Math.random()*21)-10;
}
//事件处理, 每帧相应一次
function onEnterFrame(){
//如果我们正在拖拽,不要移动目标
if (this.dragging) return;
//基于目标的速度计算下一个位置
var next_x = this._x + this.x_vel;
var next_y = this._y + this.y_vel;
//确认我们没有超出左边界
if (next_x < this.x_min){
this.x_vel *= -1;
next_x = this.x_min + (this.x_min - next_x);
}
//确认我们没有超出右边界
else if (next_x > this.x_max){
this.x_vel *= -1;
next_x = this.x_max - (next_x - this.x_max);
}
//确认我们没有超出上边界
if (next_y < this.y_min){
this.y_vel *= -1;
next_y = this.y_min + (this.y_min - next_y);
}
//确认我们没有超出下边界
else if (next_y > this.y_max){
this.y_vel *= -1;
next_y = this.y_max - (next_y - this.y_max);
}
//把已经计算好的下一个位置分配给图形元件的X,Y值
this._x = next_x;
this._y = next_y;
}
//事件处理,当目标被触发(鼠标被按下),开始相应
function onPress() {
//在MC上开始拖拽运动 (通过FLASH自动进行)
this.startDrag();
//开始拖拽时做一个标志
this.dragging = true;
}
//事件相应,当目标被释放(鼠标左键松开),开始相应
function onRelease() {
//停止拖拽
this.stopDrag();
this.dragging = false;
}
//事件相应,当目标被释放(鼠标松开在相应范围之外),开始相应
function onReleaseOutside() {
//停止拖拽,如果我们正确的拖拽
if(this.dragging) {
this.stopDrag();
this.dragging = false;
}
}
}(值得注意的是代码的第一行:class Bouncer extends MovieClip {
表明是从MovieClip继承而来)

现在我们可以把该类与库对象连接起来了:
1 、打开库面板
2 、右击"bouncer_mc",选中"Linkage..."(链接...)
3 、勾选"Export for ActionScript"(为动作脚本导出)
4 、在"AS2.0 class"输入框内写入"Bouncer".

现在我们把Bouncer类和bouncer_mc影片剪辑对象连接起来了.当该对象的一个实例被创建到场景中时,Flash会自动地调用该类的构造函数.这样就使我们的类能执行在上面代码里定义的事件方法.

现在我们要创建一些bouncer类的实例:
1 、转到Demo.fla标签
2 、打开库面板然后拖拽一个bouncer_mc的影片剪辑实例进场景.
3 、多拖动几个实例并改变大小

现在我们按Ctrl+Enter测试该影片看看会发生什么:

小球在不停地弹动(就像上面看到的).

2,275

社区成员

发帖
与我相关
我的任务
社区描述
多媒体/设计/Flash/Silverlight 开发 Flash流媒体开发
社区管理员
  • Flash流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧