dungeon_crawler

annotate prototype/src/main.cc @ 56:f9b8bbebc9b3

fixed the music playback
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 20 Sep 2012 10:04:25 +0300
parents 4c427e28ca00
children aa86119e3295
rev   line source
nuclear@1 1 #include <stdio.h>
nuclear@1 2 #include <stdlib.h>
nuclear@1 3 #include <assert.h>
nuclear@7 4 #include <unistd.h>
nuclear@1 5 #include "opengl.h"
nuclear@46 6 #include "psys/psys.h"
nuclear@1 7 #include "level.h"
nuclear@48 8 #include "texture.h"
nuclear@1 9 #include "camera.h"
nuclear@5 10 #include "datapath.h"
nuclear@5 11 #include "tileset.h"
nuclear@15 12 #include "renderer.h"
nuclear@41 13 #include "renderer_deferred.h"
nuclear@24 14 #include "cmdcon.h"
nuclear@18 15 #include "cfg.h"
nuclear@38 16 #include "timer.h"
nuclear@48 17 #include "audio/audio.h"
nuclear@48 18 #include "audio/source.h"
nuclear@55 19 #include "audio/ovstream.h"
nuclear@1 20
nuclear@17 21 bool init(int xsz, int ysz);
nuclear@5 22 void cleanup();
nuclear@7 23 void idle();
nuclear@1 24 void disp();
nuclear@15 25 void draw();
nuclear@18 26 void view_matrix(int eye);
nuclear@18 27 void proj_matrix(int eye);
nuclear@7 28 void update(unsigned long msec);
nuclear@1 29 void reshape(int x, int y);
nuclear@1 30 void keyb(unsigned char key, int x, int y);
nuclear@7 31 void key_release(unsigned char key, int x, int y);
nuclear@24 32 void keyb_con(unsigned char key, int x, int y);
nuclear@1 33 void mouse(int bn, int state, int x, int y);
nuclear@1 34 void motion(int x, int y);
nuclear@46 35 unsigned int load_psys_tex(const char *fname, void *cls);
nuclear@1 36
nuclear@5 37 static TileSet *tileset;
nuclear@1 38 static Level *level;
nuclear@7 39
nuclear@7 40 static FpsCamera cam;
nuclear@7 41 static bool keystate[256];
nuclear@1 42
nuclear@18 43 static float stereo_focus_dist = 0.25;
nuclear@18 44 static float stereo_eye_sep = stereo_focus_dist / 30.0;
nuclear@18 45
nuclear@24 46 static bool show_con;
nuclear@5 47
nuclear@48 48 static AudioSource *move_sound;
nuclear@55 49 static OggVorbisStream *music;
nuclear@48 50
nuclear@1 51 int main(int argc, char **argv)
nuclear@1 52 {
nuclear@1 53 glutInit(&argc, argv);
nuclear@5 54
nuclear@18 55 if(!cfg.parse_args(argc, argv)) {
nuclear@18 56 return 1;
nuclear@5 57 }
nuclear@5 58
nuclear@18 59 glutInitWindowSize(cfg.width, cfg.height);
nuclear@18 60 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (cfg.stereo ? GLUT_STEREO : 0));
nuclear@18 61 glutCreateWindow("dungeon crawler prototype");
nuclear@1 62
nuclear@7 63 glutIdleFunc(idle);
nuclear@1 64 glutDisplayFunc(disp);
nuclear@1 65 glutReshapeFunc(reshape);
nuclear@1 66 glutKeyboardFunc(keyb);
nuclear@7 67 glutKeyboardUpFunc(key_release);
nuclear@1 68 glutMouseFunc(mouse);
nuclear@1 69 glutMotionFunc(motion);
nuclear@1 70
nuclear@1 71 glewInit();
nuclear@1 72
nuclear@18 73 if(!init(cfg.width, cfg.height)) {
nuclear@5 74 return 1;
nuclear@5 75 }
nuclear@39 76 atexit(cleanup);
nuclear@5 77
nuclear@5 78 glutMainLoop();
nuclear@5 79 }
nuclear@5 80
nuclear@17 81 bool init(int xsz, int ysz)
nuclear@5 82 {
nuclear@41 83 // backup light for the forward crappy renderer
nuclear@1 84 glEnable(GL_LIGHTING);
nuclear@1 85 glEnable(GL_LIGHT0);
nuclear@41 86
nuclear@41 87 float ldir[] = {0, 0, -0.5, 1};
nuclear@1 88 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
nuclear@41 89 float lcol[] = {1, 1, 1, 1};
nuclear@41 90 glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol);
nuclear@41 91 glLightfv(GL_LIGHT0, GL_SPECULAR, lcol);
nuclear@1 92
nuclear@1 93 glEnable(GL_DEPTH_TEST);
nuclear@1 94 glEnable(GL_CULL_FACE);
nuclear@1 95 glEnable(GL_MULTISAMPLE);
nuclear@1 96
nuclear@25 97 add_data_path(".");
nuclear@5 98 add_data_path("data");
nuclear@48 99 add_data_path("data/audio");
nuclear@16 100 add_data_path("sdr");
nuclear@5 101
nuclear@48 102 if(cfg.sound && !init_audio()) {
nuclear@48 103 fprintf(stderr, "failed to initialize audio, continuing silently\n");
nuclear@48 104 cfg.sound = false;
nuclear@48 105 }
nuclear@48 106 if(cfg.sound) {
nuclear@48 107 move_sound = new AudioSource;
nuclear@52 108 move_sound->set_volume(0.4);
nuclear@55 109
nuclear@55 110 music = new OggVorbisStream;
nuclear@55 111 if(music->open(datafile_path("bgtrack.ogg"))) {
nuclear@56 112 music->set_volume(0.6);
nuclear@55 113 music->play(PlayMode::loop);
nuclear@55 114 } else {
nuclear@55 115 delete music;
nuclear@55 116 music = 0;
nuclear@55 117 }
nuclear@48 118 }
nuclear@48 119
nuclear@41 120 rend = new DeferredRenderer();
nuclear@42 121 if(!cfg.use_deferred || !rend->init(xsz, ysz)) {
nuclear@41 122 printf("falling back to crappy renderer...\n");
nuclear@41 123
nuclear@41 124 rend = new FwdRenderer();
nuclear@41 125 if(!rend->init(xsz, ysz)) {
nuclear@41 126 fprintf(stderr, "failed to create renderer\n");
nuclear@41 127 return false;
nuclear@41 128 }
nuclear@15 129 }
nuclear@15 130
nuclear@26 131 if(!init_cmdcon()) {
nuclear@26 132 return false;
nuclear@26 133 }
nuclear@26 134
nuclear@46 135 psys_texture_loader(load_psys_tex, 0, 0);
nuclear@46 136
nuclear@5 137 // load a tileset
nuclear@5 138 tileset = new TileSet;
nuclear@18 139 printf("loading tileset: %s\n", cfg.tileset_file);
nuclear@18 140 if(!tileset->load(datafile_path(cfg.tileset_file))) {
nuclear@5 141 return false;
nuclear@5 142 }
nuclear@5 143 set_active_tileset(tileset);
nuclear@5 144
nuclear@1 145 level = new Level;
nuclear@18 146 printf("loading level: %s\n", cfg.level_file);
nuclear@18 147 if(!level->load(datafile_path(cfg.level_file))) {
nuclear@5 148 return false;
nuclear@1 149 }
nuclear@1 150
nuclear@7 151 cam.input_move(0, 0.5, 0);
nuclear@7 152
nuclear@5 153 return true;
nuclear@1 154 }
nuclear@1 155
nuclear@15 156 void cleanup()
nuclear@15 157 {
nuclear@15 158 delete level;
nuclear@15 159 delete tileset;
nuclear@41 160 delete rend;
nuclear@26 161
nuclear@26 162 cleanup_cmdcon();
nuclear@51 163
nuclear@51 164 if(cfg.sound) {
nuclear@55 165 delete music;
nuclear@51 166 delete move_sound;
nuclear@51 167 destroy_audio();
nuclear@51 168 }
nuclear@15 169 }
nuclear@15 170
nuclear@7 171 void idle()
nuclear@7 172 {
nuclear@7 173 glutPostRedisplay();
nuclear@7 174 }
nuclear@7 175
nuclear@1 176 void disp()
nuclear@1 177 {
nuclear@38 178 update(get_time_msec());
nuclear@7 179
nuclear@18 180 if(cfg.stereo) {
nuclear@18 181 glDrawBuffer(GL_BACK_LEFT);
nuclear@1 182
nuclear@18 183 glMatrixMode(GL_PROJECTION);
nuclear@18 184 glLoadIdentity();
nuclear@18 185 proj_matrix(-1);
nuclear@18 186 glMatrixMode(GL_MODELVIEW);
nuclear@18 187 glLoadIdentity();
nuclear@18 188 view_matrix(-1);
nuclear@1 189
nuclear@24 190 draw();
nuclear@18 191
nuclear@18 192 glDrawBuffer(GL_BACK_RIGHT);
nuclear@18 193
nuclear@18 194 glMatrixMode(GL_PROJECTION);
nuclear@18 195 glLoadIdentity();
nuclear@18 196 proj_matrix(1);
nuclear@18 197 glMatrixMode(GL_MODELVIEW);
nuclear@18 198 glLoadIdentity();
nuclear@18 199 view_matrix(1);
nuclear@18 200
nuclear@24 201 draw();
nuclear@18 202 } else {
nuclear@18 203 glMatrixMode(GL_PROJECTION);
nuclear@18 204 glLoadIdentity();
nuclear@18 205 proj_matrix(0);
nuclear@18 206 glMatrixMode(GL_MODELVIEW);
nuclear@18 207 glLoadIdentity();
nuclear@18 208 view_matrix(0);
nuclear@18 209
nuclear@24 210 draw();
nuclear@18 211 }
nuclear@1 212
nuclear@1 213 glutSwapBuffers();
nuclear@1 214 assert(glGetError() == GL_NO_ERROR);
nuclear@7 215 }
nuclear@7 216
nuclear@24 217 void draw()
nuclear@24 218 {
nuclear@41 219 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@29 220
nuclear@41 221 rend->render(level);
nuclear@24 222
nuclear@24 223 if(show_con) {
nuclear@24 224 draw_cmdcon();
nuclear@24 225 }
nuclear@24 226 }
nuclear@24 227
nuclear@18 228 void view_matrix(int eye)
nuclear@18 229 {
nuclear@18 230 float offs = stereo_eye_sep * eye * 0.5;
nuclear@18 231 glTranslatef(-offs, 0, 0);
nuclear@18 232 cam.use_inverse();
nuclear@18 233 }
nuclear@18 234
nuclear@18 235 void proj_matrix(int eye)
nuclear@18 236 {
nuclear@18 237 static const float fov = M_PI / 4.0;
nuclear@18 238 static const float near_clip = 0.1;
nuclear@18 239 static const float far_clip = 100.0;
nuclear@18 240
nuclear@18 241 float top = near_clip * tan(fov * 0.5);
nuclear@18 242 float right = top * (float)cfg.width / (float)cfg.height;
nuclear@18 243
nuclear@18 244 float frust_shift = -(float)eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
nuclear@18 245 glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
nuclear@18 246 }
nuclear@18 247
nuclear@18 248
nuclear@7 249 void update(unsigned long msec)
nuclear@7 250 {
nuclear@7 251 static unsigned long last_upd;
nuclear@7 252
nuclear@7 253 if(last_upd == 0) {
nuclear@7 254 last_upd = msec;
nuclear@7 255 }
nuclear@7 256 float dt = (float)(msec - last_upd) / 1000.0;
nuclear@7 257
nuclear@56 258 float offs = 2.0 * dt;
nuclear@7 259 float dx = 0, dy = 0;
nuclear@7 260
nuclear@7 261 // handle key input
nuclear@48 262 bool did_move = false;
nuclear@7 263 if(keystate['w'] || keystate['W']) {
nuclear@7 264 dy -= offs;
nuclear@48 265 did_move = true;
nuclear@7 266 }
nuclear@7 267 if(keystate['s'] || keystate['S']) {
nuclear@7 268 dy += offs;
nuclear@48 269 did_move = true;
nuclear@7 270 }
nuclear@7 271 if(keystate['d'] || keystate['D']) {
nuclear@7 272 dx += offs;
nuclear@48 273 did_move = true;
nuclear@7 274 }
nuclear@7 275 if(keystate['a'] || keystate['A']) {
nuclear@7 276 dx -= offs;
nuclear@48 277 did_move = true;
nuclear@7 278 }
nuclear@7 279
nuclear@7 280 cam.input_move(dx, 0, dy);
nuclear@7 281
nuclear@46 282 tileset->update_tiles(msec);
nuclear@49 283
nuclear@49 284 level->set_player_position(cam.get_position());
nuclear@38 285 level->update(msec, dt);
nuclear@38 286
nuclear@49 287 if(cfg.sound) {
nuclear@50 288 // set the listener matrix
nuclear@50 289 set_audio_listener(cam.matrix());
nuclear@50 290
nuclear@50 291 // play the walking sound if we're walking
nuclear@49 292 int cellx, celly;
nuclear@49 293 level->get_cell_coords_at(cam.get_position(), &cellx, &celly);
nuclear@48 294
nuclear@49 295 const AudioSample *move_sample;
nuclear@49 296 if(did_move && (move_sample = level->get_sample(cellx, celly, TILE_SAMPLE_WALK))) {
nuclear@49 297 if(move_sample != move_sound->get_sample()) {
nuclear@49 298 move_sound->stop();
nuclear@49 299 move_sound->set_sample(move_sample);
nuclear@49 300 move_sound->play();
nuclear@49 301 }
nuclear@49 302 } else {
nuclear@49 303 if(move_sound->get_sample()) {
nuclear@49 304 move_sound->stop();
nuclear@49 305 move_sound->set_sample(0);
nuclear@49 306 }
nuclear@48 307 }
nuclear@48 308 }
nuclear@48 309
nuclear@7 310 last_upd = msec;
nuclear@1 311 }
nuclear@1 312
nuclear@1 313 void reshape(int x, int y)
nuclear@1 314 {
nuclear@1 315 glViewport(0, 0, x, y);
nuclear@18 316 cfg.width = x;
nuclear@18 317 cfg.height = y;
nuclear@30 318
nuclear@41 319 rend->resize(x, y);
nuclear@1 320 }
nuclear@1 321
nuclear@18 322 static bool stereo_shift_pressed;
nuclear@18 323
nuclear@1 324 void keyb(unsigned char key, int x, int y)
nuclear@1 325 {
nuclear@1 326 switch(key) {
nuclear@1 327 case 27:
nuclear@1 328 exit(0);
nuclear@18 329
nuclear@24 330 case '`':
nuclear@24 331 show_con = true;
nuclear@24 332 glutKeyboardFunc(keyb_con);
nuclear@24 333 glutKeyboardUpFunc(0);
nuclear@24 334 glutPostRedisplay();
nuclear@24 335 break;
nuclear@24 336
nuclear@18 337 case 'z':
nuclear@18 338 stereo_shift_pressed = true;
nuclear@18 339 break;
nuclear@18 340
nuclear@48 341 case 'p':
nuclear@48 342 {
nuclear@48 343 Vector3 pos = cam.get_position();
nuclear@48 344 int cell_x, cell_y;
nuclear@48 345 level->get_cell_coords_at(pos, &cell_x, &cell_y);
nuclear@48 346 printf("Current position: [%.2f %.2f %.2f] cell: [%d %d]\n", pos.x, pos.y, pos.z,
nuclear@48 347 cell_x, cell_y);
nuclear@48 348 }
nuclear@48 349 break;
nuclear@48 350
nuclear@48 351 case 'P':
nuclear@48 352 {
nuclear@48 353 Vector3 pos = cam.get_position();
nuclear@48 354 int cell_x, cell_y;
nuclear@48 355 level->get_cell_coords_at(pos, &cell_x, &cell_y);
nuclear@48 356 AudioSample *sample = level->get_sample(cell_x, cell_y, TILE_SAMPLE_WALK);
nuclear@48 357 printf("walk sample: %p\n", (void*)sample);
nuclear@48 358 }
nuclear@48 359 break;
nuclear@48 360
nuclear@48 361
nuclear@18 362 case '\n':
nuclear@18 363 case '\r':
nuclear@18 364 {
nuclear@18 365 static bool fullscr;
nuclear@18 366 if(glutGetModifiers() & GLUT_ACTIVE_ALT) {
nuclear@18 367 fullscr = !fullscr;
nuclear@18 368 if(fullscr) {
nuclear@18 369 glutFullScreen();
nuclear@18 370 } else {
nuclear@18 371 glutPositionWindow(20, 20);
nuclear@18 372 }
nuclear@18 373 }
nuclear@18 374 }
nuclear@18 375 break;
nuclear@18 376
nuclear@18 377 default:
nuclear@18 378 break;
nuclear@1 379 }
nuclear@7 380
nuclear@7 381 keystate[key] = true;
nuclear@7 382 }
nuclear@7 383
nuclear@7 384 void key_release(unsigned char key, int x, int y)
nuclear@7 385 {
nuclear@18 386 switch(key) {
nuclear@18 387 case 'z':
nuclear@18 388 stereo_shift_pressed = false;
nuclear@18 389 break;
nuclear@18 390
nuclear@18 391 default:
nuclear@18 392 break;
nuclear@18 393 }
nuclear@18 394
nuclear@7 395 keystate[key] = false;
nuclear@1 396 }
nuclear@1 397
nuclear@24 398 void keyb_con(unsigned char key, int x, int y)
nuclear@24 399 {
nuclear@24 400 if(key == '`' || key == 27) {
nuclear@24 401 show_con = false;
nuclear@24 402 glutKeyboardFunc(keyb);
nuclear@24 403 glutKeyboardUpFunc(key_release);
nuclear@24 404 glutPostRedisplay();
nuclear@24 405 } else {
nuclear@24 406 cmdcon_keypress(key);
nuclear@24 407 }
nuclear@24 408 }
nuclear@24 409
nuclear@1 410 static int prev_x, prev_y;
nuclear@1 411 static bool bnstate[32];
nuclear@1 412
nuclear@1 413 void mouse(int bn, int state, int x, int y)
nuclear@1 414 {
nuclear@1 415 prev_x = x;
nuclear@1 416 prev_y = y;
nuclear@1 417 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN;
nuclear@1 418 }
nuclear@1 419
nuclear@1 420 void motion(int x, int y)
nuclear@1 421 {
nuclear@1 422 int dx = x - prev_x;
nuclear@1 423 int dy = y - prev_y;
nuclear@1 424 prev_x = x;
nuclear@1 425 prev_y = y;
nuclear@1 426
nuclear@18 427 if(stereo_shift_pressed) {
nuclear@18 428 if(dy != 0) {
nuclear@18 429 stereo_focus_dist += dy * 0.01;
nuclear@18 430 stereo_eye_sep = stereo_focus_dist / 30.0;
nuclear@18 431 printf("foc: %f, sep: %f\n", stereo_focus_dist, stereo_eye_sep);
nuclear@18 432 glutPostRedisplay();
nuclear@18 433 }
nuclear@18 434 return;
nuclear@18 435 }
nuclear@18 436
nuclear@1 437 if(bnstate[0]) {
nuclear@56 438 cam.input_rotate(dy * 0.0075, dx * 0.0075, 0);
nuclear@1 439 glutPostRedisplay();
nuclear@1 440 }
nuclear@1 441 if(bnstate[2]) {
nuclear@1 442 cam.input_zoom(dy * 0.1);
nuclear@1 443 glutPostRedisplay();
nuclear@1 444 }
nuclear@1 445 }
nuclear@46 446
nuclear@46 447 unsigned int load_psys_tex(const char *fname, void *cls)
nuclear@46 448 {
nuclear@46 449 TextureSet *texset = tileset->get_textures();
nuclear@48 450 return texset->get(fname);
nuclear@46 451 }