日本語プログラミング言語Mind９βのキャンバス大量図形移動 遅延イベントで実装してみる

# はじめに
日本語プログラミング言語Mindの開発元@killyさんの御厚意により日本語プログラミング言語Mindのバージョン９βをご提供いただいておりまして、新機能であるキャンバスのグラフィックス機能についてなにかやってみることにしましたの続きです。

今回はMind９βのキャンバス上の図形を移動させる処理を遅延イベントで実装してみました。

# 前提条件
Windows11 Pro 22H2 22621.4169
mind version9-BETA-6　

# 遅延イベントとは

https://qiita.com/mylifewithviolin/items/565e61987a0fbaaa6abe#comment-cbb94119d633681da585

こちらの記事の@killyさんのコメントの引用

>「遅延実行を予約」を繰り返すものは構文上はループの形をとらず、一連の処理を一筆書きでも書けない（イベント処理に分散するため）ので抵抗があるかもしれませんが確実に動作する安心感はあります。

だいじょうぶです。抵抗感はまったくございません:joy:

## メイン処理の構造
まず、メインは下記のようになります。「次の遅延実行を予約する」でイベントを設定しています。これはまだ予約語レベルではなく、アプリケーション側の定義単語です。この後、順を追ってご説明いたします。

```mind:snowfall3.src
キャンバスは　ＩＤ。
キャンパス幅は　定数　８００。
キャンパス高は　定数　４００。

メインは
    メインウィンドウと　キャンパス幅と　キャンパス高と　黒色で
　　　　　　　　　　　　　　キャンバスを立て　キャンバスに　入れ

    雪の降る様子を描き  次の遅延実行を予約する。
```

## 次の遅延実行を予約
「次の遅延実行を予約する」まわりは下記のような記述となります。「雪の描く位置を更新」が賞味の描画処理でその内容はこの後ご説明いたします。

下記のコードでは「雪の描く位置を更新」を予約語「遅延実行を予約」で遅延実行を設定しているのですが、1回その実行が処理された際に、また同じ遅延実行を設定する必要があります。

```mind:snowfall3.src
遅延後の雪描画とは　仮定義。

次の遅延実行を予約とは
    １００ミリと
    遅延後の雪描画の　実行情報と　空列で　遅延実行を予約。
        
遅延後の雪描画とは　本定義　（引数１、引数２、・・、引数個数　→　・）
    イベント引数を捨て
    雪の描く位置を更新し
    次の遅延実行を予約すること。　
```
そのため、「遅延後の雪描画」を仮定義しておいてそれを「遅延実行を予約」する単語を「次の遅延実行を予約する」として定義し、その後の「遅延後の雪描画」の本定義の中で「雪の描く位置を更新」を実行してから、「次の遅延実行を予約する」を呼びだすことで一定時間後に同じ処理を繰り返し呼び出すようにしています。

## 雪の描く位置を更新
こちらが遅延イベント処理で呼び出す内容となります。Mind９の図形の移動で実装しています。

```mind:snowfall3.src
雪片を少し揺らすとは
        Xは　小数変数
    -2を　小数化し　一様乱数()を　f掛けて   Xに　入れ
    Xを　整数化。

雪の描く位置を更新するとは
        Xは　変数
        Yは　変数
        Rは　変数

    雪の数で　回数指定し
        Y座標（回数）に　速度（回数）を　加え　Yに　入れる
        Yが　キャンパス高　以下
        ならば
            Yを　Y座標（回数）に　入れる
            雪片を少し揺らし　xに　入れる
            円ＩＤ（回数）を　xと　速度（回数）で　図形を移動し
        さもなければ
            キャンパス幅で　雪片初期化値を返し
            速度（回数）に　入れ
            Rに　入れ
            Y座標（回数）に　入れ
            xに　入れる
            Y座標（回数）から　キャンパス高を　引き　Yに　入れ　
            円ＩＤ（回数）を　xと　Yで　図形を移動し
        つぎへ
    繰り返す。
```

## 雪の降る様子を描く
メインの中で一回だけ呼ばれる「雪の降る様子を描く」では、雪片構造体を初期化して一回「描画」するを初期化ループの中で実行しています。

雪の数は今回１０００としておりますが、図形ＩＤの配列に座標セットと同時にその値で「描画」を実行してしまうことが内部で保持しているリソースを解放することになります。このあたりは@killyさんと９βレビュアーの@ITvisionさんのご協力でクリアされました。そのため単語名も「全ての雪片を初期化して雪片を描く」に改めています。

```mind:snowfall3.src
雪の数は　      定数　１０００。


雪片は　構造体
        円ＩＤは	図形ＩＤ
        Y座標は　変数
        速度は　変数
    雪片本体は　円ＩＤと　Y座標と　速度
    全体は　雪の数の　雪片本体。

雪片初期化値を返すとは　　（変数　→　変数、変数、変数、変数）
        Xは　小数変数
        Yは　小数変数
        Rは　小数変数
        Sは　小数変数
        キャンバスサイズ幅は　変数
    キャンバスサイズ幅に　入れ
    キャンバスサイズ幅に　小数化し　ガウス分布乱数(0.5,0.4)を　f掛けて   Xに　入れる
    200と　小数化し　ガウス分布乱数(0.5,0.4)を　f掛けて   Yに　入れる
    3と　小数化し　一様乱数()を　f掛けて   Rに　入れる
    2と　小数化し　ガウス分布乱数(0.8,0.3)を　f掛けて   Sに　入れる
    Sが 1.0より　ｆ以下　
    ならば 
        1.0を Sに　入れ
    つぎに
    Xを　整数化
    Yを　整数化
    Rを　整数化
    Sを　整数化。

全ての雪片を初期化して雪片を描くとは
        Xは　変数
        Rは　変数
    20170316を　乱数種値に　入れ
    雪の数で　回数指定し
        キャンパス幅で　雪片初期化値を返し
        速度（回数）に　入れ
        Rに　入れ
        Y座標（回数）に　入れ
        xに　入れ
        キャンバスと　Xと Y座標（回数）と Rで　円のＩＤを取得し　円ＩＤ（回数）に　入れ
        白色で	円ＩＤ（回数）に　満たす色を設定し
        円ＩＤ（回数）を　描画する
    繰り返す。


雪の降る様子を描くとは
    全ての雪片を初期化して雪片を描く。
```
乱数は引き続きQiitaユーザー@t-tkd3aさんの下記の記事のソースを利用させていただいております。Mind9の「評価した値」によるTcl乱数に機会があれば移行します。

