ベクトル周りについて
ベクトルは、座標から角度を求める計算と、角度からベクトル>スカラー計算を行う部分で構成されています。ベクトル>スカラーは簡単です。
dX=速度×COS(角度) dY=速度×SIN(角度)
JAVAのSIN,COS関数がどれほどの速度かわからなかったのですが、ラジアン>角度計算を随時処理する手間を省く為、1度単位でSIN,COS値を配列に収納して使用しています。(あと小数点演算が面倒なので256倍して、使用する際に 速度÷256しています。)
次に面倒なのは角度計算です。数式にしたら非常に単純なのですが・・・
角度=ATAN(Y÷X) ・・・ATAN:アークタンジェント
ちなみに、JAVAなどの三角関数はラジアンを扱うので、角度=ラジアン×180÷πする必要があるので
角度=ATAN(Y÷X)×180÷π
となります。ここで既にお気づきでしょうが、X=0のときは計算できません。そのため、X=0の場合は条件分岐で実装しなければなりません。同じようにY=0の時もエラーにはなりませんが、特別な処理が必要です。更に、X=0でY>0の時と、X=0でY<0の時では角度が当然違うわけで、それぞれの場合を実装する必要もあります。
そして、X<0、Y>0と、X>0、Y<0の時及び、X>0、Y>0とX<0、Y<0の時は、それぞれアークタンジェントの値が同じになってしまいます。この時も条件分岐で実装する必要があります。
以上をまとめると、座標の符号により、6通りの計算を使い分ける必要があります。角度を厳密に求める必要がある場合はこの計算を適応しなければなりませんが、ゲームなどでは大雑把な位置がわかれば良いので、(2次元のゲームの場合は)角度{X,Y}という2次元配列を事前に作成し、計算のわずらわしさや速度の向上を図ります。当然の事ですが、全ての座標について2次元配列を作ったら膨大な量になるので、ある程度数値を丸めて(注1)計算します。
JAVAのソースリストをサンプルで掲載しておきます。(クラスにするほどでもありませんが・・・)
class vectol{
public int x;
public int y;
vectol(){
x=0;
y=0;
}
vectol(vectol a){
x=a.x;
y=a.y;
}
vectol(int a,int b){
x=a;
y=b;
}
}
class vectolman{
int bx,by,mx,my,sx,sy,hx,hy,size;
int deg[][];
double sin[],cos[];
vectolman(int x,int y,int s){
mx=x;
my=y;
hx=x/2;
hy=y/2;
sx=hx*s;
sy=hy*s;
size=s;
deg=new int [x][y];
sin=new double [360];
cos=new double [360];
makerad();
}
public vectol getpos(vectol a,vectol b,int s,int d){
vectol c=new vectol();
int x,y;
int r;
x=(b.x-a.x) * size / sx;
y=(b.y-a.y) * size / sy;
r=deg[x+hx][y+hy]+d;
if(r>=360){r=r-360;}
if(r<0){r=360+r;}
c.x=(int)(cos[r]*s/256d);
c.y=(int)(sin[r]*s/256d);
return c;
}
void makerad(){
int x,y,i;
double r;
r=0;
for(x=0;x hx && y != hy){
r=Math.atan((y-hy)/(x-hx));
}
if(x < hx && y != hy){
r=Math.atan((y-hy)/(x-hx))-Math.PI;
}
if(x == hx && y>=hy){
r=Math.asin(1);
}
if(x == hx && y= hx && y==hy){
r=Math.acos(1);
}
if(x < hx && y==hy){
r=Math.acos(-1);
}
deg[x][y]=(int)(r*180d/Math.PI);
}
}
for(i=0;i<360;i++){
sin[i]=(int)(Math.sin(i*Math.PI/180)*256d);
cos[i]=(int)(Math.cos(i*Math.PI/180)*256d);
}
}
}