- abstract class & virtual function
在c++裡我們有virtual function可以用,在Java裡則可以宣告abstract class ,而在actionscript 3.0雖然有undocumented的virtual specifier可以使用,但卻無法達到pure virtual function的效果,所幸還有override可以發揮,我們一樣也可以在actionscript 3.0達到abstract class的效果,一個簡易的範例如下:
/* Motion.as */
package com.xinyu.motion{
public class Motion{
public virtual function get running():Boolean{
return false;
}
public virtual function start():void{
}
public virtual function stop():void{
}
}
}
借用之前motion那一篇文章裡的程式碼,只是這裡我們不使用interface的方式來設定,並且將整個motion獨立出來。可以看到我在Motion裡所宣告的函式都加上virtual關鍵字,實際上有沒有加上都不會有任何差別,只是這麼做是為了一個良好的設計習慣。
底下則是一個SpaceMotion2D繼承於Motion的撰寫方式。
/* SpaceMotion2D */
package com.xinyu.motion{
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent
import flash.geom.Rectangle;
import flash.display.DisplayObject;
import com.xinyu.motion.Motion;
import com.xinyu.science.Science;
public class SpaceMotion2D extends Motion{
private var _timer:Timer;
protected var _xDir:int;
protected var _yDir:int;
protected var _speed:Number;
protected var _range:Rectangle;
protected var _obj:DisplayObject;
public function SpaceMotion2D(obj:DisplayObject, range:Rectangle, speed:Number = 0.1, fps:Number = 25){
_obj = obj;
_range = range;
_speed = Math.min(20, Math.max(speed, 0.001));
do{
_xDir = Science.randInt(-1,1);
}while(_xDir == 0);
do{
_yDir = Science.randInt(-1,1);
}while(_yDir == 0);
_timer = new Timer(1000/fps);
_timer.addEventListener(TimerEvent.TIMER, onTimer);
}
protected function onTimer(event:TimerEvent):void{
if(_obj.x + _obj.width/2 + _speed > _range.width){
_xDir = -1;
}
if(_obj.x - _obj.width/2 - _speed < _range.x){
_xDir = 1;
}
if(_obj.y + _obj.height/2 + _speed > _range.height){
_yDir = -1;
}
if(_obj.y - _obj.height/2 - _speed < _range.y){
_yDir = 1;
}
_obj.x += _xDir * _speed;
_obj.y += _yDir * _speed;
}
override public function start():void{
_timer.start();
}
override public function stop():void{
_timer.stop();
}
override public function get running():Boolean{
return _timer.running;
}
}
}
如同剛剛所說的,為了培養良好的設計模式,請在start(), stop(), running()前面都加上override以表示這些functions是從Motion繼承而來重新實做的。
所以大致上AS3裡的abstract class就是以這種方式來實現,至於AS4裡會怎麼去定義這個性質就請拭目以待啦!
另外如果你有興趣的話也可以將SpaceMotion2D改成3D,下面就是一個SpaceMotion3D繼承於SpaceMotion2D的寫法:
/* SpaceMotion3D */
package com.xinyu.motion{
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.Rectangle;
import flash.display.DisplayObject;
import com.xinyu.motion.SpaceMotion2D;
import com.xinyu.science.Science;
public class SpaceMotion3D extends SpaceMotion2D {
private var _zDir:int;
private var _z:Number;
private var _depth:Number;
private var xyScaleRatio:Number;
private var objScaleRatio:Number;
public function SpaceMotion3D(obj:DisplayObject, range:Rectangle, depth:Number, speed:Number = 1, fps:Number=25) {
super(obj, range, speed, fps);
_z = depth;
_depth = depth;
calXYScaleRatio();
calObjScaleRatio();
do {
_zDir = Science.randInt(-1, 1);
} while (_zDir == 0);
}
override protected function onTimer(event:TimerEvent):void {
var zRatio:Number = _z / _depth;
if (_obj.x + _obj.width / 2 + _speed > _range.width - _range.width * xyScaleRatio * zRatio ) {
_xDir=-1;
}
if (_obj.x - _obj.width / 2 - _speed < _range.x + _range.width * xyScaleRatio * zRatio) {
_xDir=1;
}
if (_obj.y + _obj.height / 2 + _speed > _range.height - _range.height * xyScaleRatio * zRatio ) {
_yDir=-1;
}
if (_obj.y - _obj.height / 2 - _speed < _range.y + _range.height * xyScaleRatio * zRatio) {
_yDir=1;
}
if (_z - _speed < 0) {
_zDir = 1;
}else if (_z + _speed > _depth) {
_zDir = -1;
}
_obj.x += _xDir * _speed;
_obj.y += _yDir * _speed;
_z += _zDir * _speed;
_obj.scaleX = 1 - objScaleRatio * zRatio;
_obj.scaleY = 1 - objScaleRatio * zRatio;
}
private function calXYScaleRatio():void{
var max: Number = Science.findMax(_range.width, _range.height);
xyScaleRatio = _depth / ( 4*max);
xyScaleRatio = Math.min(0.9, Math.max(xyScaleRatio, 0.1));
}
private function calObjScaleRatio():void{
var min: Number = Science.findMin(_range.width, _range.height);
objScaleRatio = min / (2 * _depth);
objScaleRatio = Math.min(0.9, Math.max(objScaleRatio, 0.1));
}
}
}
這裡的3D效果是我簡單以視覺的判斷產生出來的,並沒有透過嚴謹的mathematical計算來達成,也就是說SpaceMotion3D.as並不是仰賴Flash CS4的z-axes的功能,想要更完善的功能請使用PaperVision3D吧!
No comments:
Post a Comment