Home -> HSP講座 -> 初級編 No.15

履修漏れを補いましょう

前回まででいろいろ出来るようになったので、( ていうか F なので )
ここまでの内容で飛ばしたモノを、いくつか紹介します。


繰り返し構文

HSPで繰り返しといえば、ほぼ確実に使用するのはrepeat命令ですが、
C/C++、Javaなどの、製品も作れる本格的なプログラミング言語では、
主に別の繰り返しを使用します。

一番簡単なのは、whileです。
HSPでも使用できます。

// while を使ってみる

	// 単純な繰り返し
	i = 0
	while ( i < 6 )		// repeat 6 と同じことをします
		mes " "+ i +" 回目の繰り返し。repeat と同じ効果です。"
		i ++		// i = i + 1
	wend
	
	randomize
	question = rnd(100)
	pos 10, 200 : input number, 120, 25
	
	// 条件付きの繰り返し
	while ( number != question )
		wait 1
	wend
	end

※答えはデバッグウィンドウで確認できます^^

while ( 条件 ) で、条件が成立する限り繰り返します。
指定回数の繰り返しを行うには、i のように、回数を数えておく変数が必要です。(カウンタ変数)

  1. 始まり( whileの位置に来る )
  2. 条件を判定する。
    →(偽) wendの次までジャンプする。
  3. wendの位置に来る。
  4. whileにまで戻る。
  5. 終わり

while の変化系として、do というモノもあります。while とほぼ同じです。
ただし、do の方は条件が成立するまで繰り返すので、条件が逆になります。
しかも、条件を書く位置が、始めではなく終端、untilの方です。( 後判定 )
さっきのサンプルをdo - untilに直すと、こんな感じです。

// do - until を使ってみる

	// 単純な繰り返し
	i = 0
	do
		mes " "+ i +" 回目の繰り返し。repeat とほぼ同じ効果です。"
		i ++		// i = i + 1
	until ( i > 5 )	// repeat 6 と同じようなことをします
	
	randomize
	question = rnd(100)
	pos 10, 200 : input number, 120, 25
	
	// 条件付きの繰り返し
	do
		wait 1
	until ( number == question )
	end

条件に関係なく、最低でも一回は実行されます。この点、whileとは違います。
実行後、条件を見て、成立していなければ( 偽なら )もう一度繰り返します。
キー入力待ちループとして優秀です。

for文というものもあります。
これは、回数の繰り返しに特化した文です。

// for文

	// 書式
;	for カウンタ変数, 初期値, 終値, 増分=1
;		/* スクリプト */
;	next
	
	// repeat的なループ
	for i, 0, 3
		mes " "+ i +" 回目の繰り返し"
	next
	mes "抜けた直後の i は "+ i +" です。つまり終値と等しい。"
	mes
	
	// 減数ループ( 仮称 )
	for i, 3, -1, -1	// i += 増分なので、i += -1 される
		mes " i = "+ i
	next
	
	// 仮の無限ループ?
	for bKeydA, 0, 1, 0	// i += 0 なので、絶対に終了しない
		getkey bKeydA, 'A'	// [A] キーに反応
		wait 1
	next
	stop

  1. カウンタ変数に初期値を代入
  2. カウンタ変数の値が、終値と同じか終値より大きいなら終了
  3. 繰り返されるスクリプトを実行
  4. カウンタ変数 += 増分
  5. 2に戻る
という動作をします。( 実際はマクロなので、このように置き換えられています。)
使い方はサンプルの通りです。

なにげに getkey という新しい命令が登場しています。
stick同様キーボードの状態を調べる命令ですが、一度に一つしか調べられません。その代わり、すべてのキーに対応しています。

	getkey 変数, 仮想キーコード

