C言語+GLUT(キー操作で視点、注視点を変える)

OpenGL

3Dゲーム作成の続きです。

変数名を接頭辞にcb_をつけて統一しました。まだゲームの名称は未定なのでファイル名のcubeから取ってcbとしました。一括置換できるようにcb_で統一しておきます。
今回は、world_mapを外部ファイルから読み込むようにしたのと、視点、注視点を移動キー(aキー、dキー)で動かせるようにしました。
複数の色付きブロックを指定できるようにも修正してます。

takk@deb9:~$ cat -n cube.c
     1  #include <stdio.h>
     2  #include <string.h>
     3  #include <GL/glut.h>
     4  #include <math.h>
     5
     6  int cb_screen_width = 640;
     7  int cb_screen_height = 400;

ファイル読み込みと、トークンの切り出しを行うため、stdio.h、string.hをインクルードしています。
cb_screen_*は、画面サイズを設定する変数です。
glutの glutInitWindowSize(cb_screen_width,cb_screen_height) を実行するのに使います。

     8
     9  GLdouble cb_world_map[4096][4];
    10  int cb_world_size;

外部ファイル読み込みに伴って、初期値をまるまる削除しています。
ついでにサイズを4096(256 x 256)にしてます。あまり大きいとメモリ不足になるのでこれぐらいかなあと。

    11
    12  GLdouble cb_player_pos[3];
    13  GLdouble cb_player_lookat[3];
    14  int cb_player_direction;
    15  int cb_wire_flag = 0;

方向の変数であったdegをcb_player_directionという変数名に変えました。これでプレイヤーの目線であることが分かりやすくなったかなあと。

    16
    17  GLdouble cb_vertex[8][3]={
~省略~
    26  };
    27
    28  int cb_face[][4] = {
~省略~
    35  };
    36
    37  GLdouble cb_color[][3] = {
~省略~
    44  };
    45
    46  GLdouble cb_normal[][3] = {
~省略~
    53  };
    54
    55  GLfloat cb_light0pos[] = { 0.0, 3.0, 5.0, 1.0 };
    56  GLfloat cb_light1pos[] = { 5.0, 3.0, 0.0, 1.0 };
    57
    58
    59  GLfloat cb_gold[] = { 0.89, 0.65, 0.1, 1.0 };

各変数はcb_がついだだけで、値は変わってませんので省略。

    60
    61  GLfloat cb_material_colors[][4] = {
    62          { 0.00, 0.00, 0.00, 1.00 },     // black
    63          { 0.50, 0.15, 0.05, 1.00 },     // brown
    64          { 1.00, 0.00, 0.05, 1.00 },     // red
    65          { 0.90, 0.50, 0.00, 1.00 },     // orange
    66          { 0.60, 0.60, 0.10, 1.00 },     // yellow
    67          { 0.00, 0.65, 0.10, 1.00 },     // green
    68          { 0.00, 0.20, 0.90, 1.00 },     // blue
    69          { 0.80, 0.00, 0.90, 1.00 },     // purple
    70          { 0.50, 0.50, 0.50, 1.00 },     // gray
    71          { 0.90, 0.65, 0.10, 1.00 },     // gold
    72  };
    73

ブロック用の色を配列化してインデックス番号で指定できるようにしています。
今回のマップは、1番のbrownと、5番の緑を使ってます。

    74  int cb_edge[12][2]={
~省略~
    87  };
    88
    89  void cb_set_cube(GLdouble pos[])
    90  {
~省略~
   111  }
   112
   113  void cb_set_wire_cube(GLdouble pos[])
   114  {
~省略~
   131  }
   132

同じくcb_がついただけの変更です。

   133  void cb_look()
   134  {
   135          gluLookAt(
   136                  cb_player_pos[0],
   137                  cb_player_pos[1],
   138                  cb_player_pos[2],
   139                  cb_player_pos[0] + 40 * cos((double)cb_player_direction*M_PI/180.0),
   140                  cb_player_pos[1] - 5,
   141                  cb_player_pos[2] + 40 * sin((double)cb_player_direction*M_PI/180.0),
   142                  0.0, 1.0, 0.0);
   143  }
   144

