;
	;	HSP キャラクタ表示サンプル5
	;	( HSP ver2.2e以上で動作します )
	;
 
	randomize				; 乱数を不定にする
	wx=640:wy=384				; ウインドゥのサイズ
	screen 0,wx,wy,1			; Windowをパレットモードで初期化
 
	buffer 3,,,1				; 仮想画面をパレットモードで初期化
	picload "testchr.bmp"			; 仮想画面にキャラクタデータをロード
	chrsx=64:chrsy=64			; キャラクタのサイズを指定
	chrx=0:chry=64				; キャラクタのデータがある左上の座標
 
	;
	;  複数をキャラクタを動かす(背景付きスクロール)
	;
	;	sprite4.asをさらに改造して自分とリンゴとの当たり判定をつけ、得点が
	;	加算されるようにしました。自分(首)が、リンゴに当たるとマイナス4点、
	;	通常は1点づつ加算されていく簡単なゲームの形式になっています。
	;	当たり判定は、XとY座標を比較して自分が表示されているエリアと、
	;	リンゴが表示されているエリアが重なっているかどうかで判定しています。
	;	表示されているサイズが64×64ドットなので、左上の座標から64×64の範囲
	;	に、比較対象のキャラクタが入っているかどうかをif命令で比較します。
	;
	;
	score=0					; スコアを0に設定
	rollx=0					; X方向スクロールカウンター
	myf=1					; 自分のキャラクター状態フラグ
	myx=80:myy=180				; 自分のキャラクター初期位置X,Y
 
	;
	;    マップデータの初期設定
	;
	mapx=10:mapy=6				; マップのX,Yサイズ
	alloc map,1000				; マップデータの領域を確保
	map  = "3330000000"			; Y=0のマップデータ
	map += "3000000000"			; Y=1のマップデータ
	map += "3004440000"			; Y=2のマップデータ
	map += "0000000000"			; Y=3のマップデータ
	map += "1000000011"			; Y=4のマップデータ
	map += "1100001111"			; Y=5のマップデータ
	buffer 4,wx,wy,1			; ID4に仮想画面を作成
	palcopy 3				; ID3のパレットをコピーしてくる
	gosub *map_draw				; 背景マップを作成
 
	;
	;    配列変数への初期設定
	;
	kazu=12					; 同時に表示するキャラクタの数
	dim x,kazu				; キャラクタの数だけ変数xの配列変数を確保
	dim y,kazu				; キャラクタの数だけ変数yの配列変数を確保
	dim px,kazu				; キャラクタの数だけ変数pxの配列変数を確保
 
	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*9+20			; Y座標を乱数で設定する
	rnd apx,4:apx++				; 動くドット数を乱数で設定する
	loop					; ループ終了
 
*chrmove
	;	メインループ
	;
	gsel 0					; 描画先をID0に
	redraw 2				; 書き換えスイッチOFF
 
	a=640-rollx				; 左半分のサイズを計算
	gmode 1,a,wy				; 左半分の画面サイズを指定
	pos 0,0:gcopy 4,rollx,0			; ID4から画面をコピー
	if rollx=0 : goto *nosplit		; 右半分がなければ次へ
	gmode 1,rollx,wy			; 右半分の画面サイズを指定
	pos a,0:gcopy 4,0,0			; ID4から画面をコピー
*nosplit
	rollx+:if rollx=640 : rollx=0		; スクロールカウンターが一周したら0に戻す
 
	myf=1					; 自分の状態フラグをリセット
	myxe=myx+chrsx				; 自分の右下X座標を計算
	myye=myy+chrsy				; 自分の右下Y座標を計算
 
	repeat kazu				; キャラクタの数だけループさせる
	dup ax,x.cnt				; 変数axをx.cntの代用にする
	dup ay,y.cnt				; 変数ayをy.cntの代用にする
	dup apx,px.cnt				; 変数apxをpx.cntの代用にする
 
	ax-=apx					; X座標を変数apxのぶんだけ左に動かす
	if ax<=0 : ax=580			; X座標が左端まできていたら、580に戻す
 
	pos ax,ay				; カレントポジションを変数ax,ayの場所に設定
	a=0:gosub *chr_draw			; 重ねあわせキャラ表示
 
	axe=ax+chrsx				; リンゴの右下X座標を計算
	if axe<myx : goto *nohit		; リンゴが自分より左にあるか?
	if ax>=myxe : goto *nohit		; リンゴが自分より右にあるか?
	aye=ay+chrsy				; リンゴの右下Y座標を計算
	if aye<myy : goto *nohit		; リンゴが自分より上にあるか?
	if ay>=myye : goto *nohit		; リンゴが自分より下にあるか?
 
	myf=2					; 衝突しているフラグをセットする
*nohit
 
	loop					; ループ終了
 
	gosub *keychk				; キー入力チェック
	pos myx,myy				; カレントポジションをmyx,myyの場所に設定
	a=myf:gosub *chr_draw			; 重ねあわせキャラ表示
 
	if myf=1 : score+ : else : score-=4	; 自分の状態に応じてスコアを加算
	color 255,255,255			; 文字の色を白に設定
	pos 0,0:mes "score "+score		; スコアを表示
 
	redraw 1				; 最後に書き換えスイッチON
	await 20				; 必ずウエイトを入れる
 
	goto *chrmove				; 無限にループさせる
 
 
*keychk
	;	カーソルキー入力で自分(変数myx,myy)を動かすサブルーチン
	;	(カーソルキーを同時に押すことにより斜めにも移動できます)
	;
	stick a,15				; カーソルキーの情報を取得
	if a&2 : goto *go_up			; 上を押しているか?
	if a&8 : goto *go_down			; 下を押しているか?
	goto *keychk2				; 左右のチェックにジャンプ
*go_up
	if myy>=8 : myy-=8
	goto *keychk2
*go_down
	if myy<316 : myy+=8
*keychk2
	if a&1 : goto *go_left			; 左を押しているか?
	if a&4 : goto *go_right			; 右を押しているか?
	return
*go_left
	if myx>=8 : myx-=8
	return
*go_right
	if myx<580 : myx+=8
	return
 
*map_draw
	;	マップ描画ルーチン
	;
	a=0
	gmode 1,chrsx,chrsy			; 高速モードでコピー指定
	yy=0:i=0				; 画面左上から順番に描画する
	repeat mapy
	xx=0
	repeat mapx
	peek a,map,i:i+				; マップデータ読み出し
	pos xx,yy				; 変数xx,yyが描画先の座標になる
	a-='0'					; 1桁数字の文字を0〜9の数値に変換
	gcopy 3,a*chrsx,0			; チップをコピー
	xx+=chrsx				; 1つ右にずらす
	loop
	yy+=chrsy				; 1つ下にずらす
	loop
	return
 
*chr_draw
	;	重ねあわせキャラクタ描画ルーチン
	;	( カレントポジションに変数aのキャラNo.を表示する)
	;
	gmode 2,chrsx,chrsy			; 重ねあわせモードとコピーサイズの設定
	gcopy 3,a*chrsx+chrx,chry		; 重ねあわせコピーを実行
	return					; サブルーチン終了
 
back