時間を扱う
今回はバージョン2講座の同じ章で同じ題の内容を扱いたいと思います。
"時"を操作するのですが、タイムマシンのように遡ったり、飛んだりはしませんし、
現段階では時間(システム日時)を設定することも行いません。
行う内容は、処理間隔を空けたり停止したり中断すること、時間(システム日時)を取得することだけです。
処理間隔を空けることから始めましょう。
まず、何を意味しているのかと言う説明からですが、
コレは主に、以前行ったループ時に使用するものです。
2、3秒程度、遅くても10秒程であろう下記スクリプトがあります。
 1
 2
 3
 4
	repeat 9999999 // 回数指定を外してはならない!
		i++
	loop
	mes "無限ループだとヤバイよ。"
メッセージが表示されるまでに表示されたウィンドウを動かそうとしたり、
HSP以外のウィンドウ操作を行おうとしても動作が遅かったり「応答なし」になります。
Windowsに標準で搭載されているタスクマネージャというモノを見たことがありますか?
「Ctrl+Alt+Delete」で何らかのアプリケーションを強制終了させる時に表示されるアレのことです。
そのタスクマネージャには、現時点のCPU使用率という情報を確認できるようになっていますが、
先ほどのスクリプトを実行(厳密にはメッセージが表示されるまでのループ)していると、
CPU使用率が100%のままになってしまうことが確認できるかと思います。
CPU使用率とは、その名の通り、CPU(タスク)を占有している割合のことで、
フルに使用している状態が続くと最悪の場合、PC利用者は操作不可能状態に陥ってしまいます。
つまり、実行中は「今、ループさせることに必至だから、ユーザーからの処理はちょっと待って」と
いう状態になってしまっているわけですね。
ループ回数が有限だからまだ良かったものの、
無限のまま放っておくと、CPUを酷使しすぎて危険な状態になりかねません。
例えば、ユーザーからの入力や操作待ちの為に無限にループさせる必要があったとしても、
このようなループではユーザーからの処理は受け付けてもらいにくくなる為に使い物になりませんね。
そこで必要になるのが、HSPプログラムを一定時間待たせる下記命令が必要になるのです。
wait 中断時間
中断時間処理を停止させる時間を10ミリ秒単位で指定する。
実行すると、指定数値×10ミリ秒(以下ms)間だけ処理を止めておく(ウェイトさせる)ことができます。
現在は、ユーザーからの操作を受け付ける命令群を紹介していないので
無限にループさせても、ユーザーからのループを抜けさせるイベントが発生しませんが、
イメージとしては下記の通りです。
 1
 2
 3
 4
 5
 6
	mes "終了させるには右上[×]を押してください。"
	repeat
		// ココに処理を抜けさせる条件を書いておく
		wait 3 // 30ms間止める
	loop
	mes "無限ループを脱出しました。"
上記スクリプトは、ループを抜ける条件がない為に、
ループ後のメッセージは表示されることがありませんが、あくまでイメージです。
タスクマネージャを見てみると、ループ中でも(HSPスクリプトの実行では)100%のままにはなりません。
ループ内で使用しましたが、ループ内での使用に限ったわけではありません。
 1
 2
 3
 4
 5
 6
 7
	mes "イクぞ〜!!!"
	wait 150 // 1500ms間止める
	repeat 3, 1
		mes cnt
		wait 100 // 1000ms間止める
	loop
	mes "ダァ〜!!!"
どこでどのように使おうが自由です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
	mes "むかーし、むかし…"
	wait 100
	mes "おじいさんとおばあさんが住んでいました…。"
	wait 200
	mes "おじいさんは、山にしばかれに、"
	wait 100
	mes "おばあさんは、川に選択されました…。"
	wait 200
	mes "アナタが流したのはこの金の桃?"
	wait 100
	mes "それとも銀の桃?"
	wait 100
	mes "以下、続く…。"
