<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                本系列所有文章可以在這里查看[http://blog.csdn.net/cloud_castle/article/category/2123873](http://blog.csdn.net/cloud_castle/article/category/2123873) 接上文[Qt5官方demo解析集10——Qt Quick Particles Examples - Emitters](http://blog.csdn.net/cloud_castle/article/details/33306133) Affectors是Qt官方粒子系統demo中的第二個例程,它是在Emitters上的進一步擴展。我們將看到,通過使用Affectors,我們能夠創造更加靈活的粒子顯示以及交互行為。 首先還是看下介紹:This is a collection of small QML examples relating to using Affectors in the particle system. Each example is a small QML file emphasizing a particular type or feature. 很簡短,告訴我們這個demo依然是由多個使用Affectors的小例子構成。運行后是同樣的選擇框: ![](https://box.kancloud.cn/2016-01-18_569cbd0273b26.jpg) 一共有10個例子,我們還是從第一個開始: (1)Age 來看看是個什么效果:進入圖中矩形框的雪花都變小并逐漸消失了。 ![](https://box.kancloud.cn/2016-01-18_569cbd0292d42.jpg) 來看看這個小例子是怎么寫的吧~ age.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { id: root width: 360 height: 600 color: "white" ParticleSystem { id: particles } ImageParticle { // 這里向我們展示另外一種圖像粒子的設置 system: particles sprites: Sprite { // sprites屬性用來定義一組幀圖片來作為粒子,這樣粒子可以像GIF一樣擁有自己的動畫 name: "snow" source: "../../images/snowflake.png" // 這是一張具有51幀的雪花圖形 frameCount: 51 frameDuration: 40 // 幀動畫的基本設置 frameDurationVariation: 8 } } Emitter { system: particles emitRate: 20 lifeSpan: 8000 velocity: PointDirection { y:80; yVariation: 40; } // 加速度下落 acceleration: PointDirection { y: 4 } size: 36 endSize: 12 sizeVariation: 8 width: parent.width height: 100 } MouseArea { id: ma anchors.fill: parent hoverEnabled: true } Rectangle { // 這里使用Rectangle作為Age的父類,當然Age可以定義自己的坐標以及區域,但是加入Rectangle可視化效果更好 color: "#803333AA" // 半透明的湛藍色 border.color: "black" x: ma.mouseX - 36 // 這里用到屬性綁定使得該矩形可以跟隨鼠標的移動,并以鼠標為中心點 y: ma.mouseY - 36 width: 72 height: 72 //! [0] Age { // Age繼承自Affector,其實在上一篇Emitters中我們就接觸了一個Affector:Turbulence,它可以提供一個氣流的效果,而這里的Age則允許我們改變粒子的生命周期。 anchors.fill: parent system: particles once: true // 每個粒子只影響一次 lifeLeft: 1200 // 粒子剩下的時間 advancePosition: false // 退化是否影響位置、速度、和加速度 } //! [0] } } ~~~ 雪花圖太長,截一部分好了: ![](https://box.kancloud.cn/2016-01-18_569cbd02b2a6f.jpg) (2)Attractor 這個小例子使用Affector中的Attractor(吸引者)向我們展示了如何使用粒子系統模擬一個黑洞。 ![](https://box.kancloud.cn/2016-01-18_569cbd02c713c.jpg) 可以看到圖中心有一個“黑洞”,靠近黑洞的粒子會被改變運行軌跡,太近的粒子會被吸進去。如果需要我們自己來寫這種速度改變的代碼可能會相當繁瑣,好在QtQuick給我們提供了Attractor這個Affector,來看看它怎么使用的~attractor.qml ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { id: root width: 360 height: 540 color: "black" Image { source: "qrc:/images/finalfrontier.png" anchors.centerIn:parent } ParticleSystem { id: particles anchors.fill: parent Emitter { // 星星發射器 group: "stars" emitRate: 40 lifeSpan: 4000 enabled: true size: 30 sizeVariation: 10 velocity: PointDirection { x: 220; xVariation: 40 } height: parent.height // height定義了發射發射區域的高度,否則粒子從(0,0)發出 } Emitter { // 隕石發射器 group: "roids" emitRate: 10 lifeSpan: 4000 enabled: true size: 30 sizeVariation: 10 velocity: PointDirection { x: 220; xVariation: 40 } height: parent.height } ImageParticle { // 星星 id: stars groups: ["stars"] source: "qrc:///particleresources/star.png" color: "white" colorVariation: 0.5 alpha: 0 } ImageParticle { // 隕石 id: roids groups: ["roids"] sprites: Sprite { // 這里再次使用了幀動畫,由于沒有定義frameDurationVariation,所有隕石的旋轉速度都是相同的 id: spinState name: "spinning" source: "qrc:/images/meteor.png" frameCount: 35 frameDuration: 60 } } ImageParticle { // 飛船子彈 id: shot groups: ["shot"] source: "qrc:///particleresources/star.png" color: "#0FF06600" colorVariation: 0.3 } ImageParticle { // 尾氣 id: engine groups: ["engine"] source: "qrc:///particleresources/fuzzydot.png" color: "orange" SequentialAnimation on color { // 屬性動畫 loops: Animation.Infinite ColorAnimation { from: "red" to: "cyan" duration: 1000 } ColorAnimation { from: "cyan" to: "red" duration: 1000 } } colorVariation: 0.2 } //! [0] Attractor { // Affector家族中的一員,可以形成吸引其他粒子的效果 id: gs; pointX: root.width/2; pointY: root.height/2; strength: 4000000; // pointX,pointY是其作為目標點,同其他Affector一樣,設置其x,y,height,weidth改變的是其影響區域 affectedParameter: Attractor.Acceleration // 設置為影響加速度 proportionalToDistance: Attractor.InverseQuadratic // 影響效果與距離的比例關系 } //! [0] Age { // 在Attractor周圍再安裝一個Age,因為這里沒有設置lifeLeft,粒子進入該區域變消失了 x: gs.pointX - 8; // Age的影響區域 y: gs.pointY - 8; width: 16 height: 16 } Rectangle { // 用矩形畫圓的方法 color: "black" width: 8 height: 8 radius: 4 x: gs.pointX - 4 y: gs.pointY - 4 } Image { // 飛行器 source:"qrc:/images/rocket2.png" id: ship width: 45 height: 22 //Automatic movement SequentialAnimation on x { // 屬性動畫,這里使用了彈線軌跡 loops: -1 NumberAnimation{to: root.width-45; easing.type: Easing.InOutQuad; duration: 2000} NumberAnimation{to: 0; easing.type: Easing.OutInQuad; duration: 6000} } SequentialAnimation on y { loops: -1 NumberAnimation{to: root.height-22; easing.type: Easing.OutInQuad; duration: 6000} NumberAnimation{to: 0; easing.type: Easing.InOutQuad; duration: 2000} } } Emitter { // 尾氣粒子 group: "engine" emitRate: 200 lifeSpan: 1000 size: 10 endSize: 4 sizeVariation: 4 velocity: PointDirection { x: -128; xVariation: 32 } height: ship.height y: ship.y x: ship.x width: 20 } Emitter { // 子彈粒子 group: "shot" emitRate: 32 lifeSpan: 1000 enabled: true size: 40 velocity: PointDirection { x: 256; } x: ship.x + ship.width y: ship.y + ship.height/2 } } } ~~~ (3)Custom Affector 在這個例子中我們將了解到如何實現一個自定義的Affector,以及通過這個Affector實現落葉飄落的效果。當Affector的子類都不能滿足我們的需求的時候,這種方式就顯得尤為重要了。 ![](https://box.kancloud.cn/2016-01-18_569cbd02ebbdd.jpg) 直接上代碼,由于我會調試這些代碼因此其圖片的路徑被我改成了資源路徑,希望沒有影響到大家。customaffector.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Item { // 如果這個文件作為一個組件,Image作為根項目將使使用這個組件的人可以對其任意修改 width: 360 height: 600 Image { // 因此不推薦將Image作為根目錄,而是以Item作為替代,而嵌套Image source: "qrc:/images/backgroundLeaves.jpg" anchors.fill: parent } ParticleSystem { anchors.fill: parent Emitter { width: parent.width // 粒子出現的點為(0,0)到(360,0) emitRate: 4 lifeSpan: 14000 size: 80 velocity: PointDirection { y: 60 } // 初始速度 } Wander { // 一個系統自帶的Affector:Wander(漫步者),它可以用來提供隨機的粒子軌跡,這樣形成了左右晃動的葉子 anchors.fill: parent anchors.bottomMargin: 100 // 與設置Affector的height類似,確定Wander的影響區域 xVariance: 60 // x方向上的變化率 pace: 60 // 最大步長 } //! [0] Affector { // 基本的Affector類不會改變粒子任何屬性,但我們可以在合適的時候發出信號來做出相應的處理 property real coefficient: 0.1 // 自定義屬性“同步系數”和“速度” property real velocity: 1.5 width: parent.width height: parent.height - 100 // 底部100像素不再產生影響 onAffectParticles: { // 只要有粒子被該Affector影響,這個handler就被觸發。通過它我們可以定義自己的Affector行為。類似onEmitterParticles,由于使用了javaScript數組以及計算,我們同樣不推薦在包含大量粒子的系統中使用它。 //Linear movement // 這一段是在源碼中被注釋的,它提供了線性搖動的計算 // if (particle.r == 0) { // particle.r = Math.random() > 0.5 ? -1 : 1; // } else if (particle.r == 1) { // particle.rotation += velocity * dt; // 不知道這個dt是什么,只知道是一個比較小的小數... // if (particle.rotation >= maxAngle) // particle.r = -1; // } else if (particle.r == -1) { // particle.rotation -= velocity * dt; // if (particle.rotation <= -1 * maxAngle) // particle.r = 1; // } //Wobbly movement for (var i=0; i<particles.length; i++) { // 這是一個搖擺算法,相對上面的代碼而言更加精妙 var particle = particles[i]; if (particle.r == 0.0) { // 在QML中我們可以將參數定義與賦值放在一起 particle.r = Math.random() + 0.01; // 將 0.01 定義為particle.r的最小值 } particle.rotation += velocity * particle.r * dt; // 隨機的particle.r保證每片葉子的旋轉角度都是隨機的 particle.r -= particle.rotation * coefficient; // 然后這里通過“同步系數”適當改變particle.r,系數越大,葉片晃動越劇烈。根據QML屬性綁定的原則,當particle.r被改變,particle.rotation隨之改變。正向的旋轉角度使particle.r變小,導致particle.rotation變小,葉片方向旋轉,反之亦然,得到晃動效果 if (particle.r == 0.0) // 如果為0給其一個改變量 particle.r -= particle.rotation * 0.000001; particle.update = 1; } } } //! [0] //! [1] Affector { // 定義“地面”的摩擦減速效果 x: -60 width: parent.width + 120 height: 100 anchors.bottom: parent.bottom onAffectParticles: { for (var i=0; i<particles.length; i++) { var particle = particles[i]; var pseudoRand = (Math.floor(particle.t*1327) % 10) + 1; // Math.floor取到一個整數,并對10取余。葉子生命周期越長,這個數會越大,也就更容易被“減速” var yslow = dt * pseudoRand * 0.5 + 1; var xslow = dt * pseudoRand * 0.05 + 1; if (particle.vy < 1) // 速度低于 1 則停止 particle.vy = 0; else particle.vy = (particle.vy / yslow); // 否則除以摩擦系數 if (particle.vx < 1) particle.vx = 0; else particle.vx = (particle.vx / xslow); particle.update = true; } } } //! [1] ImageParticle { anchors.fill: parent id: particles sprites: [Sprite { // 將多個png賦予圖像粒子的方法 source: "qrc:/images/realLeaf1.png" frameCount: 1 frameDuration: 1 // 類似“導入者”,其生命周期很短,1ms后它將變成后面的圖像 to: {"a":1, "b":1, "c":1, "d":1} // 有1/4的概率變成"a",1/4的概率變成"b"...后面類似 }, Sprite { // 當該圖像沒有可轉變的內容,它將重復播放自己 name: "a" source: "qrc:/images/realLeaf1.png" frameCount: 1 // 我們的單幀靜態圖也就是僅有一幀的連續圖 frameDuration: 10000 }, Sprite { name: "b" source: "qrc:/images/realLeaf2.png" frameCount: 1 frameDuration: 10000 }, Sprite { name: "c" source: "qrc:/images/realLeaf3.png" frameCount: 1 frameDuration: 10000 }, Sprite { name: "d" source: "qrc:/images/realLeaf4.png" frameCount: 1 frameDuration: 10000 } ] z:4 // 在圖像中的層次 } } } ~~~ (4)Friction 在上面的例子中我們看到了如何使用代碼來模擬一個摩擦效果,但是Qt Quick已經為我們提供了一個模擬摩擦效果的Affector,它就是Friction。 這個例子與上面的例子類似: ![](https://box.kancloud.cn/2016-01-18_569cbd032ca52.jpg) 代碼十分簡練。friction.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Item { width: 360 height: 600 Image { source: "qrc:/images/backgroundLeaves.jpg" anchors.fill: parent } ParticleSystem { anchors.fill: parent Emitter { width: parent.width emitRate: 4 lifeSpan: 14000 size: 80 velocity: PointDirection { y: 160; yVariation: 80; xVariation: 20 } // xVariation給了葉子水平方向上移動的能力,但是達不到wander的“擺動”效果 } ImageParticle { // 圖像粒子同上 anchors.fill: parent id: particles sprites: [Sprite { source: "qrc:/images/realLeaf1.png" frameCount: 1 frameDuration: 1 to: {"a":1, "b":1, "c":1, "d":1} }, Sprite { name: "a" source: "qrc:/images/realLeaf1.png" frameCount: 1 frameDuration: 10000 }, Sprite { name: "b" source: "qrc:/images/realLeaf2.png" frameCount: 1 frameDuration: 10000 }, Sprite { name: "c" source: "qrc:/images/realLeaf3.png" frameCount: 1 frameDuration: 10000 }, Sprite { name: "d" source: "qrc:/images/realLeaf4.png" frameCount: 1 frameDuration: 10000 } ] width: 100 height: 100 x: 20 y: 20 z:4 } //! [0] Friction { // Friction為粒子帶來摩擦效果,我們可以設置一個閾值,使Friction只影響速度大于該閾值的粒子。該閾值默認為0 anchors.fill: parent anchors.margins: -40 factor: 0.4 // 摩擦系數,值越大摩擦力越大 } //! [0] } } ~~~ (5)Gravity 類似的,除了摩擦力,我們還有一個Affector用來模擬萬有引力。它展示了葉片向地面加速飄落的效果。 ![](https://box.kancloud.cn/2016-01-18_569cbd035ecbf.jpg) 圖中的綠色是"地面",可以拖動它360度旋轉,葉片始終向“地面”的中心加速下落。gravity.aml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Item { id: window width: 320; height: 480 Rectangle { id: sky anchors.fill: parent // 藍色的背景覆蓋了整個矩形范圍 gradient: Gradient { GradientStop { position: 0.0 color: "DeepSkyBlue" } GradientStop { position: 1.0 color: "SkyBlue" } } } Rectangle { // 因為在后面要實現“地面”的旋轉,所以設置了較大的尺寸 id: ground width: parent.height * 2 height: parent.height y: parent.height/2 x: parent.width/2 - parent.height transformOrigin: Item.Top // 用來設置旋轉和縮放的中心點 rotation: 0 gradient: Gradient { GradientStop { position: 0.0; color: "ForestGreen"; } GradientStop { position: 1.0; color: "white"; } } } MouseArea { anchors.fill: parent onPositionChanged: { // 該信號在鼠標按下并移動位置時放出,如果不需要按下鼠標,可設置hoverEnabled為true var rot = Math.atan2(mouseY - window.height/2,mouseX - window.width/2) * 180/Math.PI; // 返回當前鼠標方向矢量與X 軸正方向的夾角 ground.rotation = rot; // 以該角度旋轉 } } ParticleSystem { id: sys } //! [0] Gravity { // 當使用Gravity時,要注意它對整個場景的吸引力都是相同的,如果角度和加速度恒定,最好直接在Emitter中設置 system: sys // 但在此例中如果直接設置Emitter,角度的計算會比較復雜 magnitude: 32 // 強度 angle: ground.rotation + 90 // 運動方向 } //! [0] Emitter { system: sys anchors.centerIn: parent emitRate: 1 lifeSpan: 10000 size: 64 } ImageParticle { anchors.fill: parent system: sys source: "qrc:/images/realLeaf1.png" } } ~~~ (6)GroupGoal 在前面我們學習到我們可以設置ImageParticle的groups屬性,從而讓不同的Emitter發送不同的粒子。更進一步,使用ParticleGroup和GroupGoal可以實現粒子在特定狀態下的跳變。 ![](https://box.kancloud.cn/2016-01-18_569cbd0370afe.jpg) 可以看到,這些紅色的小光點在經過藍色火焰后被點燃成火苗,同時被鼠標滑過的也將被點燃。界面的右上角還有個數字用來記錄被點燃的火苗數。 代碼如下,groupgoal.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { id: root width: 360 height: 600 color: "black" property int score: 0 // 設置一個屬性用來記錄分數 Text { color: "white" anchors.right: parent.right text: score } ParticleSystem { id: particles anchors.fill: parent // ![unlit] ParticleGroup { // 這個元素有點類似狀態機的概念,它將一種狀態下的粒子群以打包的形式放在一起,然后通過name跳轉 name: "unlit" duration: 1000 // 1s后進入下一個狀態 to: {"lighting":1, "unlit":99} // 設置百分之一的光球可以自燃 ImageParticle { source: "qrc:/images/particleA.png" // 資源文件中的一個光點,有點類似常用的glowdot,但是更大一些 colorVariation: 0.1 color: "#2060160f" // 光點的顏色為紅褐色 } GroupGoal { // 繼承自Affector,提供特定條件滿足下的狀態跳轉 whenCollidingWith: ["lit"] // 當碰撞到正在燃燒的火苗時 goalState: "lighting" // 跳轉為"lighting"狀態 jump: true // 設置為立刻跳轉 } } // ![unlit] // ![lighting] ParticleGroup { // 一個過渡狀態,正在被點亮的狀態 name: "lighting" duration: 100 // 0.1秒后跳轉到"lit" to: {"lit":1} } // ![lighting] // ![lit] ParticleGroup { // 被點亮狀態 name: "lit" duration: 10000 // 終態粒子的生命周期 onEntered: score++; // 分數加一 TrailEmitter { // 使用TrailEmitter構建尾部火焰 id: fireballFlame group: "flame" // 粒子"flame"是基于下方定義的ImageParticle emitRatePerParticle: 48 // 每個lit后跟隨48玫"火焰" lifeSpan: 200 // 生命周期與焰尾長度成正比 emitWidth: 8 emitHeight: 8 size: 24 sizeVariation: 8 endSize: 4 // 尾部體積更小 } TrailEmitter { // 另一個TrailEmitter用來構建煙霧 id: fireballSmoke group: "smoke" // smoke在下方定義 // ![lit] emitRatePerParticle: 120 lifeSpan: 2000 // 較長的生命周期用來進行自己的動畫 emitWidth: 16 emitHeight: 16 velocity: PointDirection {yVariation: 16; xVariation: 16} acceleration: PointDirection {y: -16} // 煙霧首先向下運動,隨之向上升騰 size: 24 sizeVariation: 8 endSize: 8 } } ImageParticle { // 灰色煙霧粒子 id: smoke anchors.fill: parent groups: ["smoke"] source: "qrc:///particleresources/glowdot.png" colorVariation: 0 color: "#00111111" } ImageParticle { // 藍色閆焰苗粒子 id: pilot anchors.fill: parent groups: ["pilot"] source: "qrc:///particleresources/glowdot.png" redVariation: 0.01 blueVariation: 0.4 // 設置RGB中藍色的變化率 color: "#0010004f" } ImageParticle { // 紅色火焰粒子 id: flame anchors.fill: parent groups: ["flame", "lit", "lighting"] source: "qrc:/images/particleA.png" colorVariation: 0.1 color: "#00ff400f" } Emitter { // 用來發射易燃小球 height: parent.height/2 emitRate: 4 lifeSpan: 4000//TODO: Infinite & kill zone // demo中的注釋,TODO表示還要做的事,FIXME表示代碼待修改,XXX表示有待商榷 size: 24 sizeVariation: 4 velocity: PointDirection {x:120; xVariation: 80; yVariation: 50} acceleration: PointDirection {y:120} group: "unlit" } Emitter { // 用來構建焰苗 id: flamer x: 100 y: 300 group: "pilot" emitRate: 80 lifeSpan: 600 size: 24 sizeVariation: 2 endSize: 0 velocity: PointDirection { y:-100; yVariation: 4; xVariation: 4 } // 粒子向上移動形成焰苗的升騰感 // ![groupgoal-pilot] GroupGoal { groups: ["unlit"] // 設置被影響的粒子群 goalState: "lit" jump: true // 直接跳轉,否則默認為過渡時間結束后再跳轉 system: particles x: -15 y: -55 height: 75 width: 30 shape: MaskShape {source: "qrc:/images/matchmask.png"} // 這張圖片是一個焰苗的圖形,使用它可以使Affector影響一個非矩形區域 } // ![groupgoal-pilot] } // ![groupgoal-ma] //Click to enflame GroupGoal { groups: ["unlit"] // 設置其可以影響的粒子群 goalState: "lighting" // 目標狀態 jump: true enabled: ma.pressed // 按下事件使能 width: 18 // 作用區域 height: 18 x: ma.mouseX - width/2 y: ma.mouseY - height/2 } // ![groupgoal-ma] MouseArea { id: ma anchors.fill: parent } } } ~~~ (7)Move 這個例子展示了直接使用Affector影響粒子運動(位置、速度、加速度)的方法。 ![](https://box.kancloud.cn/2016-01-18_569cbd0387fc5.jpg) 代碼很簡單,我們大致看一下好了,move.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { width: 360 height: 540 color: "black" ParticleSystem { // 第一束紅色粒子 anchors.fill: parent ImageParticle { groups: ["A"] anchors.fill: parent source: "qrc:///particleresources/star.png" color:"#FF1010" redVariation: 0.8 // 形成"明紅"到"暗紅"的顏色差異 } Emitter { group: "A" emitRate: 100 lifeSpan: 2800 size: 32 sizeVariation: 8 velocity: PointDirection{ x: 66; xVariation: 20 } width: 80 // 產生粒子的區域是(0,0)到(80,80)的矩形范圍 height: 80 } //! [A] Affector { groups: ["A"] // Affector作用于A x: 120 // 影響區域 width: 80 height: 80 once: true position: PointDirection { x: 120; } // x 增加120 } //! [A] ImageParticle { // 第二束綠色粒子 groups: ["B"] anchors.fill: parent source: "qrc:///particleresources/star.png" color:"#10FF10" greenVariation: 0.8 } Emitter { group: "B" emitRate: 100 lifeSpan: 2800 size: 32 sizeVariation: 8 velocity: PointDirection{ x: 240; xVariation: 60 } y: 260 width: 10 height: 10 } //! [B] Affector { groups: ["B"] x: 120 y: 240 width: 80 height: 80 once: true velocity: AngleDirection { angleVariation:360; magnitude: 72 } // 角度變化范圍和強度 } //! [B] ImageParticle { // 第三束藍色粒子 groups: ["C"] anchors.fill: parent source: "qrc:///particleresources/star.png" color:"#1010FF" blueVariation: 0.8 } Emitter { group: "C" y: 400 emitRate: 100 lifeSpan: 2800 size: 32 sizeVariation: 8 velocity: PointDirection{ x: 80; xVariation: 10 } acceleration: PointDirection { y: 10; x: 20; } width: 80 height: 80 } //! [C] Affector { groups: ["C"] x: 120 y: 400 width: 80 height: 120 once: true relative: false acceleration: PointDirection { y: -80; } // 在y方向的加速度下降80 } //! [C] } } ~~~ (8)SpriteGoal 這個例子向我們展示了如何對使用sprites的ImageParticle做特殊的處理,使其在我們想要它改變時進行狀態的跳轉。 如圖是“星際迷航”中的飛船,它將撞毀其接觸到的隕石。 ![](https://box.kancloud.cn/2016-01-18_569cbd03a6c04.jpg) spritegoal.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Item { id: root width: 360 height: 540 MouseArea { id: ma anchors.fill: parent } ParticleSystem { id: sys } Image { source: "qrc:/images/finalfrontier.png" // 星際迷航 transformOrigin: Item.Center // 以中心點旋轉,一共有9個點可選,四個邊角,四個邊線中心,以及中心點 anchors.centerIn: parent NumberAnimation on rotation { // 背景緩慢旋轉 from: 0 to: 360 duration: 200000 loops: Animation.Infinite } } ImageParticle { // 星星粒子 system: sys groups: ["starfield"] source: "qrc:///particleresources/star.png" colorVariation: 0.3 color: "white" } Emitter { id: starField system: sys group: "starfield" emitRate: 80 lifeSpan: 2500 anchors.centerIn: parent //acceleration: AngleDirection {angleVariation: 360; magnitude: 200}//Is this a better effect, more consistent velocity? acceleration: PointDirection { xVariation: 200; yVariation: 200; } // 上面是源碼中的注釋,作者留給我們一個問題,這個從中心點向外散射的粒子,是使用AngleDirection還是PointDirection?筆者想了下,以第一行代碼發射的話,所有粒子的速度都將是相同的,而第二行代碼則具有更大的隨機性。以星星的散射而言,第二行代碼更合理。 size: 0 endSize: 80 sizeVariation: 10 } Emitter { // 隕石的發射器 system: sys group: "meteor" emitRate: 12 lifeSpan: 5000 acceleration: PointDirection { xVariation: 80; yVariation: 80; } // 與星星的發射類似 size: 15 endSize: 300 // 增大的endSize形成由遠及進感 anchors.centerIn: parent } ImageParticle { // 隕石粒子,由sprites的多幀圖像構成 system: sys groups: ["meteor"] sprites:[Sprite { id: spinState // 自旋隕石 name: "spinning" source: "qrc:/images/meteor.png" frameCount: 35 frameDuration: 40 randomStart: true // 從隨意的一幀開始 to: {"explode":0, "spinning":1} // 由于"explode"為0,因此spinning實際上是無限循環。"explode": 0可以不寫。但為了邏輯清楚,加上更好 },Sprite { // 碎裂隕石 name: "explode" source: "qrc:/images/_explo.png" frameCount: 22 frameDuration: 40 to: {"nullFrame":1} // 去到一個空白圖像 },Sprite {//Not sure if this is needed, but seemed easiest // 作者稱不確定這個空白圖像是否需要,但是帶上它似乎更好 name: "nullFrame" source: "qrc:/images/nullRock.png" frameCount: 1 frameDuration: 1000 } ] } //! [0] SpriteGoal { // 這就是Affector中的SpriteGoal了 groups: ["meteor"] // 與groupGoal不同,GroupGoal影響的ParticleGroup,而SpriteGoal影響的是這里使用Sprites的粒子 system: sys goalState: "explode" // 目標狀態 jump: true // 立刻跳轉 anchors.fill: rocketShip // 作用范圍跟隨飛船 width: 60 height: 60 } //! [0] Image { // 企業號飛船,因為要使飛船繞一個固定的中心點旋轉,坐標與旋轉的計算全部放在Image中比較麻煩,我們可以使用兩個Item來進行邏輯上的圓周計算 id: rocketShip source: "qrc:/images/rocket.png" anchors.centerIn: holder rotation: (circle.percent+0.25) * 360 // 隨著所在圓周位置的不同對自身進行旋轉。由于原圖飛船是向上的,因此將其初始旋轉90度 z: 2 } Item { // 通過下面的圓心和連續變化的百分比,這個Item用來得到實際的坐標 id: holder x: circle.x - Math.sin(circle.percent * 6.28316530714)*200 // 百分比乘以2π,200為半徑 y: circle.y + Math.cos(circle.percent * 6.28316530714)*200 z: 1 } Item { id: circle x: root.width / 1.2 // 圓心的位置 y: root.height / 1.7 property real percent: 0 // 定義一個百分比屬性 SequentialAnimation on percent { // 4秒的1到0循環 id: circleAnim1 loops: Animation.Infinite running: true NumberAnimation { duration: 4000 from: 1 to: 0 } } } ImageParticle { // 飛船的尾氣粒子 z:0 // 其z值比飛船小,這樣這些粒子不會覆蓋在飛船上面 system: sys groups: ["exhaust"] source: "qrc:///particleresources/fuzzydot.png" color: "orange" SequentialAnimation on color { loops: Animation.Infinite ColorAnimation { from: "red" to: "cyan" duration: 1000 } ColorAnimation { from: "cyan" to: "red" duration: 1000 } } colorVariation: 0.2 } Emitter { // 噴氣粒子發射器 id: trailsNormal2 system: sys group: "exhaust" emitRate: 300 lifeSpan: 500 y: holder.y x: holder.x velocity: PointDirection { xVariation: 40; yVariation: 40; } velocityFromMovement: 16 acceleration: PointDirection { xVariation: 10; yVariation: 10; } size: 4 sizeVariation: 4 } } ~~~ (9)Turbulence 在上篇博文的最后一個小例子——飛翔的火焰 中我們其實已經接觸到了Turbulence,它用來為粒子提供一個氣流的效果。在這個例子中我們可以更清晰地看到它的用法。 可以看到Turbulence為火苗和煙霧帶來的效果: ![](https://box.kancloud.cn/2016-01-18_569cbd03ca434.jpg) Turbulence.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { width: 320 height: 480 color: "#222222" id: root Image { source: "qrc:/images/candle.png" // 一根空白的蠟燭 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.bottomMargin: -60 // 這張圖下面有一段空白 anchors.horizontalCenterOffset: 2 // 水平中心向右平移2個像素 } ParticleSystem { anchors.fill: parent MouseArea { // 點擊后關閉/打開Turbulence效果 anchors.fill: parent onClicked: turb.enabled = !turb.enabled } //! [0] Turbulence { id: turb enabled: true height: (parent.height / 2) - 4 width: parent.width x: parent. width / 4 anchors.fill: parent strength: 32 // 可以為strength添加一個NumberAnimation,然后通過設置Easing,可以達到更逼近現實的氣流效果 NumberAnimation on strength{from: 16; to: 64; easing.type: Easing.InOutBounce; duration: 1800; loops: -1} } //! [0] ImageParticle { // 煙霧 groups: ["smoke"] source: "qrc:///particleresources/glowdot.png" color: "#11111111" colorVariation: 0 } ImageParticle { // 火苗 groups: ["flame"] source: "qrc:///particleresources/glowdot.png" color: "#11ff400f" colorVariation: 0.1 } Emitter { // 火苗粒子由窗口中心發出 anchors.centerIn: parent group: "flame" emitRate: 120 lifeSpan: 1200 size: 20 endSize: 10 sizeVariation: 10 acceleration: PointDirection { y: -40 } velocity: AngleDirection { angle: 270; magnitude: 20; angleVariation: 22; magnitudeVariation: 5 } } TrailEmitter { id: smoke1 width: root.width height: root.height/2 group: "smoke" follow: "flame" emitRatePerParticle: 1 lifeSpan: 2400 lifeSpanVariation: 400 size: 16 endSize: 8 sizeVariation: 8 acceleration: PointDirection { y: -40 } velocity: AngleDirection { angle: 270; magnitude: 40; angleVariation: 22; magnitudeVariation: 5 } } TrailEmitter { // 第二個TrailEmitter用來在更高一點的地方釋放出更濃郁的煙霧 id: smoke2 width: root.width height: root.height/2 - 20 group: "smoke" follow: "flame" emitRatePerParticle: 4 lifeSpan: 2400 size: 36 endSize: 24 sizeVariation: 12 acceleration: PointDirection { y: -40 } velocity: AngleDirection { angle: 270; magnitude: 40; angleVariation: 22; magnitudeVariation: 5 } } } } ~~~ (10)Wander 同樣我們在本文第三個小例子中已經接觸過wander了,在那我們使用wander為落葉添加了搖擺的飄落效果。在這個例子中我們將了解到,除了速度,wander還可以進一步作用于位置和加速度。 ![](https://box.kancloud.cn/2016-01-18_569cbd03dd66d.jpg) 可以看到在飄落的雪花背景中,有三個按鈕分別用來選擇位置,速度,以及加速度。通過點擊這些按鈕,可以改變這些雪花在x方向上的不同運動效果。這些按鈕是在另一個Qml文件中定義的,代碼比較簡單,貼在下面,就不一句句介紹了。 GreyButton.qml: ~~~ import QtQuick 2.0 Item { id: container property string text: "Button" property string subText: "" signal clicked width: buttonLabel.width + 20; height: col.height + 12 MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked(); onPressed: background.color = Qt.darker("lightgrey"); onReleased: background.color="lightgrey"; } Rectangle { id: background anchors.fill: parent color: "lightgrey" radius: 4 border.width: 1 border.color: Qt.darker(color) } Column { spacing: 2 id: col x: 10 y: 6 Text { id: buttonLabel; text: container.text; color: "black"; font.pixelSize: 24 } Text { id: buttonLabel2; text: container.subText; color: "black"; font.pixelSize: 12 } } } ~~~ wander.qml: ~~~ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { width: 360 height: 540 ParticleSystem { id: particles } ImageParticle { // 雪花粒子 system: particles sprites: Sprite { name: "snow" source: "../../images/snowflake.png" frameCount: 51 frameDuration: 40 frameDurationVariation: 8 } } //! [0] Wander { // wander id: wanderer system: particles anchors.fill: parent xVariance: 360/(wanderer.affectedParameter+1); // xVariance與pace必須都定義,由于沒有定義yVariance因此不會影響y方向的運動 pace: 100*(wanderer.affectedParameter+1); // 這里wanderer.affectedParameter實際等于0,不太懂這里的意思 } //! [0] Emitter { system: particles emitRate: 20 lifeSpan: 7000 velocity: PointDirection { y:80; yVariation: 40; } acceleration: PointDirection { y: 4 } size: 20 sizeVariation: 10 width: parent.width height: 100 } Row { // 這里使用了一個布局器 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter spacing: 4 GreyButton { text:"dx/dt" onClicked: wanderer.affectedParameter = Wander.Position; // 點擊改變Wander的影響屬性 } GreyButton { text:"dv/dt" onClicked: wanderer.affectedParameter = Wander.Velocity; } GreyButton { text:"da/dt" onClicked: wanderer.affectedParameter = Wander.Acceleration; } } } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看