この記事はアドカレに参加しています。
luaでパーティクルもどきを作る
半年前の文章のコピペです。
過去の僕は文章が綺麗ですね。
完成品も半年前のものです。
<はじめに>
学校の課題でパーティクルもどきを作ったので、それの紹介みたいなかんじです。
パーティクルについてしっかりと学びたい場合は「パーティクルシステム」とかで調べると面白い記事がでてきたりします。
<コンセプト>
・基準となる円が一つあり、その円から粒子がででくる。
・基準となる円も粒子も「速度」と「角度」があり、それをもとに移動する。
・粒子は時間経過で大きさが小さくなる。大きさが0以下になったら描画されない。
・粒子は時間経過で速度が減速する。
・基準となる円も、粒子も領域外には出られないようにする。
・粒子は1フレームで3つででくる。
・粒子の最大寿命は90フレームにして、最大で270の粒子が存在が存在するようにする。
<コード>
--初期化プログラム
if(obj.time==0)then
--初期化
local p={}
p.x={}
p.y={}
p.s={}
p.spd={}
p.arg={}
p.r=0
--初期値を決定
p.x[1]=100
p.y[1]=100
p.s[1]=20
p.spd[1]=10
p.arg[1]=math.rad(30)
for i=2,271 do
p.x[i]=0
p.y[i]=0
p.s[i]=0
p.spd[i]=0
p.arg[i]=0
end
--グロ変数に流す
Pdata=p
end
--乱数のseed値用の関数
function R()
Pdata.r=Pdata.r+1
return Pdata.r
end
--Pdataの値を更新
function pa(p)
--粒子を増やす
local index=rand(0,90,R())*3+2
for i=0,2 do
p.x[index]=p.x[1]
p.y[index]=p.y[1]
p.s[index]=rand(0,10,R())
p.spd[index]=p.spd[1]-rand(0,10,R())
if(p.spd[index]<0)then p.spd[index]=0 end
p.arg[index]=p.arg[1]+rand(-30,30,R())/0.3
index=index+1
end
--速度の減速とサイズを小さく
for i=2,271 do
p.s[i]=p.s[i]-(p.s[1]/90)
p.spd[i]=p.spd[i]-(p.spd[1]/90)
end
--座標の決定
for i=1,271 do
--壁との衝突判定
if(p.x[i]<=19 or p.x[i]>=380)then
p.arg[i]=math.pi-p.arg[i] end
if(p.y[i]<=19 or p.y[i]>=380)then
p.arg[i]=-1*p.arg[i] end
--移動量を計算
local dx,dy
dx=p.spd[i]*math.cos(p.arg[i])
dy=p.spd[i]*math.sin(p.arg[i])
--移動量を加算
p.x[i]=p.x[i]+dx
p.y[i]=p.y[i]+dy
--範囲外に出ないように
if(p.x[i]<19)then p.x[i]=19
elseif(p.x[i]>380)then p.x[i]=380 end
if(p.y[i]<19)then p.y[i]=19
elseif(p.y[i]>380)then p.y[i]=380 end
end
end
--関数実行と描画
pa(Pdata)
local p=Pdata
for i=1,271 do
if(p.s[i]>0)then
obj.load("figure","円",0xffff00,p.s[i])
obj.draw(p.x[i],p.y[i])
end
end
<全体のながれ>
1,グローバル変数の準備
2,粒子を増やしたり、座標を決める関数を作る
3,関数を実行して描画
4,次フレームに移動したら、3のみを行う
<補足>
解説はコメントに書いてあるので、コメントにない補足を書いときます。
・グローバル変数
今回の場合は最大で270の粒子が飛ぶようにします。
なので、粒子の数+基準となる円で、合計271のindexを持つ配列を作ればいいことになります。
・粒子の増やし方
同時に存在する粒子の最大数は270(基準となる円も含めると271)なので、描画する際には
for i=1,271 do
if(p.s[i]>0)then
obj.load("figure","円",0xffff00,p.s[i])
obj.draw(p.x[i],p.y[i])
end
end
のようにindexが1~271のものを順番にif文で判定していきます。
p.s[i]というのは、描画する際のサイズなので、サイズが0より小さいものは描画されないことになります。
p.s[i]が0より大きいものは描画され、p.s[i]が0以下のものは描画されません。
粒子を増やすには、これを利用します。
粒子を増やしたい場合は、p.s[i]が0以下のものを0よりも大きい数にすればいいことになります。
・粒子の減らし方
粒子を減らすには、p.s[i]の値が0より大きいものを0以下にすればいいことになります。
<おわりに>
rikkyさんのパーティクルスクリプトはすごいですね。
<反省>
分かりずらいコードになったかもしれないと反省。
しかも、限定的な使い方しかできないコードですし、右から左へ順番にフレームを読み込まないといけないのでaviutl向きではないという…