粒子系統 particle system
TRANSCRIPT
1
粒子系統 Particle System報告人:吳宗錫
2
簡介 一種模擬模糊現象的技術。 可用來模擬:火焰、爆炸、火花、雨滴、煙霧、水流、落葉、光、雲、雪、塵、流星尾跡……等。 應用: 影像繪製、遊戲引擎、模擬、藝術。
3
起源 量子物理: 黑體輻射→光電效應→原子結構→物質波 不確定性原理:隨機
4
組成
發射器
粒子系統
5
發射器 發射粒子 決定粒子發射的方向 爆炸:爆炸點是發射器,往四方散射 下雨:整片雲都是發射器,往地面落下
6
粒子系統 統整所有的粒子:利用 List, Stack 或 Queue… 等資料儲存方式 管理總體平均的生命長度以及最大值和最小值 管理總體平均的大小及形狀、顏色 管理總體平均的移動方向(如果是四射發散的系統就不用) 管理系統持續的總時間
7
粒子 每個粒子都有自己的生命長度 每個粒子都有自己的大小形狀、顏色 每個粒子都有自己要前進的方向 粒子間重疊時會有重疊的表現(累加或是碰撞) 粒子會隨時間更新自己的狀態:大小、位置、剩餘生命……
8
實作開發 支援每秒更新的系統,例如:遊戲引擎畫布( Canvas )
9
範例展示 Particle System Demo using Javascript
10
環境 HTML5 + Javascript
Files: index.html 網頁主架構script.js 粒子系統style.css 網頁排版
11
系統流程圖Initialize
Add()
Update()
Draw()
1/60 秒
12
主系統與發射器 Code Level for Main System & Emitter
13
HEADER // 常數 var FPS = 60; // 1 秒間描繪的次數 var SCREEN_WIDTH = window.innerWidth; // 畫面寬度 var SCREEN_HEIGHT = window.innerHeight; // 畫面高度 // 變數 var ctx; // 2D contextvar var particleList = []; // 放入建立好的顆粒的陣列 var mx = null; // 滑鼠的 X 座標 var my = null; // 滑鼠的 Y 座標
14
ONLOAD window.onload = function () { init(); };
15
INIT()// 系統初始設定 var init = function () { var canvas = document.getElementById("mycanvas"); if (!canvas || !canvas.getContext) { // 確認 canvas 元素是否存在 return false; } canvas.width = SCREEN_WIDTH; canvas.height = SCREEN_HEIGHT; ctx = canvas.getContext("2d"); // 登錄滑鼠事件至 canvas canvas.addEventListener("mousemove", updateMousePos, false); // 滑鼠移動時的事件 canvas.addEventListener("mouseout", resetMousePos, false); // 滑鼠跑出畫面外時的事件 loop(); // 執行主迴圈 };
16
滑鼠(發射器) & 主迴圈 // 取得滑鼠位置 var updateMousePos = function (e) { var rect = e.target.getBoundingClientRect();
mx = e.clientX - rect.left; my = e.clientY - rect.top; }; // 重設滑鼠位置 var resetMousePos = function (e) { mx = null; my = null; };
// 系統主迴圈 var loop = function () { add(); update(); draw(); setTimeout(loop, 1000 / FPS);
};
粒子系統
發射器
17
粒子系統功能 Code Level for Particle System
18
ADD() // 新增粒子 var add = function () { if (mx !== null && my !== null) { // 建立實體 var p = new Particle(mx, my); p.create(); // 將實體收納至陣列中 particleList.push(p); } };
19
UPDATE() // 更新粒子 var update = function () { var list = []; for (var i = 0; i < particleList.length; i++) { particleList[i].update(); // 若刪除旗標未被立起就收納至陣列中 if (!particleList[i].isRemove) { list.push(particleList[i]); } } particleList = list; };
20
DRAW() // 粒子的描繪 var draw = function () { // 描繪背景 ctx.fillStyle = "rgb(0, 0, 0)"; ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // 描繪粒子 ctx.save(); ctx.globalCompositeOperation = "lighter"; for (var i = 0; i < particleList.length; i++) { particleList[i].draw();
} ctx.restore(); };
21
粒子 Code Level for Particles
22
粒子建構子 var Particle = function (x, y) { this.x = x; this.y = y; };
23
粒子類別 PART 1 // 屬性與方法 Particle.prototype = { // 屬性 x: null, // X 座標 y: null, // Y 座標 vx: 0, // X 軸方向的速度 vy: 0, // Y 軸方向的速度 radius: 0, // 半徑 color: null, // 顏色 life: 0, // 生命值 isRemove: false, // 移除旗標 ……
24
粒子類別 PART 2 // 屬性與方法 create: function () { // 隨機設定初始速度、尺寸、顏色 this.vx = Math.random() * 6 - 3; this.vy = Math.random() * 6 - 3; this.radius = Math.random() * 22 + 5; var r = 150; var g = Math.floor(Math.random() * 100 + 155); var b = Math.floor(Math.random() * 155 + 100); this.color = "rgb(" + r + "," + g + ", " + b + ")"; this.life = Math.random() * 60 + 30; }, ……
25
粒子類別 PART 3 // 屬性與方法 update: function () { // 更新位置與生命值 this.life--; this.x += this.vx; this.y += this.vy; this.radius *= .975; // 粒子大小漸漸縮減 if (this.life <= 0) // 粒子壽命已盡 this.isRemove = true; if (this.x < 0 || this.x > SCREEN_WIDTH || this.y > SCREEN_HEIGHT) // 超出界限 this.isRemove = true; }, ……
26
粒子類別 PART 4 // 屬性與方法 // 描繪 draw: function () { ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.fill(); } };
27
展示 Demo
Demo
28
參考資料 Wiki - 量子動力學 Wiki - 粒子系統 書籍 - 接案我最行 ! HTML5 + CSS3 + JavaScript 商業範例必殺技
29
Thanks for your attention !