這是一個 Flash/AS3 專案,實現「雪花飄落並在地面自然堆積」的視覺效果。核心挑戰在於:雪花非直線下落、大小不一、下落速度隨大小變化、落地後像素級碰撞形成不規則堆疊。源碼採用隨機旋轉力、縮放比例關聯速度、兩階段碰撞檢測(粗略+像素級)三大技巧,效能與效果兼顧。
ln.rotationX += Math.random() * 10; ln.rotationY += Math.random() * 10;
每幀給予雪花微小隨機 3D 旋轉增量,使其在下落過程中呈現「飄搖」姿態,而非僵硬的垂直位移。
ln.scaleX = ln.scaleY = Math.random() * 0.3 + 0.1; // 0.1 ~ 0.4
_indexes[ln] = { vy:Math.random() * ln.scaleY * 8 + 4, iniy:ln.y };
scale 越大 → 視覺上越「近」 → 下落速度 vy 越快 (近大遠小,近處物體視角速度更大)。iniy 記錄初始 Y 座標,用於落地後重置位置復用雪花對象 (對象池模式)。// 粗略檢測:超過當前 x 座標的堆疊高度 _plie[int(ln.x)]
if (ln.y >= _plie[int(ln.x)]) {
// 像素級精確檢測:使用 BitmapData.hitTest
if (!_plieImg.hitTest(new Point(0,0), 0, new Point(ln.x, ln.y)) && ln.y < STAGEHEIGHT - DENSITY) return;
// 真正著地
_shut.addChild(ln); // 加入快照容器
_plieImg.draw(_shut); // 將雪花繪製到堆疊快照
addChild(ln); // 重新加入顯示列表 (繼續下一輪)
_plie[int(ln.x)] = Math.min(ln.y - DENSITY, _plie[int(ln.x)]); // 更新該 x 的堆疊高度
ln.y = _indexes[ln].iniy; // 重置 Y
ln.x = Math.random() * STAGEWIDTH; // 隨機 X,使堆疊均勻
}
_plie[x] 記錄每個 X 座標的當前堆疊高度。雪花 Y 超過此高度才進入精確檢測,避免對所有雪花每幀都做昂貴的 hitTest。_plieImg 為 BitmapData,持續累積已落地雪花的像素圖。hitTest(alphaThreshold=0) 進行像素級碰撞,確保雪花能「卡」在凹陷處,形成自然堆疊輪廓。_shut 為 Sprite 容器,每次著地前將雪花加入,draw() 到 _plieImg,再移回主顯示列表,實現「永久保留像素」且「對象復用」。package {
import flash.display.*;
import flash.events.Event;
import flash.geom.Point;
public class SnowEffect extends Sprite {
private var _flakes:Vector.<SnowFlake> = new Vector.<SnowFlake>();
private var _plie:Array = []; // uint 堆疊高度
private var _plieImg:BitmapData; // 累積像素
private var _shut:Sprite; // 快照容器
private var _indexes:Dictionary; // 對象池數據
public function SnowEffect() {
// 初始化 _plieImg, _shut, _plie 陣列 (寬度 = STAGEWIDTH)
// 建立 N 個 SnowFlake,隨機 scale, x, y, rotation, vy
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void {
for each (var flake:SnowFlake in _flakes) {
// 1. 隨機旋轉
flake.rotationX += Math.random() * 10;
flake.rotationY += Math.random() * 10;
// 2. 下落
flake.y += _indexes[flake].vy;
// 3. 碰撞檢測與堆疊 (見上文)
}
}
}
}
class SnowFlake extends Sprite {
// 內部繪製雪花圖形 (向量或位圖)
}
STAGEWIDTH, STAGEHEIGHT 應從 stage.stageWidth/Height 獲取。DENSITY 控制堆疊「鬆緊度」,值越小堆疊越高。https://files.cnblogs.com/flash3d/snow.rar (含完整 Flash Builder/AS3 專案)
這個效果展示了「簡單規則產生複雜自然現象」的典型思路:隨機力賦予生命感、縮放關聯速度構建景深、分級碰撞兼顧效能真實感。同樣原理可擴展至落葉、塵埃、氣泡等粒子系統,是遊戲特效與互動媒體開發的基礎範式。