CDW マップを複数画面にする Part3


2022年 2月 11日
 
 
 最後にキー入力の座標計算をする。

 座標の計算そのものは HEXの x座標 mkx lxを足すだけでできた。

訂正 : 以下の式が必要でした。

 if mkx>=(hxb+schk) : mkx-=(hxb+schk)

 赤枠の部分です。

 つまりこの場合、横の HEX数 hxb=37、海の余白 schk=2で、全長さ 39ですけど、マップの左端座標は 0なので 1週すると 0が 39になります。

 ですので mkx(マウス座標)に lx(スクロール座標)を足した座標が 39オーバーなら 39引きます。

 これでも動いてるように見えたのは、マップデータが 1次元配列だったために 39のズレが、トータルで y座標が 1個ズレるような感じの事になったからです。
 
 

 カーソルの座標は mx,my

 そこから HEXの座標 mkx,mkyを算出する。

 mkn=-1 ; hex座標

 mx=mousex : my=mousey ; カーソル位置

; HEX座標(mkn)
 mkx=(mx-hxp-2-(mky\2)*(hkx/2))/hkx
 mkx+=lx
  if mkx>=(hxb+schk) : mkx-=(hxb+schk)
 mky=(my-hyp-3)/hky
 mkn=mky*hxb+mkx ; HEX座標
  if mkn>=hxb*hyb : mkn=-1 ; オーバー

 見ての通り mkx+=lxで mkxに lx(スクロール座標)を足してる、変更はそれだけだった(訂正しました)

 y座標はスクロールせず固定なので変更無し。

 最終的に算出する HEXの座標は mknになる、いつもながら縦横を 1次元配列で扱っているため。
 
 
 さて問題なのは、むしろキー入力の処理。

 何が問題かと言うと「押して放す操作」と「押したままドラッグしてスクロールさせる操作」を判定しないといけない。

 でも、これは前に 1MAP防衛シューティングの時にやったので、今回はそのソースを元にして割りと簡単にできた。

 プログラムは 1度思考錯誤して作成すると割と使いまわすだけで済む、なんかプログラム用語では「同じ車輪を 2度発明するな」とかなんとかいう言葉があった。
 
 
 考え方としては「押してる」状態の処理と「押してない」状態の処理を分けて処理する事。

 状態(モード)を kf(キーフラグ)で管理する事。

 kfフラグにより、押した kf=1、そこから放した kf=2のように処理できる(このソースでは kf=2はスクロールモードになってる)

	kf=0	; キーフラグ

	kln1=0	; 押した国
	kln2=0	; 攻め込む国

	repeat
	 mkn=-1 ; hex座標

	 k=0 : mx=0 : my=0 ; 入力リセット
	 repeat 1
	  if kwc>0 : kwc- : break ; ウエイト
	  mx=mousex : my=mousey ; カーソル位置
	  stick k,256 ; マウスボタン、スマホクリック
	 loop

; 押してる
	 repeat 1
	  if k!256 : break
	  if kf=0 : kf=1 : kepx=mx : kepy=my : keplx=lx
	  if kf=1 : if kepx-mx>8 or mx-kepx>8 : kf=2 ; スクロールモード

	  if kf=2 { ; スクロール
	   lx=keplx+(kepx-mx)/20;hkx
	    if lx<0 : lx=lx+hxb+schk
	    if lx>=hxb+schk : lx=lx-(hxb+schk)
	  }
	 loop

; 押してない
	 repeat 1
	  if k=256 : break ; 放してない
	  if kf=0  : break ; 一度も押してない
	  if kf=2 : kf=0 : break ; スクロールモード
; 押して放した

	  kf=0 ; リセット

