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 で時間を待っているので、一番キー入力を受け付ける時間があるため。
当然何かの処理中にキー入力をすると言うのは、ややこし過ぎる。
実機にて確認。

きちんと動いている。
これでスクロールの実装はできた。