最も初歩的なものを作ってみよー。
ではまず、画面デザインを考えてみましょう。
ここまで順を追って読んでいる入門な方たちは、多分この段階で難しいデザインをしようとすると挫折します。ちなみに僕の場合グラフィックを用いようという時点で死にましたが。――というわけで文字だけで構成されるわけですが、その文字で表示するにしたってある程度工夫の余地があります。が、ここは入門ということで最もシンプルに行きましょう。
ただ、いつまででもそのままでは味気ないので、ざっとグラフィック辺りまで出来るようになったら頑張ってみるのもいいかもしれません。

(いつまで経っても改善していない例)
と、いうわけで。とりあえず日時の取得だけしましょう。表示はまた後で。
日時を取得するには、gettime関数(この関数は2.61までは命令でした)を使います。関数についてはAppendix1.関数を参照してください。
variable = gettime(type) type : 取得する情報のタイプ タイプリスト 0 : 年 1 : 月 2 : 曜日 3 : 日 4 : 時 5 : 分 6 : 秒 7 : ミリ秒
とりあえず例を挙げると、
day = gettime(3) ;日を取得
hour = gettime(4) ;時を取得
こんな感じです。上の例の場合、dayに日が代入され、hourに時が代入されます。今これを書いているのは6月19日21時50分なので、今実行した場合、dayには"19"、hourには"21"が代入されます。
ちなみに、ミリ秒は1000分の1秒です。wait命令(一定時間動作を止める命令)など、HSPにおいて時間を指定する際には大抵この単位を用います。
さて、時計を作ると言うことはタイプ0~6までを取得すればオーケーです。ミリ秒を取得して更新していたら画面がちらつきますし(この辺については後で)、そもそもミリ秒まで知りたいなんて人は恐らくいないでしょう。単純に考えるとこうなります。
year = gettime(0) ;年
month = gettime(1) ;月
・
・
・
とま、こんな感じになります。というかこれ以外に考えられません(とかいいつつSCCでは違う手段を使っているという)。さて、こういう書き方をするので後は頑張ってみてくださいな。
で、これはおまけなんですが。無茶苦茶極端な例を挙げると、このプログラムを2006年12月31日23時59分に実行したとします。年の取得から秒の取得までには微妙なタイムラグがありますので、例えば日を取得した直後に翌年1月1日0時0分になると、yearに2006、monthに12、dayに31が入っていて、hourは0、minuteも0、secondも0、という状況が発生します。要するに表示上では12月31日をもう一回やり直すという……。相当稀ですが。月を取得した直後だと一気に12月1日まで逆戻りしてしまうことも。ただ、時計プログラムの場合、新しい情報を常に取得しているので次回の取得の時(普通1秒後)には直っています。――こんなことも、僕は見たことありませんが一応あり得ます。
取得方法が分かったところで、表示してみましょう。
変数を画面表示する方法については、2-4で説明しました。その方法で表示してみてください。課題です。練習です。復習です。
さて、表示できましたか? 文字と数字を組み合わせることで、『年』、『月』、『日』といった単位も表示できます。数字だけの表示をしたかたは是非こちらを。大体の人は文字+数字だと思いますが。
……と、いうわけでここで聞こえると思われる読者の声にお応えしようと思います。答えるかな?
表示されていたら嘘です。対策したでしょう貴方?
gettime関数で、代入先に指定できるのは数値型変数です。逆に言えば、gettime関数が返すのは数値です。しかし、曜日は文字列です。2006年6月19日は月曜日です。この日に実行した場合、曜日の所には1と表示されていることでしょう。これは、曜日も数値で返されているからです。数値型変数の時点で分かっているとは思いますが念のため。
となると、数値から文字列を表示させなければなりません。――が、これを条件分岐、if命令だとかswitch~caseマクロでやろうものなら壮絶な処理となります。if命令を連発するのはあまりよろしくありません。何より見にくいです。するとどうするかというと、配列変数を使います。
復習ですが、配列変数の添え字には変数なども使うことができます。……もう大体分かっているかと思います。そうです。配列変数に曜日の文字をあらかじめ代入しておくのです。
dowdat="日","月","火","水","木","金","土"
――とします。実はこれSCCから持ってきたのですが、dowdatというのは“Day Of Week DATa”という意味……だと思います。僕ももう覚えてません。
後は添え字を指定してやるだけです。
貴方が作った表示部分の、曜日の所をdowdat(dow)という風に変更してみてください。ちなみに変数名は同じくSCCからです。
サンプルを提示するとこんな感じです。
dowdat = "日","月","火","水","木","金","土"
dow = gettime(2)
mes dowdat(dow)
どうでしょう。表示されましたか? ではこの辺で曜日については終了、ということで。
日時を取得して表示したは良いものの、動かないんじゃ意味ありませんよね。動かない時計は意味が無いのと同じように。時間は刻一刻と過ぎているのに自分のプログラムだけ時空から取り残されているのは悲しいですよね。よね? そういうわけで、自分のプログラムが時間の最先端を行けるように改良しましょう。……ええ、時代じゃなく。
画面を更新するには、repeat~loop命令を使います。3-3.繰り返しでやったアレですね。どこでも良いので、wait命令を入れるのを忘れないでください。さもなくば反応しなくなります。wait命令の引数は、大体50くらい(500ミリ秒)で良いでしょう。あんまり小さくしても意味ありませんし、大きくしても意味ありません。
ただ、単純に繰り返すと凄いことになります。repeatが来る度にどんどん下に流れていって、最終的には画面からはみ出てしまいます。そこで、画面をクリアする必要があります。
画面をクリアするにはcls命令を使うんですね。この命令を、loopで戻ってきた直後、表示の直前に入れてやれば良いのです。
これで表示は更新されるようになり、作った時計のプログラムはようやく時間の流れに追いつくことが出来るようになりました……が。恐らく皆さんは少し疑問に思うことがあるでしょう。僕も思いましたね。――何故か知らんが表示がちらついている、と。それは次で説明します。
恐らくこの時点で実行すると画面がちらつきます。これには理由が2つあります。
cls命令を使っているでは1つ目から説明しましょう。
ここで言う「逐次表示」というのは、画面全ての描画を待たずに単純にmes命令を使っている、という意味です。それのどこが悪いのかというと、この規模のものであればまだ良いのですが、将来的にゲームなどを作ると、画面が徐々に描画されるという現象に出くわします。徐々にといっても一瞬ですが、人の目に分かるレベルではあります。
以下のサンプルはこれをかなり極端な形で再現したものです。実際にはwait 10のところが様々な処理に変わり、その処理の時間が積み重なっていくわけです。
repeat 10
mes cnt
wait 10
loop
0~9まで次々に表示されると思います。
これを解決するにはredraw命令を使用します。描画を始める直前にredraw 0を、そしてloop命令の直前辺りにredraw 1を加えて下さい。上記サンプルならrepeatの前にredraw 0、loopの後にredraw 1を入れてみて下さい。
redraw命令は画面の描画モードを切り替える命令です。……というと難しそうなんですが、かなり極端に言えば『描画を止める』命令です。redraw 0が実行されると、実際の画面(ウィンドウとして表示されている画面)が書き換わらなくなります。この間に実行されたmes命令などの結果は、redraw 1が実行されるまで描画されません。
これを利用すると、今回の時計であればきちんと秒まで書ききってから表示を書き換えることが出来るわけです。
次に2つ目です。何故cls命令がダメなのか。
これにはcls命令は少し特殊であるということが関係しています。cls命令は「画面をクリアする命令」と認識されていますが、実際は「ウィンドウ内の情報をクリアする命令」なのです。当然表示されている内容も情報なのでクリアされるわけですが、同時にフォントの設定、色の設定などがクリアされています。
その関係で、cls命令は先程述べたredraw命令が実行されていても(つまりredraw 0が実行されてからredraw 1が実行されるまでの間でも)画面を書き換えます。となるとredraw命令が意味を成さなくなるわけです。
というわけで、代わりにboxf命令を使います。この命令は、指定された範囲を現在の色で塗りつぶします。画面をクリアするには左上から右下まで全部白で塗りつぶせば良いわけです。
HSPで『色』というのはRGB(光の三原色)を0~255までの数値で表したものになります。特に指定しない場合現在の色は黒ですので、0, 0, 0ということになります。
現在の色を変更するのはcolor命令です。パラメータは3つで、1つ目からR, G, Bと指定します。白は全て255なので、color 255, 255, 255を記述します。
boxf命令はパラメータが4つありますが、全て省略すると画面全てが指定されます。特に一部を書き換える必要もないので、単純にboxfと記述します。
まとめるとこうなります。
color 255, 255, 255
boxf
これで画面はきちんとクリアされます。
boxf命令の後、color命令を使って現在の色を黒(0, 0, 0)に戻すのを忘れないで下さい。さもないと白地に白が表示されて何も見えなくなります。
ちなみに、SCCはそんなことを全く知らないアホな時代に作ってるのでredrawはあってもboxfではなくclsを使っています。更新するのが面ど――……。
これで、かなり簡素で質素で……ずばり言うならしょぼい時計が完成したわけです。
完成したからには、実行ファイル(exeファイル)を作ってみたい気分になりませんか? なりますよね。なりますとも。――というわけで、最後に実行ファイルを作ってみたいと思います。
さて、実行ファイルを作るのは非常に簡単です。ソースファイルを保存しておいて、Ctrl+F9で一発です(『実行ファイル自動作成』という機能です)。すると、ソースファイルと同じフォルダに、"hsptmp.exe"が出来ています。これが実行ファイルです。試しに起動してみると、スクリプトエディタでF5を押したときと全く同じように動いています。
と、これだけでは味気ないので、手動で作成する方も紹介しましょう。これはHSP2.55まで使われていた方法ですので、今では基本的に自動作成を使います。
とりあえずソースファイルを保存しておきましょう。そうしたら、メニューバーにある『HSP(P)』をクリックし、次に『START.AXファイル作成』をクリックします。これで、ソースファイルをコンパイルしたファイルが出来ます。
START.AXが出来たら、次はPACKFILEを作ります。これは、実行ファイルに含めるファイルを指定するリストの様なものです。メニューバーの『ツール(T)』をクリックし、『PACKFILE編集』をクリックします。左側にはソースファイルのあるフォルダのリスト、右側にはPACKFILEのリストが表示されています。どんな場合でも必ずPACKFILEに含めなければならないのはSTART.AXだけです。今回、それ以外のファイルは必要ありませんので、とりあえず"START.AX"を選んで『追加->』をクリックします。暗号化はチェックしてもしなくてもどちらでも構いません。チェックする場合は追加する前にチェックしてください。――右側に"START.AX"(暗号化にチェックしていれば、"+START.AX"になります)が追加されていれば、『閉じる』をクリックしてください。
これで準備は整いました。メニューバーの『ツール(T)』をクリックし、『EXEファイル作成(M)』をクリックしてください。とりあえずファイル名を入力し、『OK』をクリックすれば、カレントディレクトリに実行ファイルが作成されます。
オプションなどは、スクリプト内でも指定出来るようになっているので、3.0を使っている限り手動ではなく自動で作成した方が良いと思います。簡単ですし。その辺はHSPのプログラミングマニュアル1を参照してください。
Last Modified: 2008-11-28