キャラクターと話す



今回はキャラクターと話します。「マップ内を移動する」と「勝手に歩くキャラクター」をつなぎ合わせます。
共通部分が多いのでつなげるだけならばそれほど難しくありません。

;話しかけよう

#const tipsize 20		;マップチップのサイズ
#const movefreq tipsize/4	;移動時に何ループで行くか(サイズを割りきれるように)
#const movelong tipsize/movefreq;一歩の長さ
#const tipmax 20

#define ch 5	;キャラクターの数
#define max 100	;カウントの最大値
#define small 50;カウントの最小値

randomize	;乱数の初期化

	jpx=10		;自分のマップチップのマスで数えたx座標
	jpy=10		;自分のマップチップのマスで数えたy座標
	jx=jpx*tipsize	;自分の位置の絶対座標x
	jy=jpy*tipsize	;自分の位置の絶対座標y

	dim chmvflg,ch	;キャラの移動フラグ
	dim chcnt,ch	;次の移動までのカウント
	dim chpx,ch	;キャラクターのマップチップで数えたx座標
	dim chpy,ch	;キャラクターのマップチップで数えたy座標
	dim chx,ch	;キャラクターのx座標
	dim chy,ch	;キャラクターのy座標
	dim chmvx,ch	;一回の移動量x
	dim chmvy,ch	;一回の移動量y
	dim chmvcnt,ch	;移動回数のカウント

	sdim talk,256,ch	;テキスト
	talk.0="私はNo.0です。\nこのように話しかけることができます。"
	talk.1="私はNo.1です。\nただの●がしゃべってるのはおかしいかな?"
	talk.2="私はNo.2です。\n自分で作る場合はもっとましな会話に変更してください。"
	talk.3="私はNo.3です。\nちゃんと当たり判定でキャラが重ならないようになってます。"
	talk.4="私はNo.4です。\n次はもっとましなのにします。"

	repeat ch	;各キャラクターの初期位置をランダム決定
		cnt2=cnt
		rnd chpx.cnt,tipmax
		rnd chpy.cnt,tipmax
		if (chpx.cnt=jpx)&(chpy.cnt=jpy) : continue cnt	;その場所に自分がいたらやり直す
		re=0
		repeat cnt
			if (chpx.cnt=chpx.cnt2)&(chpy.cnt=chpy.cnt2) : re=1 : break	;もしその場に他のキャラがいたらやり直す
		loop
		if re=1 : continue cnt
		chx.cnt=chpx.cnt*tipsize
		chy.cnt=chpy.cnt*tipsize

		rnd chcnt.cnt,max-small	;カウンターの初期数値もランダム指定
		chcnt.cnt+small
	loop

	screen 0,tipsize*tipmax,tipsize*tipmax

	title "相手の方向キー+スペースキーで話す"

*mainloop	;メインループ
	redraw 0
	gosub *drawmap
	gosub *checkkey
	gosub *drawown
	gosub *character
	redraw
	await 1
	goto *mainloop

*drawmap	;マップ描画ルーチン
	color ,255 : boxf
return

*checkkey	;キー判定ルーチン
	if moveflg=0 {	;キー取得
		stick key,15,1
		if key=1 : if jpx!0 {		;画面端でなければ
			jarrx=jpx-1		;自分移動先x
			jarry=jpy		;自分移動先y
			jmovex=-movelong	;自分移動量x
			jmovey=0		;自分移動量y
			moveflg=1		;移動前の処理へ
		}
		if key=2 : if jpy!0 {
			jarrx=jpx
			jarry=jpy-1
			jmovex=0
			jmovey=-movelong
			moveflg=1
		}
		if key=4 : if jpx!(tipmax-1) {
			jarrx=jpx+1
			jarry=jpy
			jmovex=movelong
			jmovey=0
			moveflg=1
		}
		if key=8 : if jpy!(tipmax-1) {
			jarrx=jpx
			jarry=jpy+1
			jmovex=0
			jmovey=movelong
			moveflg=1
		}
		if key&16 {	;スペースキーが押されたとき
			repeat ch
				if (jarrx=chpx.cnt)&(jarry=chpy.cnt) {
					color 255,255,255 : boxf 20,winy-100,winx-20,winy-20	;白枠を表示
					font "",14 : color : pos 40,winy-80 : mes talk.cnt	;テキストの表示
					redraw
					repeat	;スペースキーが押されるまで待つ
						stick key2
						await 1
						if key2=16 : break
					loop
				}
			loop
		}
	}
	if moveflg=1 {	;移動前の処理
		moveflg=2
		repeat ch
			if (jarrx=chpx.cnt)&(jarry=chpy.cnt) : moveflg=0 : break	;移動先に他のキャラがいたら移動しない
		loop
		if moveflg=2 {
			counter=movefreq
			jpx=jarrx
			jpy=jarry
		}
	}
	if moveflg=2 {	;移動中
		jx+jmovex
		jy+jmovey
		counter-- : if counter=0 : moveflg=0
	}