という書式です。仮想キーコードというのは、キーに割り当てられた定数( 整数値 )です。
ABCやタブスペースなどの文字を入力するキーは、ASCII文字コードと同じです。( 詳しくは↓ )
ASCII文字コードは、シングルクォーテーション( ' )で文字を括って、'X' のようにして簡単に取得できます。
暗記する必要はありません。
※キーコードとして使う場合は大文字アルファベットを使います。
※全角文字( 仮名や漢字 )は '' で取得できません。
※[Shift]や[Ctrl]などの特殊なキーは、「キーコードチェッカー」で調べてください。
+参照:getkey命令の F1 ヘルプ。これは便利。

キーが押されている場合は、変数にが、
押されていなければが代入されます。

★アスキーコード? / ASCII code
※小難しい話なので、あんまり悩まなくてもいいです。
ファイル編でちらりと言いましたが、機械はすべての情報を数値で記憶するので、
文字も数値で表す、という話でした。
値を文字に変換するための規則、ルールを、文字コードというのでした。
似たような種類の文字コードの集まりを、文字コード体系といい、ASCIIはその一つです。
ASCIIでは、0 〜 127 の数値に、それぞれ1文字を割り当ています。( 'a' = 97, 'b' = 98, '0' = 48 )
この数値をアスキーコード(ASCII code)と言います。
※ちなみに、HSPの文字列は、ASCIIの一つである SHIFT_JIS を使っています。
 SHIFT_JIS では、アルファベットだけでなく仮名や漢字も扱えます。

とまぁ、ループの話をしていたことを忘れたかもしれませんが、戻ってきてください。
ここまでで、whiledofor の三種類のループ文を紹介しましたが、
勘のいい人なら思ったことでしょう。

breakできないの?」、と。
先に言ってしまうと、出来ます。
先頭にアンダースコア _ を付けて、それぞれ
_break_continue にします。
この3種類のループでは、共通してこれらを使用します。
入れ子構造から一発で脱出することは出来ません。そういうときはgotoをどうぞ。
一番外側を回数1のrepeatで囲むという手もありですね。

この話だけでやたら長いですが、最後におまけです。
whilewend
dountil
fornext
の対応を間違えた場合や、これらの外に_breakがあったりすると、こんな感じのエラーが出ます。
プリプロセッサエラー 特殊天界マクロ
※実行できませんでした
今回は for 文のどこかに異常があったようです。
がんばって探しましょう。


ラベル編

ラベルを扱う命令として、gotogosub を紹介しましたが、実を言うともうちょっとあります。
あまり使わないかもしれませんが……。

	randomize
	objmode 2
	
	pos 10, 10 : input nCmdType, 120, 25
	pos 10, 40 : button gosub "実行", *Execute
	
	stop
	
*Execute
	if ( nCmdType < 0 || nCmdType > 5 ) {
		dialog "コマンドは 0 〜 5 にしてください。", 1, "Error"
		return
	}
	
	// nCmdType の数値によって分岐する
	on nCmdType gosub *Zero, *One, *Two, *Three, *Four, *Five
	return
	
*Zero
	mes "ゼロってます"
	redraw
	return
	
*One
	mes "何故1から始まらないのか疑問である。"
	return
	
*Two
	logmes "2が選択されました"
	assert nCmdType == 2
	return
	
*Three
	color 255, 255, 255 : boxf : color
	return
	
*Four
	color rnd(256), rnd(256), rnd(256)
	return
	
*Five
	redraw 2
	return

on命令です。書き方が特殊なので注意。
これは、p1 の数値によってジャンプ先が変更されます。
switchとジャンプ命令が合体したようなものですが、基本的にswitchの方が見やすいかと思います。
これと似たような名前に、onkeyなどの命令がありますが、それらは中級編で紹介します。

ただし、こんなことするくらいならラベル型の配列変数を使った方がいいです。
※サンプル略。

もう一つ、exgotoという命令もありますが、わかりにくい上に利用価値がないので、覚えるだけ時間の無駄です。


レイアウト編

colorなどと同様、色を変更する命令には syscolor というモノもあります。
これは、Windows に設定されている色、システムカラーを使用するものです。
システムカラーは、ユーザーが独自に変更できます。( あまり変えている人はいませんが…… )
そのため、一覧は自分で作る必要があります。

// システムカラーを一覧にする

#const HEIGHT_ONELINE (480 / 31)	// 一行あたりの高さ
	
	font msgothic, 13
	
	// システムカラーは31種類( たぶん )
	repeat 31
		py = cnt * HEIGHT_ONELINE	// この行の y 座標
		
		syscolor cnt
		boxf 30, py, 300, py + HEIGHT_ONELINE
		r = ginfo_r
		g = ginfo_g
		b = ginfo_b
		
		color
		pos   5, py : mes strf("%2d", cnt)	// 行番号
		pos 320, py : mes "RGB = ("+ strf("%3d, ", r) + strf("%3d, ", g) + strf("%3d", b) +")"
		
	loop
	stop

ツールっぽい画面の背景色に 15 を使いますが、それ以外はほぼ使いません。

strf() 関数は、文字列を書式化して返す関数です。
書式というのは、上の例では"%3d"などです。
%?? というのが書式で、この部分にもう一つのパラメータの値が入ります。
%d なら整数値、%f なら実数値、%x なら16進数の整数です。
% とアルファベットの間の数値は、桁数指定で、この数値より少ない桁なら前に空白が入ります。
例えば、strf("[%3d]", 34) なら、スペースが一つ入って "[ 34]" になります。
括弧でくくるときや、桁数をそろえたいときに便利です。
普通の % は、%% とします。フォーマット指定子(%??)と見分けるためです。

HSP3.2以降では、strf()はフォーマットを複数書けるようになっています。
世の中便利なモンですねぇ……。

// HSP3.2以降でしか動かない

	r = 17
	g = 234
	b = 25
	mes strf("RGB = (%3d, %3d, %3d)", r, g, b)
	stop

ちなみに、strf()は string + format の略です。
C言語でおなじみ sprintf() のHSPバージョンですね。(謎)


ウィンドウ編

ウィンドウは、screen命令以外でも作成できます。
その方法も紹介しておきましょう。

// 枠なしウィンドウを作成する

#const wID_Main 0

*main
	gosub *Initialize
	gosub *SetWindow
	gsel wID_Main, 1
	stop
	
*Initialize
	randomize
	gsel 0, -1
	return
	
*SetWindow
	bgscr wID_Main, ginfo_dispx, ginfo_dispy, 2, 0, 0
		button "終了", *OnBtn_End
	return
	
*OnBtn_End
	end

bgscr命令です。
これで作成したウィンドウには、タイトルバーがありません。
「子ウィンドウ」というものを作成するときに使いますが、ほとんど必要はないでしょう。

もう一つあります。

// 低クオリティー・スタンプ

#const IDW_MAIN  0
#const IDW_STAMP 1

*main
	gosub *init		// Initialize (初期化) の略
	gsel IDW_MAIN, 1
	
// メインループ
*mainlp
	getkey bLClick, 1	// 左クリック (右利きの)
	
	// 左クリックされたとき
	if ( bLClick ) {
		pos mousex - 8, mousey - 8
		gcopy IDW_STAMP, 0, 0, 32, 32
	}
	
	await 64
	goto *mainlp
	
//######## サブルーチン群 ########
*init
	gsel 0, -1
	gosub *SetWindow
	return
	
*SetWindow
	buffer IDW_STAMP, 32, 32
	repeat 16
		hsvcolor (192 / 16) * cnt, 255, 255
		boxf cnt, cnt, 32 - cnt, 32 - cnt
	loop
	return

※怒らないでね。

新しく出てきた命令を2つだけ紹介します。

まず一つ目は、bufferです。
これは、screenbgscr に非常に似ていますが、
決定的な違いがあります。
ウィンドウではありません
仮想ウィンドウといいます。今流行の「仮想」、ヴァーチャルです。
ウィンドウだと思って操作してもあまり問題ありませんが、ウィンドウではないので表示することはできません。
しかし、サンプルのように画像を保存するだけなら十分なので、結構便利です。

また、bufferbgscrに変更すると、何が描画されているのか見れます。

……と、よく考えたらこれってレイアウト編だよな? という違和感がたっぷりですが、このままいきます。
続いて、gcopy です。
これは、graphics copy、画像をコピーする命令です。
ウィンドウ(または仮想ウィンドウ)の画像を、別のウィンドウ(または(略))にコピーします。
表示位置はカレントポジションからです。
詳しくは中級編で紹介する予定……です。たぶん。きっと。おそらく。


まとめ

さて、以上を持ちまして初級編を終了させていただきます。
後半が初級っぽくなかったあたり申し訳ない気持ちで一杯です……。
では、中級編でまた会いましょう!

by 上大

第十四章へ