dungeon_crawler

annotate prototype/src/main.cc @ 55:4c427e28ca00

music playback bugfixing
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 19 Sep 2012 08:19:10 +0300
parents bcdea26c8f27
children f9b8bbebc9b3
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@55 112 music->play(PlayMode::loop);
nuclear@55 113 } else {
nuclear@55 114 delete music;
nuclear@55 115 music = 0;
nuclear@55 116 }
nuclear@48 117 }
nuclear@48 118
nuclear@41 119 rend = new DeferredRenderer();
nuclear@42 120 if(!cfg.use_deferred || !rend->init(xsz, ysz)) {
nuclear@41 121 printf("falling back to crappy renderer...\n");
nuclear@41 122
nuclear@41 123 rend = new FwdRenderer();
nuclear@41 124 if(!rend->init(xsz, ysz)) {
nuclear@41 125 fprintf(stderr, "failed to create renderer\n");
nuclear@41 126 return false;
nuclear@41 127 }
nuclear@15 128 }
nuclear@15 129
nuclear@26 130 if(!init_cmdcon()) {
nuclear@26 131 return false;
nuclear@26 132 }
nuclear@26 133
nuclear@46 134 psys_texture_loader(load_psys_tex, 0, 0);
nuclear@46 135
nuclear@5 136 // load a tileset
nuclear@5 137 tileset = new TileSet;
nuclear@18 138 printf("loading tileset: %s\n", cfg.tileset_file);
nuclear@18 139 if(!tileset->load(datafile_path(cfg.tileset_file))) {
nuclear@5 140 return false;
nuclear@5 141 }
nuclear@5 142 set_active_tileset(tileset);
nuclear@5 143
nuclear@1 144 level = new Level;
nuclear@18 145 printf("loading level: %s\n", cfg.level_file);
nuclear@18 146 if(!level->load(datafile_path(cfg.level_file))) {
nuclear@5 147 return false;
nuclear@1 148 }
nuclear@1 149
nuclear@7 150 cam.input_move(0, 0.5, 0);
nuclear@7 151
nuclear@5 152 return true;
nuclear@1 153 }
nuclear@1 154
nuclear@15 155 void cleanup()
nuclear@15 156 {
nuclear@15 157 delete level;
nuclear@15 158 delete tileset;
nuclear@41 159 delete rend;
nuclear@26 160
nuclear@26 161 cleanup_cmdcon();
nuclear@51 162
nuclear@51 163 if(cfg.sound) {
nuclear@55 164 delete music;
nuclear@51 165 delete move_sound;
nuclear@51 166 destroy_audio();
nuclear@51 167 }
nuclear@15 168 }
nuclear@15 169
nuclear@7 170 void idle()
nuclear@7 171 {
nuclear@7 172 glutPostRedisplay();
nuclear@7 173 }
nuclear@7 174
nuclear@1 175 void disp()
nuclear@1 176 {
nuclear@38 177 update(get_time_msec());
nuclear@7 178
nuclear@18 179 if(cfg.stereo) {
nuclear@18 180 glDrawBuffer(GL_BACK_LEFT);
nuclear@1 181
nuclear@18 182 glMatrixMode(GL_PROJECTION);
nuclear@18 183 glLoadIdentity();
nuclear@18 184 proj_matrix(-1);
nuclear@18 185 glMatrixMode(GL_MODELVIEW);
nuclear@18 186 glLoadIdentity();
nuclear@18 187 view_matrix(-1);
nuclear@1 188
nuclear@24 189 draw();
nuclear@18 190
nuclear@18 191 glDrawBuffer(GL_BACK_RIGHT);
nuclear@18 192
nuclear@18 193 glMatrixMode(GL_PROJECTION);
nuclear@18 194 glLoadIdentity();
nuclear@18 195 proj_matrix(1);
nuclear@18 196 glMatrixMode(GL_MODELVIEW);
nuclear@18 197 glLoadIdentity();
nuclear@18 198 view_matrix(1);
nuclear@18 199
nuclear@24 200 draw();
nuclear@18 201 } else {
nuclear@18 202 glMatrixMode(GL_PROJECTION);
nuclear@18 203 glLoadIdentity();
nuclear@18 204 proj_matrix(0);
nuclear@18 205 glMatrixMode(GL_MODELVIEW);
nuclear@18 206 glLoadIdentity();
nuclear@18 207 view_matrix(0);
nuclear@18 208
nuclear@24 209 draw();
nuclear@18 210 }
nuclear@1 211
nuclear@1 212 glutSwapBuffers();
nuclear@1 213 assert(glGetError() == GL_NO_ERROR);
nuclear@7 214 }
nuclear@7 215
nuclear@24 216 void draw()
nuclear@24 217 {
nuclear@41 218 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@29 219
nuclear@41 220 rend->render(level);
nuclear@24 221
nuclear@24 222 if(show_con) {
nuclear@24 223 draw_cmdcon();
nuclear@24 224 }
nuclear@24 225 }
nuclear@24 226
nuclear@18 227 void view_matrix(int eye)
nuclear@18 228 {
nuclear@18 229 float offs = stereo_eye_sep * eye * 0.5;
nuclear@18 230 glTranslatef(-offs, 0, 0);
nuclear@18 231 cam.use_inverse();
nuclear@18 232 }
nuclear@18 233
nuclear@18 234 void proj_matrix(int eye)
nuclear@18 235 {
nuclear@18 236 static const float fov = M_PI / 4.0;
nuclear@18 237 static const float near_clip = 0.1;
nuclear@18 238 static const float far_clip = 100.0;
nuclear@18 239
nuclear@18 240 float top = near_clip * tan(fov * 0.5);
nuclear@18 241 float right = top * (float)cfg.width / (float)cfg.height;
nuclear@18 242
nuclear@18 243 float frust_shift = -(float)eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
nuclear@18 244 glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
nuclear@18 245 }
nuclear@18 246
nuclear@18 247
nuclear@7 248 void update(unsigned long msec)
nuclear@7 249 {
nuclear@7 250 static unsigned long last_upd;
nuclear@7 251
nuclear@7 252 if(last_upd == 0) {
nuclear@7 253 last_upd = msec;
nuclear@7 254 }
nuclear@7 255 float dt = (float)(msec - last_upd) / 1000.0;
nuclear@7 256
nuclear@9 257 float offs = 2.5 * dt;
nuclear@7 258 float dx = 0, dy = 0;
nuclear@7 259
nuclear@7 260 // handle key input
nuclear@48 261 bool did_move = false;
nuclear@7 262 if(keystate['w'] || keystate['W']) {
nuclear@7 263 dy -= offs;
nuclear@48 264 did_move = true;
nuclear@7 265 }
nuclear@7 266 if(keystate['s'] || keystate['S']) {
nuclear@7 267 dy += offs;
nuclear@48 268 did_move = true;
nuclear@7 269 }
nuclear@7 270 if(keystate['d'] || keystate['D']) {
nuclear@7 271 dx += offs;
nuclear@48 272 did_move = true;
nuclear@7 273 }
nuclear@7 274 if(keystate['a'] || keystate['A']) {
nuclear@7 275 dx -= offs;
nuclear@48 276 did_move = true;
nuclear@7 277 }
nuclear@7 278
nuclear@7 279 cam.input_move(dx, 0, dy);
nuclear@7 280
nuclear@46 281 tileset->update_tiles(msec);
nuclear@49 282
nuclear@49 283 level->set_player_position(cam.get_position());
nuclear@38 284 level->update(msec, dt);
nuclear@38 285
nuclear@49 286 if(cfg.sound) {
nuclear@50 287 // set the listener matrix
nuclear@50 288 set_audio_listener(cam.matrix());
nuclear@50 289
nuclear@50 290 // play the walking sound if we're walking
nuclear@49 291 int cellx, celly;
nuclear@49 292 level->get_cell_coords_at(cam.get_position(), &cellx, &celly);
nuclear@48 293
nuclear@49 294 const AudioSample *move_sample;
nuclear@49 295 if(did_move && (move_sample = level->get_sample(cellx, celly, TILE_SAMPLE_WALK))) {
nuclear@49 296 if(move_sample != move_sound->get_sample()) {
nuclear@49 297 move_sound->stop();
nuclear@49 298 move_sound->set_sample(move_sample);
nuclear@49 299 move_sound->play();
nuclear@49 300 }
nuclear@49 301 } else {
nuclear@49 302 if(move_sound->get_sample()) {
nuclear@49 303 move_sound->stop();
nuclear@49 304 move_sound->set_sample(0);
nuclear@49 305 }
nuclear@48 306 }
nuclear@48 307 }
nuclear@48 308
nuclear@7 309 last_upd = msec;
nuclear@1 310 }
nuclear@1 311
nuclear@1 312 void reshape(int x, int y)
nuclear@1 313 {
nuclear@1 314 glViewport(0, 0, x, y);
nuclear@18 315 cfg.width = x;
nuclear@18 316 cfg.height = y;
nuclear@30 317
nuclear@41 318 rend->resize(x, y);
nuclear@1 319 }
nuclear@1 320
nuclear@18 321 static bool stereo_shift_pressed;
nuclear@18 322
nuclear@1 323 void keyb(unsigned char key, int x, int y)
nuclear@1 324 {
nuclear@1 325 switch(key) {
nuclear@1 326 case 27:
nuclear@1 327 exit(0);
nuclear@18 328
nuclear@24 329 case '`':
nuclear@24 330 show_con = true;
nuclear@24 331 glutKeyboardFunc(keyb_con);
nuclear@24 332 glutKeyboardUpFunc(0);
nuclear@24 333 glutPostRedisplay();
nuclear@24 334 break;
nuclear@24 335
nuclear@18 336 case 'z':
nuclear@18 337 stereo_shift_pressed = true;
nuclear@18 338 break;
nuclear@18 339
nuclear@48 340 case 'p':
nuclear@48 341 {
nuclear@48 342 Vector3 pos = cam.get_position();
nuclear@48 343 int cell_x, cell_y;
nuclear@48 344 level->get_cell_coords_at(pos, &cell_x, &cell_y);
nuclear@48 345 printf("Current position: [%.2f %.2f %.2f] cell: [%d %d]\n", pos.x, pos.y, pos.z,
nuclear@48 346 cell_x, cell_y);
nuclear@48 347 }
nuclear@48 348 break;
nuclear@48 349
nuclear@48 350 case 'P':
nuclear@48 351 {
nuclear@48 352 Vector3 pos = cam.get_position();
nuclear@48 353 int cell_x, cell_y;
nuclear@48 354 level->get_cell_coords_at(pos, &cell_x, &cell_y);
nuclear@48 355 AudioSample *sample = level->get_sample(cell_x, cell_y, TILE_SAMPLE_WALK);
nuclear@48 356 printf("walk sample: %p\n", (void*)sample);
nuclear@48 357 }
nuclear@48 358 break;
nuclear@48 359
nuclear@48 360
nuclear@18 361 case '\n':
nuclear@18 362 case '\r':
nuclear@18 363 {
nuclear@18 364 static bool fullscr;
nuclear@18 365 if(glutGetModifiers() & GLUT_ACTIVE_ALT) {
nuclear@18 366 fullscr = !fullscr;
nuclear@18 367 if(fullscr) {
nuclear@18 368 glutFullScreen();
nuclear@18 369 } else {
nuclear@18 370 glutPositionWindow(20, 20);
nuclear@18 371 }
nuclear@18 372 }
nuclear@18 373 }
nuclear@18 374 break;
nuclear@18 375
nuclear@18 376 default:
nuclear@18 377 break;
nuclear@1 378 }
nuclear@7 379
nuclear@7 380 keystate[key] = true;
nuclear@7 381 }
nuclear@7 382
nuclear@7 383 void key_release(unsigned char key, int x, int y)
nuclear@7 384 {
nuclear@18 385 switch(key) {
nuclear@18 386 case 'z':
nuclear@18 387 stereo_shift_pressed = false;
nuclear@18 388 break;
nuclear@18 389
nuclear@18 390 default:
nuclear@18 391 break;
nuclear@18 392 }
nuclear@18 393
nuclear@7 394 keystate[key] = false;
nuclear@1 395 }
nuclear@1 396
nuclear@24 397 void keyb_con(unsigned char key, int x, int y)
nuclear@24 398 {
nuclear@24 399 if(key == '`' || key == 27) {
nuclear@24 400 show_con = false;
nuclear@24 401 glutKeyboardFunc(keyb);
nuclear@24 402 glutKeyboardUpFunc(key_release);
nuclear@24 403 glutPostRedisplay();
nuclear@24 404 } else {
nuclear@24 405 cmdcon_keypress(key);
nuclear@24 406 }
nuclear@24 407 }
nuclear@24 408
nuclear@1 409 static int prev_x, prev_y;
nuclear@1 410 static bool bnstate[32];
nuclear@1 411
nuclear@1 412 void mouse(int bn, int state, int x, int y)
nuclear@1 413 {
nuclear@1 414 prev_x = x;
nuclear@1 415 prev_y = y;
nuclear@1 416 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN;
nuclear@1 417 }
nuclear@1 418
nuclear@1 419 void motion(int x, int y)
nuclear@1 420 {
nuclear@1 421 int dx = x - prev_x;
nuclear@1 422 int dy = y - prev_y;
nuclear@1 423 prev_x = x;
nuclear@1 424 prev_y = y;
nuclear@1 425
nuclear@18 426 if(stereo_shift_pressed) {
nuclear@18 427 if(dy != 0) {
nuclear@18 428 stereo_focus_dist += dy * 0.01;
nuclear@18 429 stereo_eye_sep = stereo_focus_dist / 30.0;
nuclear@18 430 printf("foc: %f, sep: %f\n", stereo_focus_dist, stereo_eye_sep);
nuclear@18 431 glutPostRedisplay();
nuclear@18 432 }
nuclear@18 433 return;
nuclear@18 434 }
nuclear@18 435
nuclear@1 436 if(bnstate[0]) {
nuclear@7 437 cam.input_rotate(dy * 0.01, dx * 0.01, 0);
nuclear@1 438 glutPostRedisplay();
nuclear@1 439 }
nuclear@1 440 if(bnstate[2]) {
nuclear@1 441 cam.input_zoom(dy * 0.1);
nuclear@1 442 glutPostRedisplay();
nuclear@1 443 }
nuclear@1 444 }
nuclear@46 445
nuclear@46 446 unsigned int load_psys_tex(const char *fname, void *cls)
nuclear@46 447 {
nuclear@46 448 TextureSet *texset = tileset->get_textures();
nuclear@48 449 return texset->get(fname);
nuclear@46 450 }