十字キーの中心を原点とすると、図のようになります。
上: y > |x|
下: y < -|x|
右: x > |y|
左: x < -|y|
境界上を判定に加える場合は、等号を含めます。
y >= |x|
8方向キーの場合は、境界ベクトルと入力方向の内積から判定できます。
(ベクトル内積には順方向だとプラス。逆方向だとマイナスになる性質があります)
オレンジ色のエリアにPがあると、V1・Pがプラスになります。
グリーン色のエリアにPがあると、V4・Pがプラスになります。
図の点Pは、V1・PとV4・Pが両方プラスなので左上と判定できます。
十字キー用と8方向キー用。それぞれ独立した関数です。
#include <math.h>
//ベクトルの方向判定( 上下左右の4方向 )
int VectorDirection4( double x, double y ) //戻り値 0:上 1:左 2:下 3:右 -1:エラー
{
if( y == 0 && x == 0 ) { return -1; }
//境界上の判定の場合、左右より上下が優先になります
if( y >= abs(x) ) { return 0; } //上
if( y <= -abs(x) ) { return 2; } //下
if( x < -abs(y) ) { return 1; } //左
if( x > abs(y) ) { return 3; } //右
return -1; //こないはず
}
//ベクトルの方向判定( 縦横斜めの8方向 )
int VectorDirection8( double x, double y ) //戻り値 0:上 1:左上 2:左 3:左下 4:下 5:右下 6:右 7:右上 -1:エラー
{
#define M_PI 3.14159265358979323846
int i;
if( y == 0 && x == 0 ) { return -1; }
//境界のベクトル 境界ベクトルは8本ですがそのうち4つあれば計算できます。
//固定値なのであらかじめ計算しておくとよいでしょう。
double work_vx[4];
double work_vy[4];
double rad;
for( i = 0 ; i < 4; i++ ) {
rad = ( ( 22.5 + i * 45 ) * M_PI ) / 180;
work_vx[i] = cos( rad );
work_vy[i] = sin( rad );
}
//各ベクトルと内積を行い結果を格納します
double dot_result[8];
for( i = 0 ; i < 4; i++ ) {
dot_result[i] = work_vx[i] * x + work_vy[i] * y;
//反対側ベクトルの内積値は符号反転でよい
dot_result[i+4] = - dot_result[i];
}
//境界ベクトル上に入力点があった場合は、半時計周りにある方向を優先します
if( dot_result[0] > 0 && dot_result[3] >= 0 ) { return 0; }//上
if( dot_result[1] > 0 && dot_result[4] >= 0 ) { return 1; }//左上
if( dot_result[2] > 0 && dot_result[5] >= 0 ) { return 2; }//左
if( dot_result[3] > 0 && dot_result[6] >= 0 ) { return 3; }//左下
if( dot_result[4] > 0 && dot_result[7] >= 0 ) { return 4; }//下
if( dot_result[5] > 0 && dot_result[0] >= 0 ) { return 5; }//右下
if( dot_result[6] > 0 && dot_result[1] >= 0 ) { return 6; }//右
if( dot_result[7] > 0 && dot_result[2] >= 0 ) { return 7; }//右上
return -1; //こないはず
}