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行も書いてない。この調子だと一年かかっても終わらなさそうです。。
コメント