次は下りを作ります
移動キーが入力されると、移動後のプレイヤーの位置にブロックが存在するかどうかで登り判定をしていました。
case 'w': cb_player_pos[0] += 0.2 * cos((double)cb_player_direction*M_PI/1 cb_player_pos[2] += 0.2 * sin((double)cb_player_direction*M_PI/1 { int x,y,z,block_id; x = (int)cb_player_pos[0]; y = (int)cb_player_pos[1]; z = (int)cb_player_pos[2]; block_id=cb_get_block(x,y,z); if(block_id != 0){ cb_player_pos[1]++; } } glutPostRedisplay(); break;
下りは足元にブロックがあるかどうかの判定にしますが、その前に、上のプログラムをリファクタリングしたいと思います。
私の場合プログラミングしていて、一番楽しいと思う時は、リファクタリングしている時です。最初からきれいに作れば、もっとスピーディにプログラミングできるのでしょうけど。
cb_player_pos[0]~[2]は、プレイヤーがいる座標が格納される配列ですが、
[0]にx座標、[1]にy座標、というように、配列である必要がありません。
これを構造体にして、x、y、zのメンバを揃えることにします。
変更前の変数定義はこのようになってます。
GLdouble cb_player_pos[3]; int cb_player_direction; int cb_player_direction_v;
下のように変更しました。
struct cb_struct_pos { GLdouble x,y,z; int dir,dir_v; }; struct cb_struct_pos cb_player_pos;
ついでにプレイヤーの向き(方角)を格納しているcb_player_directionともdirという名前にして構造体メンバとしました。dir_yは上下の向きです。
ということで、変数名に合わせて、最初のプログラムも下のように修正。少しすっきりしました。
case 'w': { struct cb_struct_pos* p = &cb_player_pos; p->x += 0.2 * cos((double)cb_player_pos.dir*M_PI/180.0); p->z += 0.2 * sin((double)cb_player_pos.dir*M_PI/180.0); if(cb_get_block(p->x, p->y, p->z) != 0) p->y++; } glutPostRedisplay(); break;
さらに改造。キー入力全体では、このようになりました。
void cb_callback_keyboard(unsigned char key, int x, int y) { struct cb_struct_pos* p = &cb_player_pos; switch(key){ case 'q': exit(0); break; case 'w': p->x += 0.2 * cos((double)cb_player_pos.dir*M_PI/180.0); p->z += 0.2 * sin((double)cb_player_pos.dir*M_PI/180.0); break; case 's': p->x -= 0.2 * cos((double)cb_player_pos.dir*M_PI/180.0); p->z -= 0.2 * sin((double)cb_player_pos.dir*M_PI/180.0); break; case 'a': cb_player_pos.dir--; if(cb_player_pos.dir < 0)cb_player_pos.dir=359; break; case 'd': cb_player_pos.dir++; if(cb_player_pos.dir >= 360)cb_player_pos.dir=0; break; case ' ': cb_wire_flag = 1 - cb_wire_flag; break; default: return; } redisplay: if(cb_get_block(p->x, p->y, p->z) != 0) p->y++; if(cb_get_block(p->x, p->y-1, p->z) == 0) p->y--; glutPostRedisplay(); }
コメント