最近在論壇上看到有人問相關的問題
需要在 Flash 內用點陣圖作慢速移動效果
每次移動的單位小於一個像素
結果跑出來的效果會卡卡的感覺
看起來點陣圖還是以一個像素的距離在移動
下面是平滑與不平滑移動效果的比較範例

BmpMotionCompare

這是由於電腦螢幕最小單位是像素而已
倘若點陣圖不是位於整數座標上
Flash 渲染引擎必須要重新取樣
預設它可能是用 Nearest 方式而非 Linear or Cubic
所以才會無法模擬出點陣圖位於非整數座標的效果

可是我印象中,內嵌 SWF 的點陣圖只要打開 smoothing 就能夠很平滑的移動啊
於是測試了一下
假如點陣圖是內嵌 SWF 內,勾選 smoothing 並且不能 Export for AS
這樣在舞台的上的慢速移動是很順的

用 AS3 去 Trace 發現,點陣圖已經被轉成 Shape 也就是點陣圖填色
再進一步將載入的點陣圖,改用 AS3 作 Bitmap Fill 也能達到相同效果

總結下來,發現有好幾種方式都可以作到平滑移動

點陣圖移動平滑技巧 1. 使用 3D Transform 強迫柔化

BmpSmoothMotion01

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Matrix3D;
 
stage.scaleMode = StageScaleMode.NO_SCALE;
 
var bmpData:BitmapData = new OrigamiMurexBmp();
 
var bmp:Bitmap = new Bitmap(bmpData, PixelSnapping.AUTO, true);
 
bmp.transform.matrix3D = new Matrix3D();
bmp.y = 50;
 
addChild(bmp);
 
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
 
function onEnterFrameHandler(e:Event):void{
 bmp.x = (bmp.x + 0.051) % 200;
}

點陣圖移動平滑技巧 2. 使用點陣圖填色

BmpSmoothMotion02

import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.Graphics;
 
stage.scaleMode = StageScaleMode.NO_SCALE;
 
var bmpData:BitmapData = new OrigamiMurexBmp();
 
var sp:Sprite = new Sprite();
var g:Graphics = sp.graphics;
 
g.beginBitmapFill(bmpData, null, false, true);
g.drawRect(0, 0, bmpData.width, bmpData.height);
g.endFill();
 
sp.y = 50;
addChild(sp);
 
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
 
function onEnterFrameHandler(e:Event):void{
 sp.x = (sp.x + 0.051) % 200;
}

點陣圖移動平滑技巧 3. 稍微縮放 Bitmap 強迫柔化

BmpSmoothMotion03

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Matrix;
 
stage.scaleMode = StageScaleMode.NO_SCALE;
 
var bmpData:BitmapData = new OrigamiMurexBmp();
 
var bmp:Bitmap = new Bitmap(bmpData, PixelSnapping.AUTO, true);
 
var m:Matrix = new Matrix();
m.scale(1.001, 1.001); // 稍微放大強迫抗鋸齒
bmp.transform.matrix = m;
bmp.y = 50;
 
addChild(bmp);
 
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
 
function onEnterFrameHandler(e:Event):void{
 bmp.x = (bmp.x + 0.051) % 200;
}

點陣圖移動平滑技巧 4. 稍微旋轉 Bitmap 強迫柔化

BmpSmoothMotion04

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Matrix;
 
stage.scaleMode = StageScaleMode.NO_SCALE;
 
var bmpData:BitmapData = new OrigamiMurexBmp();
 
var bmp:Bitmap = new Bitmap(bmpData, PixelSnapping.AUTO, true);
 
var m:Matrix = new Matrix();
m.rotate(0.001221); // 極小的旋轉量強迫抗鋸齒
bmp.transform.matrix = m;
bmp.y = 50;
 
addChild(bmp);
 
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
 
function onEnterFrameHandler(e:Event):void{
 bmp.x = (bmp.x + 0.051) % 200;
}

以上四種方式都能達到不錯的效果
不過需要特別注意的是
Bitmap 本身到移動座標的外層容器之間絕對不能用點陣圖快取或是濾鏡,否則就破功了

Sprite 1 – Sprite 2 – Sprite 3 – Bitmap – BitmapData

假設實際作移動的對象是 Sprite 2
那麼 Sprite 2, Sprite 3, Bitmap 都不可用 cacheAsBitmap 或是濾鏡