
HSPの掲示板に、左右どちらに旋回する方が早いのかの判定について質問がありました。
方法としては色々あるでしょうが、そのひとつとして、ベクトルの外積を使う方法を紹介します。
// 角度の補正が面倒なので、数学に合わせて0ラジアンはx軸方向に並行とします。
// 考え方としては、自分の向きをaベクトル、自分から目標の向きをbベクトルとして、
// 外積から、abベクトルのなす角のsinを求め、どちらに旋回する方が早いか判定します。
; 自分の座標と向き
mx = 320.0
my = 240.0
mr = 0.0
*main
; 目標の座標(マウスカーソル)
tx = 0.0+mousex
ty = 0.0+mousey
; aベクトル(自分の向き)
ax = cos(mr)
ay = sin(mr)
; bベクトル(自分から目標の向き)
bx = tx-mx
by = ty-my
;-----------------------------------------------------------
; ここから重要
;-----------------------------------------------------------
; abベクトルの外積
a×b = ax*by - bx*ay
; abベクトルのなす角をsinθとして
; a×b = |a||b|sinθ
sinθ = (a×b)/sqrt(bx*bx+by*by)
if absf(sinθ)>=0.02 {
; sinθの符号で旋回する方向を判定
if sinθ>=0 {
mr += 0.02
} else {
mr -= 0.02
}
}
;-----------------------------------------------------------
; ここまで
;-----------------------------------------------------------
redraw 0
color 255,255,255 : boxf
color 0,0,0
; 自分
line mx+cos(mr)*100,my+sin(mr)*100, mx,my
; 目標
pos tx-7,ty-9 : mes "◎"
redraw
await 10
goto*main
なぜ外積やsinの符号で判定できるか分からない人は、sinの定義をよく考えてください。
この方法なら、自分が何回転するとしても面倒なことを考えなくて済みます。
説明の為に冗長なソースになっていますが、実際にやってることは簡単です。工夫すれば、かなり短くできるので、HSPコンテストのショート部門に向いているかもしれません。
この手の判定ですが、他の人のゲームのソースを研究すれば、他にも色々な方法があるかもしれません。私はプログラムの技術は人から盗んで学ぶものだと考えているので、そういうのも大切かなと思います。
3/16追記、ショートっぽくサイズを削ってみたら、ここまで短縮できました。
; 自分の座標
#const mx 320
#const my 240
mr = 0.0
; 目標(mousex,mousey)
#define tx mousex
#define ty mousey
*main
tr = atan(ty-my, tx-mx)
sinθ = cos(mr)*sin(tr) - cos(tr)*sin(mr)
mr += 0.02 * (absf(sinθ)>=0.02) * (2*(sinθ>=0)-1)
redraw 0
pget -1 : boxf
color
; 自分
line mx+cos(mr)*100,my+sin(mr)*100, mx,my
; 目標
pos tx-7,ty-9 : mes "◎"
redraw
await 10
goto*main
bベクトルの長さを1にすることで、外積からsinθの変換の手間が省けます。