今回からプレイヤーの視点=プレイヤーの位置にしてます。注視点は40個離れた先を見るようにしています。

   145  void cb_callback_display()
   146  {
~省略~
   167  }
   168
   169  void cb_callback_reshape(int w, int h)
   170  {
~省略~
   180  }
   181
   182  void cb_callback_keyboard(unsigned char key, int x, int y)
   183  {
   184          switch (key) {
   185          case 'q': exit(0); break;
   186          case 'w':
   187                  cb_player_pos[0] += 0.2 * cos((double)cb_player_direction*M_PI/180.0);
   188                  cb_player_pos[2] += 0.2 * sin((double)cb_player_direction*M_PI/180.0);
   189                  glutPostRedisplay();
   190                  break;
   191          case 's':
   192                  cb_player_pos[0] -= 0.2 * cos((double)cb_player_direction*M_PI/180.0);
   193                  cb_player_pos[2] -= 0.2 * sin((double)cb_player_direction*M_PI/180.0);
   194                  glutPostRedisplay();
   195                  break;
   196          case 'a':
   197                  cb_player_direction--;
   198                  if(cb_player_direction < 0)cb_player_direction=359;
   199                  glutPostRedisplay();
   200                  break;
   201          case 'd':
   202                  cb_player_direction++;
   203                  if(cb_player_direction >= 360)cb_player_direction=0;
   204                  glutPostRedisplay();
   205                  break;
   206          case ' ':
   207                  cb_wire_flag = 1 - cb_wire_flag;
   208                  glutPostRedisplay();
   209                  break;
   210          default:
   211                  break;
   212          }
   213  }
   214

キー操作でプレイヤーの位置が移動します。
wで前進、sで後退。dが右回り、aが左回りです。いずれマイクラと同じ操作にできればなあと考えています。

   215  void cb_world_cratete()
   216  {
   217          FILE *fp;
   218          char readline[100],*p1, *p2, *p3,*p4;
   219
   220          cb_world_size = 0;
   221
   222          if ((fp = fopen("world_map.txt", "r")) == NULL) {
   223                  fprintf(stderr, "can not read world_map.txt");
   224                  exit(EXIT_FAILURE);
   225          }
   226
   227          while ( fgets(readline, 100, fp) != NULL ) {
   228                  if(strlen(readline) > 4){
   229                          p1 = strtok(readline, "\t");
   230                          p2 = strtok(NULL, "\t");
   231                          p3 = strtok(NULL, "\t");
   232                          p4 = strtok(NULL, "\t");
   233                          cb_world_map[cb_world_size][0]= atoi(p1);
   234                          cb_world_map[cb_world_size][1]= atoi(p2);
   235                          cb_world_map[cb_world_size][2]= atoi(p3);
   236                          cb_world_map[cb_world_size][3]= atoi(p4);
   237                          cb_world_size++;
   238                  }
   239          }
   240
   241          fclose(fp);
   242  }
   243

マップの読み込み処理です。初回のマップはランダム生成にするつもりなので、セーブしたマップの読み込みに使うことになります。
マップデータは、world_map.txtというファイルに
X座標/Y座標/Z座標/色、をタブ区切り
テキスト形式で保存してあります。strtokを使ってp1~p4に各データが文字列で格納されます。

   244  int main(int argc, char *argv[])
   245  {
   246          cb_wire_flag = 0;
   247          cb_world_cratete();
   248
   249          cb_player_pos[0]=0;
   250          cb_player_pos[1]=5;
   251          cb_player_pos[2]=0;
   252          cb_player_direction = 0;
   253
~省略~
   274  }
   275
takk@deb9:~$

ゲーム作りを始めて3日目ですが、まだ全然ゲームの形になってません。ソースも300行も書いてない。この調子だと一年かかっても終わらなさそうです。。

コメント

タイトルとURLをコピーしました