Jasmine Teaで時間計測!

この記事は、 [Jasmine Tea アドベントカレンダー 2023](https://qiita.com/advent-calendar/2023/jasminetea) の第21日目です。

# はじめに

[Jasmine Tea](https://jasminetea.app) (ジャスミンティー) は、プログラミングの楽しさを多くの人に知ってもらうために作られたプログラミング言語です。初心者が学びやすい仕組みで、実際に社会で使われている多くのプログラミング言語に応用できる基礎が身に付きます。

ここでは、Jasmine Teaを実際に開いて、時間を扱うプログラムを紹介していきます。

まず、Studio 画面を開いてください。もし Studio 画面をまだ開いたことがなければ、 [Studio画面を表示する - Jasmine TeaでHello, world!](https://qiita.com/yoichiro6642/items/3dc478726f4f73941b46#studio%E7%94%BB%E9%9D%A2%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B) を参考にして Jasmine Tea の試用を開始してください。

# 日時を表示してみよう

コンピューターには、時計が内蔵されています。インターネットに接続されていれば時間の補正も自動的に行われていて、正確な日時を教えてくれます。

Jasmine Tea では、[`datetime@` 関数](https://jasminetea.app/docs/references/function-datetime@) にて、現在時刻を入手することができます。さっそく、プログラムを書いてみましょう。Studio 画面の左にあるエディターに、以下のプログラムを入力してください。

```vb
now@=datetime@()
print now@
```

エディターの下にある青色の「実行」ボタンを押して、プログラムを実行してください。

![Screenshot_20231220_143351.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632303/cdd72786-ea18-bfe9-df71-3024f5a6494c.png)

`datetime@` 関数の戻り値を変数 `now@`（配列を代入する変数の名前は末尾に「@」記号を書きます）に代入しています。[`print` 命令](https://jasminetea.app/docs/references/command-print) を使って変数 `now@` に代入された配列を表示すると、以下のように各数値が入っていることがわかります。

* `[ 年, 月, 日, 時, 分, 秒, ミリ秒 ]`

上記のプログラムでは「実行したときの日時」しかわかりません。無限ループを使って、刻一刻と変化する現在日時を表示させてみましょう。エディターに入力されている内容を一旦全部消去して、以下のプログラムを入力してください。

```vb
do
  now@=datetime@()
  cls
  print now@  
loop
```

[`do` 命令](https://jasminetea.app/docs/references/command-do) と [`loop` 命令](https://jasminetea.app/docs/references/command-loop) を使うと、無限に繰り返すことができます。[`cls` 命令](https://jasminetea.app/docs/references/command-cls) にて画面を消去した後に現在日時を表示する、という処理を延々と繰り返しています。

実行してみましょう。「実行」ボタンを押してプログラムを実行してください。

![Peek 2023-12-20 14-40.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632303/21af1fe7-43f2-39f4-62f0-ed01ffaf0a7a.gif)

消去と表示を繰り返しているのでチカチカしてしまっていますが、これでシンプルな時計プログラムができました。しかし、見た目が良くないですね。時、分、秒のそれぞれの数を使って、アナログ時計を作ってみました。

```vb
do
  render 0
  cls
  now@=datetime@()
  circle (300,200),160,7
  sd=now@[5]*6-90
  md=now@[4]*6-90
  hd=now@[3]*30-90
  line (300,200)-(300+cos(sd)*150,200+sin(sd)*150),7
  line (300,200)-(300+cos(md)*130,200+sin(md)*130),7
  line (300,200)-(300+cos(hd)*100,200+sin(hd)*100),7
  render 1
loop
```

秒針と分針は 6 度ずつ、時針は 30 度ずつ移動させています。あとは、三角関数の [`sin` 関数](https://jasminetea.app/docs/references/function-sin) と [`cos` 関数](https://jasminetea.app/docs/references/function-cos) を使って各針の座標を求めています。

上記のプログラムを実行すると、以下のように動作します。

![Peek 2023-12-20 16-18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632303/d1bce6a9-8dfe-200e-55f3-2342e006eb72.gif)

# 一定時間ごとに何かしてみよう

ゲームやアニメーションでは、「一定時間ごとに何かする」ということが頻繁に行われます。例えば、以下のようなことです。

* 1 秒ごとに背景をスクロールさせる。
* 60 秒経過したら敵の数を増やす。
* 0.5 秒ごとに図形を回転させる。

`do` 命令と `loop` 命令の組み合わせで作り出す無限ループは、Jasmine Tea が動作しているコンピューターの性能に依存して、単位時間あたりの繰り返し回数は変わってきます。それに対して、上記のように「どのコンピューターでも同じ時間間隔で何かをする」ことによって、ゲームやアニメーションが安定した動作となります。

Jasmine Tea では、[`time` 関数](https://jasminetea.app/docs/references/function-time) が提供されています。`time` 関数は、プログラムが実行されてからの経過時間をミリ秒（1000分の1秒）単位で得ることができます。これを使って、プログラムが実行されているときに「一定時間経過したかどうか」をチェックすることができます。

具体的にはどうチェックすればよいか、見ていきましょう。ここでは、1 秒ごとに何か処理をしたいと仮定します。まずは、以下の図を見てください。

![Screenshot_20231221_124612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632303/db4d5ce6-2de8-6f63-aa22-4a1dd696ae62.png)

プログラムが実行された直後を 0 ミリ秒とします。プログラムの最初に、`time` 関数を呼び出して、その時点での経過時間を変数 `base_time` に代入しておきます。この変数に記憶された時間が、基準時間となります。

そして、メインループの繰り返しごとに、`time` 関数を呼び出して、基準時間で引き算します。例えば、基準時間が `100` だったとします。`time` 関数の戻り値が `1000` だったとすると、引き算の答えは `900` です。つまり、`900` ミリ秒だけ経過したことになります。1 秒は 1000 ミリ秒なので、まだ 1 秒経過していないことになります。この計算の答えが `1000` よりも大きくなったときに、1 秒経過したと判断できます。

では、この仕組みを使って、1 秒ごとに図形を横にスクロールさせるプログラムを作ってみましょう。Studio 画面のエディターに入力されているプログラムを全て消去した後に、以下のプログラムを入力してください。

```vb
circle (300,200),50,7,7
base_time=time()
do
  if time()-base_time>1000 then
    roll (0,0)-(639,399),8,0,-1
    base_time=time()
  end if
loop
```

[`circle` 命令](https://jasminetea.app/docs/references/command-circle) を使って画面の中央に白い円を描いたあとに、変数 `base_time` に `time` 関数の戻り値を代入しています。そして、 [`do` 命令](https://jasminetea.app/docs/references/command-do) と [`loop` 命令](https://jasminetea.app/docs/references/command-loop) でメインループを作っています。

メインループの中では、[`if` 命令](https://jasminetea.app/docs/references/command-if) を使って、 条件式 `time()-base_time>1000` が成立するかどうかチェックしています。成立したときは `if` 命令の次の行から実行されますので、[`roll` 命令](https://jasminetea.app/docs/references/command-roll) 命令を使って画面を右にスクロールします。そして、変数 `base_time` に `time` 関数の戻り値を代入して、基準時間を更新します。

では、実行してみましょう。「実行」ボタンを押して、プログラムを実行してください。

![Peek 2023-12-21 13-04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632303/f2a01760-8c0b-7a53-4b31-e6226d9d5b70.gif)

白い円が 1 秒ごとに移動しているのがわかります。`1000` という箇所を違う数字にして試してみてください。白い円の移動速度を変えることができます。

# 明日は何をつくるの？

今日は、Jasmine Tea にて日時を扱うための方法を紹介しました。明日は、再び @tmatsuo@github さんが、クリスマスにふさわしい何かを Jasmine Tea で作ってくれる予定です。