;
	;	HSP キャラクタ表示サンプル2
	;	( HSP ver2.2e以上で動作します )
	;
 
	randomize				; 乱数を不定にする
	wx=640:wy=400				; ウインドゥのサイズ
	screen 0,wx,wy,1			; Windowをパレットモードで初期化
 
	buffer 3,,,1				; 仮想画面をパレットモードで初期化
	picload "testchr.bmp"			; 仮想画面にキャラクタデータをロード
	chrsx=64:chrsy=64			; キャラクタのサイズを指定
	chrx=0:chry=64				; キャラクタのデータがある左上の座標
 
	;
	;    複数のキャラクタを同時に表示して動かす
	;
	;	ここでは、sprite1.asで表示したリンゴの絵を複数動かします。
	;	以前は描画する座標を変数x,yだけで保存していましたが、複数表示をする
	;	ためには座標を保存する変数も、表示する個数だけ必要になります。
	;	ここから先では、そのための設定を行なっています。
	;	配列変数を使い、x.0やx.2のように、それぞれのリンゴの座標を保存できる
	;	ようにします。ここでは、全体の個数をkazuという変数に保存しておき、
	;	その数だけ配列変数を宣言しています。たとえば、kazuが16の場合は、
	;	x.0〜x.15がそれぞれのリンゴのX座標に、y.0〜y.15がY座標になります。
	;	また、px.0〜px.15が1回につき右に何ドット移動するかを保存する変数に
	;	なります。最初にこれらの変数に乱数で値を設定してやり、複数を同時に
	;	動かしてやると、色々な速度でリンゴが動くにぎやかなデモになります。
	;
	;
	kazu=16					; 同時に表示するキャラクタの数
	dim x,kazu				; キャラクタの数だけ変数xの配列変数を確保
	dim y,kazu				; キャラクタの数だけ変数yの配列変数を確保
	dim px,kazu				; キャラクタの数だけ変数pxの配列変数を確保
 
	;
	;    配列変数への初期設定
	;
	;	ここでは、配列変数に乱数で初期の値を設定しています。
	;	repeat〜loop命令で全体の個数分だけループさせて、それぞれの配列要素に
	;	値を設定しています。重要なテクニックとして、ここではdup命令を使用して
	;	います。たとえば、「dup ax,x.cnt」は「x.cnt」という変数を「ax」という
	;	変数名でも代用できるようになります。「cnt」は、ループのカウントを示す
	;	システム変数なので、最初のループでは変数axは、「x.0」となり、次のループ
	;	では「x.1」、その次では「x.2」…というぐあいに、繰り返されるごとに
	;	変数axの役割が変わっていきます。逆に考えると、これは1つのリンゴに対して
	;	設定するつもりで変数ax,ay,apxを使うだけで、複数のリンゴに対しての設定を
	;	行なうことができることになります。
	;	複数の物を同時に処理するためには、どうしても配列変数が必要になりますが、
	;	「x.1」や「y.cnt」などの配列要素の指定を1つ1つ行なうのは面倒ですし、
	;	処理も余計にかかります。dup命令を使用することで、余計な記述を減らし、
	;	速度も向上させることができます。そして、通常の変数を扱うような感覚で
	;	配列変数を使うことができるようになります。
	;
	ax=0:ay=0:apx=0				; dup命令で使用する変数を宣言(ダミー)
 
	repeat kazu				; キャラクタの数だけループさせる
	dup ax,x.cnt				; 変数axをx.cntの代用にする
	dup ay,y.cnt				; 変数ayをy.cntの代用にする
	dup apx,px.cnt				; 変数apxをpx.cntの代用にする
	rnd ax,50:ax=ax*10+50			; X座標を乱数で設定する
	rnd ay,30:ay=ay*10+20			; Y座標を乱数で設定する
	rnd apx,4:apx++				; 動くドット数を乱数で設定する
	loop					; ループ終了
 
*chrmove
	;	メインループ(複数のリンゴが左から右へと移動する)
	;	   1. redraw命令で画面の書き換えスイッチをoffにします。
	;	   2. boxf命令で画面をすべてクリアします。
	;	   3. 表示したい絵を描画します。全体の個数だけループさせて、
	;             ここでもdup命令による代用で、配列変数x,y,pxを変数ax,ay,apx
	;	      として使用しています。
	;	   4. 表示したい絵をすべて描画し終わったら、再びredraw命令で
	;	      画面の書き換えスイッチをonにします。2〜3までの結果は、
	;	      書き換えスイッチがoffになっている間は画面に反映されません。
	;	      (内部的には更新されています)最後に、redraw 1を行なうことで、
	;	      いままでの更新が画面上にも反映されます。こうすることにより、
	;	      画面のちらつきがなくなり、きれいに動きます。また、何より
	;	      速度が2〜3倍以上速くなります。リアルタイムにキャラクタが
	;	      動くソフトなどを作る際には重要なテクニックです。
	;
	gsel 0					; 描画先をID0に
	redraw 2				; 書き換えスイッチOFF
	color 0,0,0				; 画面クリアをする色を指定
	boxf 0,0,wx-1,wy-1			; 画面をクリアする
 
	repeat kazu				; キャラクタの数だけループさせる
	dup ax,x.cnt				; 変数axをx.cntの代用にする
	dup ay,y.cnt				; 変数ayをy.cntの代用にする
	dup apx,px.cnt				; 変数apxをpx.cntの代用にする
	a=0:gosub *chr_draw			; 重ねあわせキャラ表示
	ax+=apx					; X座標を変数apxのぶんだけ右に動かす
	if ax>540 : ax=0			; X座標が右端まできていたら、0に戻す
	loop					; ループ終了
 
	redraw 1				; 最後に書き換えスイッチON
	await 20				; 必ずウエイトを入れる
 
	goto *chrmove				; 無限にループさせる
 
*chr_draw
	;	重ねあわせキャラクタ描画ルーチン
	;	( 変数ax,ayの座標に変数aのキャラNo.を表示する)
	;
	pos ax,ay				; カレントポジションを変数ax,ayの場所に設定
	gmode 2,chrsx,chrsy			; 重ねあわせモードとコピーサイズの設定
	gcopy 3,a*chrsx+chrx,chry		; 重ねあわせコピーを実行
	return					; サブルーチン終了
 
back