!!!どこかでよく見たアレ with HSP 今、世界中を探せばコンピュータの開発言語といわれるものは非常に数多く存在しています。 しかし、C(C++)やBASIC、Javaなどの詳細解説はたくさんあるのに、HSPではそれが少ない。 「有名な"○○"のアルゴリズムをCで書いたものがこちらです」なんていわれても、 HSP使いには分からないじゃないか… そんなあなた。 ちょっと覗いていきませんか? !!!注意事項 *HSP3前提です。HSP2以前の情報は無いです。 **特に、各種数学的演算については2と3でルールそのものが違うため、別物と考えるべきです。 *説明をかなり端折ってます。 !!!超基本 !!Hello World! {{code HSP,8,1 ;メインウィンドウにHello World!と表示 mes "Hello World!" }} {{code HSP,8,1 ;タイトルバーに以下略 title "Hello World!" }} {{code HSP,8,1 ;メッセージボックスでry dialog "Hello World!" }} 新しい開発言語を触るときにまずやりたいのは、やはり"Hello World!"でしょう。 要は何らかの手段を用いて出力(画面とは限らない)に"Hello World!"と表示させればいいわけです。 例は、どれも、表示場所が違うだけでHello World!と表示されます。 ちなみに、""で囲まれた部分は「文字列」です。命令で文字列を指定せよ、となっているときは いつも""で囲まなくてはいけません。 mes/title/dialogはそれぞれ「命令」です。命令を実行すると、その命令ごとに決まった動作を行います。 命令の後ろに半角スペースを空けてから数字や文字列を書くことで、命令を実行するに当たって必要な情報を渡すことも出来ます。 これは「引数(ひきすう)」といいます。パラメータとも呼ばれます。 !!変数 {{code HSP,8,1 A=1 B=2.0 C="日本語" D="4" }} 「変数」は、数字や文字列を一時的にいれておくことが出来る入れ物です。 上の例では、変数Aに"1"という「整数」、同Bに"2.0"という「実数」、Cに"日本語"という「文字列」を 入力しています。変数は中に入っているデータの代わりに使え、またいつでも中身を入れ替えることができます。 変数にデータを入力することを代入といいます。 中に入っているデータの種類によって、変数の種類は整数型/実数型/文字列型に分類されます。 種類によって使える場面と使えない場面が出てくるので注意する必要があります。 ちなみに、上の例で変数Dは"4"という「'''文字列'''」が代入されます。""で囲めば、数字だろうと何だろうと文字列です。 {{code HSP,8,1 A=1 A=A+5 mes A }} 変数の代入の式は、算数の式と違い、左辺と右辺が等しいことを示すものではなく、 左辺に右辺の計算結果を入力する、という意味しかありません。したがって、 上に書いたような数学的にはおかしい式も、プログラムとしては全く問題ありません。 この例ではmes Aで6と出力されます。 !!四則演算 {{code HSP,8,1 A=1+2*3 mes A }} 一般的な算数、あるいは数学と同じルールです。つまり、まずカッコに囲まれたところを計算し、 掛け算割り算をしてから、足し引きを行うわけです。 上の例では、画面に7と表示されます。 !補足 従来のHSP2では、カッコで囲まない限り、常に左から演算していました。 よって、先ほどのスクリプトでは9が出力されてしまいます。 !!比較と条件判断 {{code HSP,8,1 A=1 if A=1:mes "Aは1":else:mes "Aは1じゃない" }} if命令で、条件に該当するときだけ実行したい処理を書くことが出来ます。 上の例では、A=1が成立しているので、「Aは1」と表示されます。 if命令の引数は数値です。上の例では、「A=1」という式に答えがあり、その値によって 処理が分けられています。比較を行った場合成立すれば1、不成立なら0です。 if命令は引数の値が0かそれ以外かを判断し、それ以外なら直後の命令を、 0ならelse以降の命令を実行します。0でelseが無い場合はその行は飛ばします。 {{code HSP,8,1 if 1:mes "この文章は表示されます。" if 0:mes "この文章は表示されません。" }} こういうことです。 !!繰り返し処理 {{code HSP,8,1 repeat 10 A=A+cnt loop mes A }} repeat命令とloop命令を組み合わせて、繰り返し処理したい内容を書くことが出来ます。 repeatの引数は繰り返す回数です。 cntは「システム変数」の一種で、repeatとloopの間で現れたときに、何回目のループかが代入されています。1回目のときは0です。 上の例ではAにループの回数を順に加えていく、つまり0から順に1,2,3…と加えていくものです。 繰り返し回数を10回にしているので、加算されるのは9でです。 よってmes Aでの出力は45です。 !!論理演算 {{code HSP,8,1 mes "3秒後に←キーが押されているかチェックします" wait 300 ;3秒の間、プログラムの実行を停止します stick KEY ;特定のキーだ押されているかどうかを取得します if KEY&1=1:mes "←が押されてた":else:mes "←は押されてなかった" }} 論理演算は、2進法を知らないと理解が難しいです。 2進法は、ありとあらゆる数値を0と1の2種類の数値だけで表す方法で、コンピュータ内部の値は 全てこれで表現されてます。{{fn ちなみに、理由は「ONとOFFだけで表現できるから」です。}} ,10進法,2進法 ,0,0 ,1,1 ,2,10 ,3,11 ,10,1010 ,100,1100100 で、論理演算は、比較する2つの値をそれぞれ2進法で表現して{{fn さっきも書いたとおり内部的には常に2進法の数値なんですが}}、同じ位ごとに値を比べて答えを出します。 これが参考になります。[論理演算|http://ew.hitachi-system.co.jp/p/r-logic.html] HSPでは、ANDが&、ORが|、XORが^で使えます。 最初の例では、←キーが押されている場合のみ変数KEYに1が代入されるので、 KEY&1 イコール 1&1 イコール 1 が成立、「←が押されてた」と出力されます。 !!!どこかで見た数学的プログラム !!読む前に できれば、中学で三角関数を習ってからご覧になってください。 !注意点 コンピュータの場合、一般に右方向と'''下方向が'''正です。HSPでもそうです。 したがって、グラフなどを描画しようとするときにY座標に関してはそのことを考慮する必要があります。 !!円を描く {{code HSP,8,1 X0=cos(6.28/360*cnt)*50+50 Y0=sin(6.28/360*cnt)*50+50 repeat 360,1 X=cos(6.28/360*cnt)*50+50 Y=sin(6.28/360*cnt)*50+50 line X0,Y0,X,Y X0=X:Y0=Y loop }} ここでは、中学数学までで使う度数法にて計算するために、2πを360で割り、使用しています。 !ちょっと詳しく 角度を表す方法として、一般に2種類の方法があります。 一つは、1周360°で表現する、度数法。 もう一つは、1周を2πで表現する弧度法です。ラジアン法とも呼ばれます。{{fn πは、もちろん円周率のπです。π=3.14159...}} 世間一般でよく使われているのは度数法ですが、数学や物理の世界で一般的に用いられるのは弧度法で、プログラミングでも例外ではありません。 360°=2πなので、2πを360で割れば1度あたりのラジアンを求めることが出来ます。{{fn もちろんπ/180でいいんですが、ここでは見た目の分かりやすさ優先にしてます。}}{{fn 弧度法は高校数学ですが、現時点では360°=2πさえ理解できれば問題ありません。}} !余談1 πなど数学的によく使う定数は、hspmath.asをincludeすることで簡単に使うことが出来ます。 πならM_PIという定数として定義されています。 !余談2 ちなみに、ただ単に円を描きたいだけなら {{code HSP,8,1 circle 0,0,100,100,0 }} で出来ます。 !!アナログ時計を作る {{code HSP,8,1 #define M_PI 3.1415926535 #define DEG M_PI/180 width 200,200 repeat redraw 0 ;実画面の描画を一時停止 color 255,255,255 boxf 0,0,200,200 ;画面クリア ;中心を(100,100)としている color 255 ;時針(30度ごと、半径50px、赤) line 100,100,sin(DEG*30*gettime(4))*50+100,-cos(DEG*30*gettime(4))*50+100 color ,255 ;分針(6度ごと、半径90px、緑) line 100,100,sin(DEG*6*gettime(5))*90+100,-cos(DEG*6*gettime(5))*90+100 color ,,255 ;秒針(6度ごと、半径100px、青) line 100,100,sin(DEG*6*gettime(6))*100+100,-cos(DEG*6*gettime(6))*100+100 redraw 1 ;画面の再描画 wait 100 ;1秒待機 loop }} !ちょっと詳しく 上で登場した#defineは、スクリプトの文字列を置き換える機能です。例えば {{code HSP,8,1 #define M_PI 3.1415926535 }} は、スクリプト中の「M_PI」と言う文字列を「3.1415926535」で置き換えるわけです。 同様に DEG→M_PI/180→3.1415926535/180 と置き換えられます。 この置き換え機能は、一般にプログラムを読みやすくするのに用いられます。 今回はこれを使う事で、DEGは角度の1度を示していることになります。 アナログ時計は、極端な話、秒が変化するたびに3本の線を描画すればいいわけです。 で、その座標を求めるのにはやはり三角関数を用います。 時計の針は、値が0のときに上を指します。したがって、時間が0のときに 描画位置が原点の真上に来るようにするためにXを求めるのにsinを使います。 同様にYを求めるのにcosを使いますが、上でも書いているとおりYに関しては 下が正ですので、上下の位置関係を反転させるために-をつけます。 !余談っつーか練習 このスクリプトでは、時針は1時間に1回、分針は1分に1回しか描画位置が変わりません。 しかし、現実のアナログ時計はそうではなく、秒や分に合わせて徐々に指し示す位置が変わっていきます。 それをプログラムで実現するためにはどうすればいいでしょうか。