- ベストアンサー
ゲームの射程についてのアルゴリズムとは?
- ゲームの射程について知りたいです。歴史ゲームで鉄砲の射程がどこまで及ぶかをアルゴリズムで示しているようです。
- 壁がある場合、その先には射程が及ばなくなるようですが、壁の横には射程が届くことがあるのか不明です。
- 左上を座標(1,1)とした場合、打つ人が座標(4,4)にいるとき、射程が3の場合には■が射程になると思われます。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
あっ検証不足でしたね申し訳ない。 いつもxオフセットでループすると直線と式としてだめでした。差分の大きな方をループ変数にしてください。 今回の場合はyの差分の方が大きいので、yオフセットをループ変数にしてください。傾きもxの差分/yの差分で計算します。で、傾きの値が少数以下になるのでdoubleで計算してください。 int x_sa = x - x_src; int y_sa = y - y_src; // 差分の多きい方をループ変数にする。 if( abs(x_sa) < abs(y_sa) ) { // 傾きをdoubleで計算する。 double katamuki = (double)x_sa / (double)y_sa; // y差分のループの±方向を決める。 int loopcount = 1; if( y_sa<0 ) loopcount = -1; // y方向のループ for( y_offset=loopcount ; y_offset!=y_sa ; y_offset+=loopcount ) { // 傾きからxオフセットを求めます。0.5を足しているのは、丸め誤差対策です。 x_offset = (int)( ((double)y_offset+0.5) * katamuki ); x_check = x_src + x_offset; y_check = y_src + y_offset; if( map[y_check][x_check] == 1)//障害物があったら { result[y][x] = -1;//届かない } } } else { //xの差分が大きいときの処理。 } って感じです。 で、気をつけてほしいのは、射手自身の座標のときはうまく計算できないので、x_src==x&y==y_srcは除外してください。
その他の回答 (2)
- zwi
- ベストアンサー率56% (730/1282)
ゲームも数学なしでは作れませんので、数学の教科書などを読み直してみると発見がありますよ。一種の応用問題ですから。 で、今回の件ですが。 直線を式で計算します。 まず差分を求めて xの差分 = 目標ポイントのx - 射手のx yの差分 = 目標ポイントのy - 射手のy 差分から傾きを求めます。 傾き = yの差分 / xの差分 後はxのオフセットとして1からxの差分まで1刻みでループさせます(xの差分が負なら-1から-1刻みでループさせること)。 このxのオフセットに傾きを乗算するとyのオフセットが求まります。 求まったオフセットを射手のx、yに加算すれば座標がでますので、障害物かチェックします。ループ途中で障害物があればNGです。
お礼
ご返答ありがとうございます。 どんな感じなのか汚いですが自分なりにプログラムっぽいものを書いてみました。 map[8][8] = (//(1,1)基準なので余分に(←これは変なやり方だと思います・・・) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ); x_src = 4;//射手x y_src = 4;//射手y for (y = 1; y <= 8; y++) { for (x = 1; x <= 8; x++) { x_sa = x - x_src; y_sa = y - y_src; katamuki = y_sa / x_sa; if (x_sa > 0) { for (x_offset = 1; x_offset <= x_sa; x_offset++) { y_offset = x_offset * katamuki; x_check = x_src + x_offset; y_check = y_src + y_offset; if (map[y_check][x_check] == 1)//障害物があったら { result[y][x] = -1;//届かない } } } else { } } } 例えば(5, 6)☆が目標ポイントだとした場合、 xの差分が1、yの差分が2になって、傾きが2になり、 xのチェックする位置は5(x_src+1)、yのチェックする位置は6(y_src+2(x_offset * katamuki))になり 本来調べたいと思ってる(4,5)や(5,5)になりません・・・ たぶん(確実に)自分が書いたプログラムが間違っていると思うのですが、 どこらへんがいけないのでしょうか? □□□□□□□ □□■壁■□□ □■■■■■□ ■■■○■■■ □■■壁■■□ □□□□☆□□ □□□□□□□
- zwi
- ベストアンサー率56% (730/1282)
私なら射程内の全ポイントに射手からポイントまでの直線を引いてみて途中で障害物があったらNGにしますね。 >壁の横(下の壁だと(3,5)と(5,5))に射程が届いても良いのか(不自然じゃないか)は自分でもよく分かりません・・・ 絵的に変でなければ問題ないと思います。
お礼
ご返答ありがとうございます。 なるほどイメージはできたのですが、 例えば(4,4)○と(3,6)☆を線で結んだときにどうやって その間の壁とぶつかるのかをチェックするのでしょうか? 線を結ぶというのが具体的にプログラムでどう書けばいいのかが分からないです・・・ □□□□□□□ □□■壁■□□ □■■■■■□ ■■■○■■■ □■■壁■■□ □□☆□□□□ □□□□□□□
お礼
ご返答ありがとうございます。 早速試してみたのですができました。ありがとうございます。 ※自分が示した例の訂正があります。 for (y = 1; y <← 8; y++) { for (x = 1; x <← 8; x++) { このマップ設定はおかしい個所があるので参考にならないと思いますが一応訂正します。 あと、下の図で(3,2)☆が目標の時に、(4,3)◎のみ調べるので☆に届いてしまいます。 ちょっと不自然な感じがするので、傾きで得られたオフセットが整数じゃない場合は 2パターン(1.5なら1と2、-0.5なら0と-1)調べるようにすると届かなくなります。 ただその場合も逆に不自然かもしれないので、どちらが良いかは分かりません。 □□□□□□□ □□☆壁■□□ □■壁◎■■□ ■■■○■■■ □■■壁■■□ □□□□□□□ □□□□□□□