2006年2月23日 星期四

ActionScript 3.0 beta 1 物件比較   [+/-]

Ticore's Blog

在物件導向的程式語言內,常常會遇到資料物件的比較

比較的方式至少有這幾種方式

1.兩個物件參考是否指向同一個物件
2.兩個物件所持有的資料是相同的
3.使用者定義上是相同的

一般少量資料的基礎型別都是以本身持有資料進行比較
像是整數、浮點、布林變數等等

而資料多的複雜型別物件預設是以參考進行比較
假如需要進行資料比較,大部分都是要自行實作比較方式

字串的型別比較特殊
可以持有大量資料
在現在很多高階語言中卻又是不可修改物件 (Immutable Object)
相同字串的物件常常會被復用,意即為了節省資源,不會重複產生相同的物件
除非使用 new 運算子強迫產生新物件出來

例如:
 var str1:String = new String("test");
var str2:String = new String("test");
trace(str1 == str2); // false
在 Flash 8 的環境執行,結果是 false 的
稍作修改,在 Java、Javascript 上執行也是有類似的結果


但是 ActionScript 3.0 似乎作了修改
上述的例子在 Flash 8.5 執行將會回傳 true
不僅僅是如此
新增 E4X 的 XML、XMLList 物件也是一樣
只要是 Base Class 物件都可以直接使用 == 運算子作比較

String 改成這樣,比較不會有問題
因為很多人早就把它當作基礎物件來用,一直狂用 == 作比較
AVM 底層可能也是一直回收使用
『物件參考上的比較』與『物件資料的比較』結果可以達到一致性

但是像 XML 比較大型的物件
這樣做可能會遇到一些其他的問題
譬如說現在想我想要比較的是『物件參考相等性』
因為 == 運算子已經被底層覆載
必須要改用 === 運算子才可以做物件參考比較

不過相對的,像 XML 這種複雜大型物件
要做資料相等性的比較卻是變的相當簡單


以下是一些測試程式
相關連結:AS3 基礎型別物件一致性
Read more...

2006年2月4日 星期六

替 MovieClip 加上 FPS 屬性   [+/-]

Ticore's Blog

以下是用AS 2.0類別繼承MovieClip
以setInerval的方式模擬FPS的功能
為了避免與既有的影格控制函式發生衝突
一併連影格控制函式一起覆寫了
但是使用上仍有不少限制

譬如主要撥放swf的FPS要越高越好
不然用setInterval模擬無法達到高FPS的效果

class MovieClipFPS extends MovieClip {
 //
 //==================================================
 //
 private var _fps:Number = 12;
 private var intervalId:Number;
 private var target:MovieClip;
 //
 private var _play:Function;
 private var _gotoAndPlay:Function;
 private var _gotoAndStop:Function;
 private var _stop:Function;
 private var _nextFrame:Function;
 private var _prevFrame:Function;
 //
 //==================================================
 //
 public function MovieClipFPS() {
  init();
 }
 public function init():Void {
  //覆寫相關影格控制function
  this._play = this.play;
  this.play = function() {
   stopInterval();
   startInterval();
  };
  this._gotoAndPlay = this.gotoAndPlay;
  this.gotoAndPlay = function(frame) {
   stopInterval();
   this._gotoAndPlay(frame);
   startInterval();
  };
  this._gotoAndStop = this.gotoAndStop;
  this.gotoAndStop = function(frame) {
   stopInterval();
   this._gotoAndStop(frame);
  };
  this._stop = this.stop;
  this.stop = function() {
   stopInterval();
  };
  this._nextFrame = this.nextFrame;
  this.nextFrame = function() {
   stopInterval();
   this._nextFrame();
  };
  this._prevFrame = this.prevFrame;
  this.prevFrame = function() {
   stopInterval();
   this._prevFrame();
  };
  //
  _stop();
  target = this;
  startInterval();
 }
 //
 //==================================================
 //
 public function set fps(f:Number):Void {
  _fps = f;
  if (intervalId != null) {
   stopInterval();
   startInterval();
  }
 }
 public function get fps():Number {
  return _fps;
 }
 //
 //==================================================
 //
 private function startInterval():Void {
  //trace(1000 / _fps);
  intervalId = setInterval(run, Math.floor(1000 / _fps), this);
 }
 private function stopInterval():Void {
  clearInterval(intervalId);
  intervalId = null;
 }
 private function run(target):Void {
  //trace("run");
  //trace(target._currentframe + " : " + target._totalframes);
  target._gotoAndStop((target._currentframe) % target._totalframes + 1);
  updateAfterEvent();
 }
 //
 //==================================================
 //
}
Read more...