; HEX座標(mkn)
	  mkx=(mx-hxp-2-(mky\2)*(hkx/2))/hkx
	  mkx+=lx
	  mky=(my-hyp-3)/hky
	  mkn=mky*hxb+mkx ; HEX座標
	   if mkn>=hxb*hyb : mkn=-1 ; オーバー

	  if mkn<0 { ; 画面外
	   if kln1=0 : gosub *tarn_end
	   kln1=0 : kf=3 : break
	  }

	  if map(mkn)<1 : kln1=0 : break ; 領土外

	  ldn=map(mkn) ; 国No.

	  if kln1=ldn : kln1=0   : break ; 同じ国の場合リセット
	  if kln1=0   : kln1=ldn : break ; 国選択
	  if lpd(kln1)!pn1 and kln1!ldn : kln1=ldn : break ; 別の国を選択

	  repeat 1 ; 攻め込む
	   if kln1=0		: break ; 選択してない
	   if lpd(kln1)!pn1 : break ; 自国では無い
	   if lpd(ldn)=pn1	: break ; 自領なので攻め込まない
	   if ldcd(kln1)<2	: kln1=0 : break ; ダイスが2以上無い

	   f=0 : ldlg=kln1*ldlb
	   repeat ldlb ; 隣接国か
		if ldl(ldlg+cnt)=ldn : f=1 : break
	   loop
	   if f=0 : kln1=0 : break

	   kln2=ldn
	   gosub *battle ; 戦闘へ
	  loop

	  kln1=0
	  kln2=0
	 loop

	 if k=512 {
	  if kln1=0 : gosub *tarn_end : kf=3 : break ; ターンエンド
	  if kln1>0 : kln1=0
	 }

	 if mainf!5 or kf=3 : break

 kf=0 の時押した座標を元にして、kf=1の処理で移動距離が 8ドット以上の時に kf=2にしてスクロール処理している。

 lx=keplx+(kepx-mx)/20 でスクロールする HEX数(lx)を算出している。

 /20と言うのは移動量で、HEXの幅が30ドットなので、この数字を /30にすれば、なぞったドットと等速でスクロールする、/20は少し早めのスクロールになる。
 
 
 
 次に問題なのは CPUが自動操作している状態でのスクロール操作。

 当然 CPUが行動している状態でもマップ画面をスクロールして確認したい。

 戦闘状態の時はスクロールしないとして、それ以外の時のスクロールをしたい。
 
 
 まずキー入力を一元化する。

#deffunc scr_key ; スクロール入力

	mx=mousex : my=mousey ; カーソル位置
	stick k,256 ; マウスボタン、スマホクリック

; 押してる
	repeat 1
	 if k!256 : break
	 if kf=0 : kf=1 : kepx=mx : kepy=my : keplx=lx
	 if kf=1 : if kepx-mx>8 or mx-kepx>8 : kf=2 ; スクロールモード

	 if kf=2 { ; スクロール
	  lx=keplx+(kepx-mx)/20;hkx
	   if lx<0 : lx=lx+hxb+schk
	   if lx>=hxb+schk : lx=lx-(hxb+schk)
	 }
	loop

	return

 押して放す、つまりタップ操作は必要無いので、これだけで LXを算出すれば済む。

 一元化したのは 8ドットずらしたらスクロールのような値を一元管理するため、と言っても先のものと合わせて今の所 2ヶ所だけ。
 
 
 とりあえずターンエンド時のダイス増の時に受け付けるようにした。

#deffunc te_put int _te_putf; ターンエンド表示

	te_putf=_te_putf

	bpwt1c=0
	repeat
	 scr_key ; スクロール入力
	  if kf>0 and k!256 : kf=0 : break ; 放した

	 if bpwt1f=0 and k!0 : break
	 if bpwt1f>0 and bpwt1c=bpwt1 : break
	 bpwt1c+

	 redraw 0
	  n=0 : if tef=1 or te_putf=1 : n=1
	  map_put n
	 redraw 1
	 await 1000/50
	loop

	return

 これはターンエンドの画面表示ルーチンだけど、ここにスクロールのキー操作を入れた。

 なぜかと言うと await 1000/50 つまり FPS 20 で時間を待っているので、一番キー入力を受け付ける時間があるため。

 当然何かの処理中にキー入力をすると言うのは、ややこし過ぎる。
 
 
 実機にて確認。

 きちんと動いている。

 これでスクロールの実装はできた。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です