https://qiita.com/t-tkd3a/items/460b6f42ea69051f1130

# お題のソースをMind9β6でビルド
無事に成功です！
```
C:\developments\vscode\mind9>mind snowfall3 guilib

日本語プログラミング言語 Ｍｉｎｄ Version 8.11 for Windows
          Copyright(C) 1985 Scripts Lab. Inc.
コンパイル中 .. 終了
Coping.. c:\mind9-beta\mind9-beta\bin\mindexw.exe --> snowfall3.exe
```

# 実行イメージ
では実行してみます。

![mind9snowfall3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/5803fde7-9047-20fc-80ca-d9d9fe3c8135.png)

雪の数も1000個になるとかなり迫力がでてきますね。GIFアニメですとわかりづらいかもですが、ぜひデスクトップで実行してみてください。CPU負荷も低いです。

![mind9snowfall3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/5d88b461-1baf-7c89-4c74-db7c1b187f45.gif)



# おわりに
いかがでしたでしょうか？なにかの参考になれば幸いです。まだほんのさわりの部分ですが、今年で生誕４０周年を迎える日本語プログラミング言語Mind、ついに新バージョンがベールをぬぎはじめます！

## 参考情報
<details><summary>ソースコード全文</summary>

```mind:snowfall3.src
"random.src"を　コンパイル。

キャンバスは　ＩＤ。
キャンパス幅は　定数　８００。
キャンパス高は　定数　４００。
雪の数は　      定数　１０００。


雪片は　構造体
        円ＩＤは	図形ＩＤ
        Y座標は　変数
        速度は　変数
    雪片本体は　円ＩＤと　Y座標と　速度
    全体は　雪の数の　雪片本体。

雪片初期化値を返すとは　　（変数　→　変数、変数、変数、変数）
        Xは　小数変数
        Yは　小数変数
        Rは　小数変数
        Sは　小数変数
        キャンバスサイズ幅は　変数
    キャンバスサイズ幅に　入れ
    キャンバスサイズ幅に　小数化し　ガウス分布乱数(0.5,0.4)を　f掛けて   Xに　入れる
    200と　小数化し　ガウス分布乱数(0.5,0.4)を　f掛けて   Yに　入れる
    3と　小数化し　一様乱数()を　f掛けて   Rに　入れる
    2と　小数化し　ガウス分布乱数(0.8,0.3)を　f掛けて   Sに　入れる
    Sが 1.0より　ｆ以下　
    ならば 
        1.0を Sに　入れ
    つぎに
    Xを　整数化
    Yを　整数化
    Rを　整数化
    Sを　整数化。



全ての雪片を初期化して雪片を描くとは
        Xは　変数
        Rは　変数
    20170316を　乱数種値に　入れ
    雪の数で　回数指定し
        キャンパス幅で　雪片初期化値を返し
        速度（回数）に　入れ
        Rに　入れ
        Y座標（回数）に　入れ
        xに　入れ
        キャンバスと　Xと Y座標（回数）と Rで　円のＩＤを取得し　円ＩＤ（回数）に　入れ
        白色で	円ＩＤ（回数）に　満たす色を設定し
        円ＩＤ（回数）を　描画する
    繰り返す。

雪片を少し揺らすとは
        Xは　小数変数
    -2を　小数化し　一様乱数()を　f掛けて   Xに　入れ
    Xを　整数化。

雪の描く位置を更新するとは
        Xは　変数
        Yは　変数
        Rは　変数

    雪の数で　回数指定し
        Y座標（回数）に　速度（回数）を　加え　Yに　入れる
        Yが　キャンパス高　以下
        ならば
            Yを　Y座標（回数）に　入れる
            雪片を少し揺らし　xに　入れる
            円ＩＤ（回数）を　xと　速度（回数）で　図形を移動し
        さもなければ
            キャンパス幅で　雪片初期化値を返し
            速度（回数）に　入れ
            Rに　入れ
            Y座標（回数）に　入れ
            xに　入れる
            Y座標（回数）から　キャンパス高を　引き　Yに　入れ　
            円ＩＤ（回数）を　xと　Yで　図形を移動し
        つぎへ
    繰り返す。

雪の降る様子を描くとは
    全ての雪片を初期化して雪片を描く。

遅延後の雪描画とは　仮定義。

次の遅延実行を予約とは
    １００ミリと
    遅延後の雪描画の　実行情報と　空列で　遅延実行を予約。
        
遅延後の雪描画とは　本定義　（引数１、引数２、・・、引数個数　→　・）
    イベント引数を捨て
    雪の描く位置を更新し
    次の遅延実行を予約すること。　

メインは
    メインウィンドウと　キャンパス幅と　キャンパス高と　黒色で
　　　　　　　　　　　　　　キャンバスを立て　キャンバスに　入れ

    雪の降る様子を描き　
    次の遅延実行を予約する。
```

</details>