return

*drawown	;自分描画ルーチン
	font "",tipsize : color 255 : pos jx,jy : mes "●"
return

*character	;キャラクター関係ルーチン
	repeat ch
		cnt3=cnt
		if chmvflg.cnt=0 {
			if chcnt.cnt=0 {
				repeat
					cnt2=cnt
					rnd course,4	;移動する方向
					if course=0 {	;左方向
						if chpx.cnt3=0 :break	;マップの端だったら移動しない
						arrx=chpx.cnt3-1	;移動先のx座標
						arry=chpy.cnt3		;移動先のy座標
						chmvx.cnt3=-movelong	;移動量x
						chmvy.cnt3=0		;移動量y
					}
					if course=1 {	;上方向
						if chpy.cnt3=0 :break
						arrx=chpx.cnt3
						arry=chpy.cnt3-1
						chmvx.cnt3=0
						chmvy.cnt3=-movelong
					}
					if course=2 {	;右方向
						if chpx.cnt3=(tipmax-1) :break
						arrx=chpx.cnt3+1
						arry=chpy.cnt3
						chmvx.cnt3=movelong
						chmvy.cnt3=0
					}
					if course=3 {	;下方向
						if chpy.cnt3=(tipmax-1) :break
						arrx=chpx.cnt3
						arry=chpy.cnt3+1
						chmvx.cnt3=0
						chmvy.cnt3=movelong
					}
					if (arrx=jpx)&(arry=jpy) : break	;移動先に自分がいたら移動しない
					bflg=0
					repeat ch
						if cnt=cnt3 : continue
						if (chpx.cnt=arrx)&(chpy.cnt=arry) : bflg=1 : break	;移動先に他のキャラがいたら移動しない
					loop
					if bflg=1 : break
					chmvcnt.cnt3=movefreq	;移動カウンター
					chmvflg.cnt3=1		;移動フラグをONにする
					chpx.cnt3=arrx		;移動先の座標へx
					chpy.cnt3=arry		;移動先の座標へy
					break
				loop
				rnd chcnt.cnt,max-small	;カウンターを再設定
				chcnt.cnt+small
			}
			chcnt.cnt--
		}
		if chmvflg.cnt=1 {
			chx.cnt+chmvx.cnt	;移動x
			chy.cnt+chmvy.cnt	;移動y
			chmvcnt.cnt--
			if chmvcnt.cnt=0 : chmvflg.cnt=0	;カウンターが0になったら移動終了
		}
		font "",tipsize : color ,,255 : pos chx.cnt,chy.cnt : mes "●"
	loop
return

かなり長くなってしまいましたが、追加点は黄色い文字で表されています。
checkkeyサブルーチンはほとんど全て変更されました。なぜかというと、前回の方法は、あれだけならばおそらく最適な方法ですが、 こういったほかのキャラとの連携を取る場合は今の方がいいです。もしこれを前回の方法でやろうとすると、checkkeyサブルーチンは おそらく今の2倍にはなるでしょう。
moveflgが3段階になり、1で事前処理を行うようになっています。といってもこの事前処理は、他のキャラとの位置関係を調べるためのものであり、それが済めばすぐ次に行きます。


前へ 戻る 次へ