Dripです。
1さん、こんにちは。
プレイヤーと同条件で動作する敵AIの設計でしょうか?面白いことをされていますね。
スクリプトを拝見させていただきますと、あくまで8方向のキーを押し分けて、
「あたかも人間が操作しているように中途半端な角度にいる目標へも
なるべく直線で向かっていくような動きでキー入力操作をシミュレーションしたい」
という解釈でよろしいのでしょうか?そうしますと1さんのスクリプト中の
「; 適用」とされる範囲(7行全て)を以下の処理で置き換えてください。
; 適用
key=0 //キーをリセットする
#define myRatio 20 //何フレーム使って斜めの押し分けを行うかを定義。
//この値は大きい値ほど悠長な動きになるが、その分補正割合は正確になる。
//逆に小さい程機敏に補正を行うが、正確さに欠けるようになる。10〜20が良い具合です。
myHorizon=double(mousex-x) //目標座標への水平方向の距離
myVertical=double(mousey-y) //目標座標への垂直方向の距離
myTotal=absf(myHorizon)+absf(myVertical) //水平・垂直移動のみで移動した場合の目標座標までの距離
if myTotal>2:{ //目標座標に到達していない場合、キーの押し下げ処理を行う
//次の1行の判定は現在の目標角度が中途半端な角度であるかを判定し、
//中途半端な角度を何フレーム間補正してキー入力を行うか判定するためのif文である。
//タイマーをレートと見て、水平距離と垂直距離の差がレートを上回った場合に限り単純なキー入力を行う。
//つまり、より正確に斜めの位置に目標が存在する場合ほど以下の単純なキー入力処理が実行されることになる。
if myTimer\myRatio > abs(abs(myHorizon/myTotal*myRatio) - abs(myVertical/myTotal*myRatio)):{
//単純なキー入力処理では目標が少しでも斜めの位置にあれば斜め入力を行い、
//完全に水平・完全に垂直な位置にいる場合に限って単キーの入力を行う。
if myHorizon<0:key|=LEFT
if myHorizon>0:key|=RIGHT
if myVertical<0:key|=UP
if myVertical>0:key|=DOWN
}else{
//タイマーをレートと見て、水平距離と垂直距離の差がレートを下回っている場合は単キーの補正入力を行う。
//この処理は例えば目標が10時方向(左左上と言いましょうか)に存在する場合、
//プレイヤーは左上にキーを入力しながらも時々左キーのみをプッシュしてより真っ直ぐ目標に向かおうとします。
//この処理ではそれを行います。
if absf(myHorizon)>absf(myVertical):{ //標的がより水平方向に離れている場合、水平方向のキーのみを補正入力する
if myHorizon<0:key|=LEFT:else:key|=RIGHT //目標の位置に応じて左・右を押し分ける
}else{ //標的がより垂直方向に離れている場合、垂直方向のキーのみを補正入力する
if myVertical<0:key|=UP:else:key|=DOWN //目標の位置に応じて上・下を押し分ける
}
}
}
myTimer++ //入力レートの判定に使うためのタイマーを常時加算する
この修正によってまるで人間が操作しているような入力操作を行うようになります。
しかしこれでは角度があまりにガクガクしているので何とかならないか?
というところまで追求する場合は、敵に角度の概念を持たせる必要があります。
上記の修正に加え、「; 移動」とされる範囲(17行全て)を以下の処理で置き換えてください。
; 移動
s = ""
#define angRatio 5 //何度ずつ角度を変えるかを定義。
//大きいほど俊敏に角度を変えるが大きすぎるとガクガクする
//小さい程滑らかに角度を変えるが小さすぎるとなかなか目標の角度を向かない
//敵の速度によるが、3〜10がいい具合
moveKeyOnly=key&15 //keyから移動キーのみを取り出し、以下の判定でa_tgtに押されたキーの角度を代入する
if moveKeyOnly=UP: a_tgt=directionDegree*0:s+="↑"
if moveKeyOnly=UP+RIGHT: a_tgt=directionDegree*1:s+="↑→"
if moveKeyOnly=RIGHT: a_tgt=directionDegree*2:s+="→"
if moveKeyOnly=RIGHT+DOWN: a_tgt=directionDegree*3:s+="→↓"
if moveKeyOnly=DOWN: a_tgt=directionDegree*4:s+="↓"
if moveKeyOnly=DOWN+LEFT: a_tgt=directionDegree*5:s+="↓←"
if moveKeyOnly=LEFT: a_tgt=directionDegree*6:s+="←"
if moveKeyOnly=LEFT+UP: a_tgt=directionDegree*7:s+="←↑"
if s!"":{ //何らかのキーが入力された場合
t=a_tgt-a:if t<-180:t+=360:else:if t>180:t-=360 //tに自分の角度(a)と目標角度(a_tgt)の差を求める(-180〜180の範囲で)
if t<0:a-=angRatio:else:a+=angRatio //差の出た方向に自分の角度(a)を操作する
if a<-180:a+=360:else:if a>180:a-=360 //自分の角度(a)が(-180〜180の範囲に収まるようにする)
x+=sin(deg2rad(-a+180))*2.0 //水平方向の移動を反映
y+=cos(deg2rad(-a+180))*2.0 //垂直方向の移動を反映
}
敵の座標を管理する変数x,yに加え、敵の角度を管理する変数aに従ってx,yを移動させるので
より動きが滑らかになります。
今回はあくまで8方向のキープッシュをシミュレーションしながら
なるべく滑らかに移動させるという縛りですので出来ることに限界はありますが、
自分なりに最適な動作になるよう色々アイデアを凝らしてみると面白いかと思います。
がんばってください。