首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

ActionScript 3.0 實現逼真雪花飄落與堆積效果:物理模擬與像素級碰撞檢測

     編輯:關於.NET

前言

這是一個 Flash/AS3 專案,實現「雪花飄落並在地面自然堆積」的視覺效果。核心挑戰在於:雪花非直線下落、大小不一、下落速度隨大小變化、落地後像素級碰撞形成不規則堆疊。源碼採用隨機旋轉力、縮放比例關聯速度、兩階段碰撞檢測(粗略+像素級)三大技巧,效能與效果兼顧。

核心技術解析

1. 隨機旋轉力:模擬空氣擾動

ln.rotationX += Math.random() * 10;
ln.rotationY += Math.random() * 10;

每幀給予雪花微小隨機 3D 旋轉增量,使其在下落過程中呈現「飄搖」姿態,而非僵硬的垂直位移。

2. 縮放比例決定視覺深度與速度

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 座標,用於落地後重置位置復用雪花對象 (對象池模式)。

3. 兩階段碰撞檢測:效能與精度平衡

// 粗略檢測:超過當前 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 {
    // 內部繪製雪花圖形 (向量或位圖)
}

效果優化要點

  • 對象池:雪花數量固定 (如 200-500),落地後重置位置復用,避免頻繁 GC。
  • BitmapData 累積:堆疊圖層只增不減,記憶體隨時間增長,長時間運行需定期清理或限制幀數。
  • Stage 尺寸適配:STAGEWIDTH, STAGEHEIGHT 應從 stage.stageWidth/Height 獲取。
  • 密度常數:DENSITY 控制堆疊「鬆緊度」,值越小堆疊越高。

源碼下載

https://files.cnblogs.com/flash3d/snow.rar (含完整 Flash Builder/AS3 專案)

總結

這個效果展示了「簡單規則產生複雜自然現象」的典型思路:隨機力賦予生命感、縮放關聯速度構建景深、分級碰撞兼顧效能真實感。同樣原理可擴展至落葉、塵埃、氣泡等粒子系統,是遊戲特效與互動媒體開發的基礎範式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved