マイクラでカスタムパーティクルを作ったお話


マイクラコマンドアドベントカレンダー！？　おもしろそう！！！！
とりあえず1枠取った！！
せっかくの機会だし、これまで自分がやったことないことをやってみよう！
そこで、自作カスタムパーティクルの制作が頭に浮かびました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/0ce41c80-fdb3-d415-1bfb-65eae5d5dc7f.png)

ということでこの記事は、自分がマイクラで頑張ってカスタムパーティクルを作った、備忘録みたいなものになります

Qiitaは愚かPC文書すらまともに書いたことがない人による記事なので
寝る直前にコーヒーでも飲みながら読み流すように見やがれください☆☆☆(?)

※この記事の内容は、JE1.20.4で動かしています。

# どういう方法で作れるのか模索
外で描いたテクスチャをゲーム内に持ってきたいから、カスタムモデルデータかな...
先人のデータパックを見てみよう

![senjin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/b92fefd8-1f32-310d-e9fe-fc9494998b64.png)

カスタムフォント使ってそう(小並感)
なのでカスタムフォント使ってカスタムパーティクルを作ります

# リソースパックを作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/b517484c-0ddf-1e82-0395-d1f5adf50ca1.png)
まずはテクスチャを描いた
こんな感じのパーティクルを作りたいのです

そして、某M氏の動画を参考にしてカスタムフォントのリソースパックを作りました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/ff5a9523-fd8e-6f16-3a5a-d58305c36447.png)
↑テクスチャを文字コードに割り当ててるファイルの図

作ったリソースパックをマイクラに入れて下のコマンドを打つと...
```python
/summon minecraft:text_display ~ ~ ~ {text:'{"text":"\\uE000"}',background:0,billboard:center,brightness:{block:15,sky:15}}
/summon minecraft:text_display ~ ~ ~ {text:'{"text":"\\uE001"}',background:0,billboard:center,brightness:{block:15,sky:15}}
/summon minecraft:text_display ~ ~ ~ {text:'{"text":"\\uE002"}',background:0,billboard:center,brightness:{block:15,sky:15}}
/summon minecraft:text_display ~ ~ ~ {text:'{"text":"\\uE003"}',background:0,billboard:center,brightness:{block:15,sky:15}}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/cc1a8ebe-445f-21c4-1692-e19d54fa669e.png)



描いた画像がマイクラ内にテキストディスプレイとして反映されました～


「uE000」に一番左の画像を、「uE001」に左から2番目の画像を...
の要領で、UNICODEフォントに画像をむりやり上書きすることができました
これでリソースパックはかんせーい

# データパックを作る

次は、さっきのをコマ撮りの要領でアニメーションさせるシステムをコマンドで作ろうと思います

まずは、カスタムフォントを入れるためのテキストディスプレイを召喚します
```python:summon.mcfunction
summon minecraft:text_display ~ ~ ~ {Tags:[particle,slash],text:'{"text":"\\uE000"}',background:0,billboard:center,brightness:{block:15,sky:15}}
```

背景色を透明にして、明るさをMAXにして、「uE000」が入ってるテキストディスプレイです↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/d69c285c-ffe4-44d5-b799-ceeb479d5adf.png)

次は、これを1tickごとに次の画像に変えるシステムを作ります
これを実装するには、「今自分が何コマ目の画像を表示すればいいのか」を把握しなければならず、そのためにテキストディスプレイ自身が計測できる「タイマー」を用意してあげなきゃいけません
タイマーを実装する方法は、Storageを使うとかPortalCooldownを使うとかいろいろありますが、今回は「スコアボード」を使おうと思います

```python:reload.mcfunction
#データパックをリロードしたときに実行する
    scoreboard objectives add age dummy
```
↑タイマーのためのスコアボードを用意しました
「年齢」という意味の「age」と名付けます

```python:tick.mcfunction
#毎ティック実行する
    execute as @e[tag=particle] run scoreboard players add @s age 1
```
↑そして、このタイマーを毎ティック1増加させます
「execute as @e[tag=particle]」の部分で、さっきのテキストディスプレイを選択しています
スコアってプレイヤー以外のエンティティにもつけられるんですよね～

これで、毎ティック1増加するスコアが完成です
あとは、このタイマーの値に合わせてテキストディスプレイの画像を変更する処理を書きましょう

```python:.mcfunction
#タイマーをまだもらってない憐れなテキストディスプレイに対して初動のタイマーを授ける
    execute unless entity @s[scores={age=0..}] run scoreboard players set @s age 0

#タイマーが1のとき、2のとき、3のとき、に、テキストディスプレイの中身を書き換える
    execute if entity @s[scores={age=1}] run data modify entity @s text set value '{"text":"\\uE001"}'
    execute if entity @s[scores={age=2}] run data modify entity @s text set value '{"text":"\\uE002"}'
    execute if entity @s[scores={age=3}] run data modify entity @s text set value '{"text":"\\uE003"}'
#タイマーが4のとき、自分自身をkillする
    execute if entity @s[scores={age=4}] run kill @s
```
↑タイマーが進んだ時の処理
あとはこれを毎ティック実行させて...

```python:tick.mcfunction
#毎ティックタイマーの処理を実行する
    execute as @e[tag=slash] at @s run function particle:slash/
#毎ティックタイマーを1増やす
    execute as @e[tag=particle] run scoreboard players add @s age 1
```
できた。これでsummon.mcfunctionを実行させると...

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591846/57fe571d-beea-a0ec-81f5-04d5178257f4.gif)

完成！パーティクルがなめらかに表示される

---
テキストディスプレイを召喚
↓
タイマーが増える
↓
タイマーに応じて画像が変わる
↓
またタイマーが増える
↓
また画像が
...

---
の要領で自作パーティクルが表示される。
gifだから滑らかさが若干伝わりづらいのが残念...
おけ！カスタムパーティクルできた！これでおわり！！

# と思っていたのか？
まぁこれでおわりでもいいんですけどね、
作ってる途中に思った事があるんですよ
「**これだけだと何か物足りないなぁ**」 って。
このままだと他の人が作るパーティクルと何一つ変わらないんですよ
~~それは嫌~~なので、自分が「あったらいいな」という要素を自分で考えて、アイデンティティを足していきたいと思います
私が思うパーティクルに「あったらいいな」と思うことは、**『大きさの変更』**。
自在な大きさでパーティクルを出せたら便利だと思わない？
これからはそのシステムを実装します

# 最後のわるあがき
せっかくだし今回は最近出た「マクロ」を使ってみましょう
functionコマンドを打つときにオプションを加えることができる機能です(厳密には違うけどこんな認識)
今回は、「Size」という名前のオプションをつける体で書きます

```python:summon.mcfunction
#テキストディスプレイを召喚
summon minecraft:text_display ~ ~ ~ {Tags:[particle,slash,summoned],text:'{"text":"\\uE000"}',background:0,billboard:center,brightness:{block:15,sky:15}}

#「召喚された瞬間」のテキストディスプレイに、マクロで受け取った値をnbtに代入
$execute as @e[tag=summoned] run data modify entity @s transformation.scale set value [$(Size),$(Size),$(Size)]

#「召喚された瞬間」を認識するタグを剥奪
execute as @e[tag=summoned] run tag @s remove summoned
```
ドルマークから始まってる文がマクロ文です
[\\$(Size),\\$(Size),\\$(Size)] の部分が、
例えば5.0を代入すると、 [5.0,5.0,5.0]、
　　　10.0を代入すると、[10.0,10.0,10.0]
として扱われます
functionを実行するときにオプションで加えた好きな値をここで反映してくれる訳ですね

こうしてマクロのおかげでサイズを手軽に自由に変えられるようになったカスタムパーティクル、完成品がこちらになりまーす↓

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">サイズをマクロで自由に変更できる自作パーティクル <a href="https://t.co/8ChdPf997l">pic.twitter.com/8ChdPf997l</a></p>&mdash; ほりしゅ (@Twi_HollySyu) <a href="https://twitter.com/Twi_HollySyu/status/1730543524578504840?ref_src=twsrc%5Etfw">December 1, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

剣を相手に当てた時によく出そうな自作斬撃パーティクル、かんせい！！！

# おわりに
自作パーティクルなんて正直いくらでも作り方はあるしわざわざ記事にするまでもない事だったのかもしれないけど、挑戦したなら記事にしたいよねってことで書いてみました。
自分オリジナルの要素も思いついて実装できたからけっこう満足したね。
この記事が少しでも初心者中級者上級者の参考になれば幸いです。

...
あとこの記事が上がる日12/6は私の誕生日なのでぜひTwitterで祝えください 
Twitter → [@Twi_HollySyu](https://twitter.com/Twi_HollySyu)


## 参考
・某M氏の動画：(https://www.youtube.com/watch?v=w0Zraz-o8yE)


・ここまでわざわざ読んでくれた人のために今回のデタパ・リソパをダウンロードできるリンク：(https://github.com/HollySyu/CustomParticele-By-HollySyu/tree/main)