単位が10ms(1秒の100分の1)ですので、「wait 100」が1秒間の停止を意味します。
ただし、ループ内で例えば「wait 100」と書いても1ループは1秒きっちりではありません。
wait命令は1秒きっかり止まってくれたとしても、
他の命系や演算を処理する時間が掛かってきますし、wait命令自体の処理時間も必要になる為、です。
コレは使用するパソコンの処理スペックにより、大きな差が発生してしまうかもしれませんね。
リアルタイムな処理を必要としているツールやゲームでは致命的な問題です。
また、単位が10msというのも、ソレより細かい単位で処理したい場合に使用できなくなります。
そのような場合に用いられるウェイト命令が下記になります。
await 中断時間
中断時間処理を停止させる時間を1ミリ秒単位で指定する。
似ている名称になりますが、ActiveWAITの略でしょう。
await命令はwait命令と、処理時間を指定時間だけ停止させるという点においては同じですが、
停止単位が10分の1になる点と、wait命令は、指定値×10msを止めることに対し、
await命令は前回のウェイト時からの待ち時間になることが決定的に異なります。
前回のウェイト時からの待ち時間とは、
処理パソコンのスペック、処理状態により、ウェイト時間が自動的に変わると言うことです。
イメージを掴みやすくする為に、具体例をあげましょう。
指定ウェイトが10ms、ウェイト以外に1ms掛かるループがあったとします。
Aパソコンは、ウェイト以外に3ms掛かってしまいます。
Bパソコンは、指定時間で処理できるものとします。
AB
wait命令の場合10ms + 3ms -> 13ms10ms + 1ms -> 11ms
await命令の場合7ms + 3ms -> 10ms9ms + 1ms -> 10ms
wait命令だと処理スペックにより、差が出てしまうものも、
await命令ではウェイト部分が自動的に調整されて処理スペックによる差は縮まります。
当然ですが、ウェイト以上の差は埋められません。
await命令は以前のバージョンで、使用しても常にCPU使用率が100%になる問題や、
CPU使用率が100%ではなくなった次には、wait命令よりも使用率が若干高いということがありましたが、
ヘルプを見る限り、wait命令もawait命令もCPUに対する負荷は同じとのことだそうです。
スクリプトの書き方は次のようになります。
 1
 2
 3
 4
 5
 6
 7
	mes "10ミリ秒以下がいかに高速かを見てみましょう。"
	await 2000
	repeat 10, 1
		mes "はい、" + cnt + "ミリ秒たった。"
		await 1 // 1ms止める
	loop
	mes "見た目は10ms秒差と変わんないよね…。"
さて、続いては、処理を指定時間ではなく中断させる命令の紹介です。
指定時間ではない中断と言うのは、要するにずっと中断させること?
つまり、完全に停止することか…と、そういうわけではありません。
完全に止めてしまうと自分で終了させるほか、終了させることができなくなってしまいます。
いや、むしろ完全に止まるなら、終了させることすらもできなくなってしまうのかも?
ヘルプにも「プログラムの実行を『一時』中断」と書いています。
この説明は後程…。
stop
[パラメータなし]処理を無条件に停止させる為、パラメータを必要としない。
スクリプトを最後まで流し終えると、ループではない場合、処理が停止します。
コレは初めに申しあげましたね?
バージョン2ではウィンドウごと終了していたものが、バージョン3では処理が中断するようになっています。
ココで起こっている処理がstop命令と同じ中断処理なのです。
一時中断ですので、ユーザーからの処理は受け付けています。
右上のクローズボックスを押すことや、タイトルバーの右クリック、
タスクバーのHSPウィンドウ箇所をクリックすると反応しています。
また、現段階では説明してませんが、ウィンドウ上に配置したボタンを押すと処理再開させたり、
ウィンドウをクリックしたらメニューを出せたり、
別ファイルアイコンをドロップするとイベントが発生したりさせられるようになります。
これらから分かるように、処理が停止したわけではなく、
現段階では単に再開させるイベントが起きず「待ち」の状態になっているだけなのです。
 1
 2
 3
 4
 5
 6
	value = 3
	*select
	if value < 0 : stop // 止まります
	mes "現在value[" + value + "]"
	value--
	goto *select
中断させる一方、処理を終了させる命令もあります。
end
[パラメータなし]終了させるだけの為、パラメータを必要としない。
処理を終了するとは、立ち上げたウィンドウを閉じて、使用メモリを開放するという事です。
つまり、起動前の状態にするということですね。
何度も書きますが、バージョン2ではスクリプト最終行まで実行すると終了していました。
この、end命令を実行していたのと、同じ状態が起きていたということです。
パラメータもなく、実行すると無条件に終わらせるだけなので簡単ですね。
 1
 2
 3
 4
 5
 6
 7
	wait 300
	mes "ウィンドウ終了スイッチが稼動しました。"
	repeat 6
		wait 100
		mes "終了" + (5 - cnt) + "秒前。"
	loop
	end // 終了
最後に、時刻を取得する下記命令を紹介します。
日時情報 = gettime(取得タイプ)
日時情報取得した日時情報を受け取るもの。
取得タイプ取得する下記の日時情報の種類を指定する。
0 : 年(Year)
1 : 月(Month)
2 : 曜日(DayOfWeek)
3 : 日(Day)
4 : 時(Hour)
5 : 分(Minute)
6 : 秒(Second)
7 : ミリ秒(MilliSeconds)
見て分かる通り、関数です。
また、1回で1つの日時情報のみを取得しますので、全てを取得するには8回実行する必要があります。
ただし、タイプの設定が数値で0から順になっているので、ループと配列変数を使えば大丈夫ですね。
 1
 2
 3
 4
 5
 6
 7
 8
 9
	dim now, 8
	sdim dow, 3, 7
	dow = "日", "月", "火", "水", "木", "金", "土"
	foreach now
		now(cnt) = gettime(cnt) // 日時情報を順に取得
	loop
	day = "" + now(0) + "/" + now(1) + "/" + now(3) + "(" + dow(now(2)) + ")"
	time = "" + now(4) + ":" + now(5) + ":" + now(6) + "." + now(7)
	mes day + " "+ time
現在日時と言うのは冒頭で触れていますが、システム日付のことです。
パソコンの現在時刻を変更すれば、設定された値を取得しますので、
厳密には現在の日時というと語弊があります。
普通に考えてもらって分かるかと思いますが…。