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