dungeon_crawler

annotate prototype/src/level.cc @ 50:c40efa9cf844

torches sound
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 18 Sep 2012 04:45:46 +0300
parents 303743485aba
children d57df51f6b50
rev   line source
nuclear@1 1 #include <stdio.h>
nuclear@1 2 #include <string.h>
nuclear@5 3 #include <errno.h>
nuclear@1 4 #include "opengl.h"
nuclear@1 5 #include "level.h"
nuclear@1 6 #include "tile.h"
nuclear@5 7 #include "tileset.h"
nuclear@49 8 #include "cfg.h"
nuclear@1 9
nuclear@1 10 Level::Level()
nuclear@1 11 {
nuclear@1 12 cell_size = 1.0;
nuclear@1 13
nuclear@1 14 cells = 0;
nuclear@1 15 xsz = ysz = 0;
nuclear@1 16 }
nuclear@1 17
nuclear@1 18 Level::~Level()
nuclear@1 19 {
nuclear@1 20 delete [] cells;
nuclear@38 21
nuclear@38 22 for(auto cell : cell_list) {
nuclear@38 23 delete cell;
nuclear@38 24 }
nuclear@1 25 }
nuclear@1 26
nuclear@1 27 bool Level::load(const char *fname)
nuclear@1 28 {
nuclear@5 29 if(!fname) {
nuclear@5 30 return false;
nuclear@5 31 }
nuclear@5 32
nuclear@5 33 TileSet *tileset = get_active_tileset();
nuclear@5 34 if(!tileset) {
nuclear@5 35 fprintf(stderr, "level loading failed: no active tileset\n");
nuclear@5 36 return false;
nuclear@5 37 }
nuclear@5 38 Tile *deftile = tileset->get_tile("default");
nuclear@5 39 if(!deftile) {
nuclear@5 40 fprintf(stderr, "level loading failed: active tileset has no default tile\n");
nuclear@5 41 return false;
nuclear@5 42 }
nuclear@5 43
nuclear@5 44 FILE *fp = fopen(fname, "r");
nuclear@5 45 if(!fp) {
nuclear@5 46 fprintf(stderr, "failed to open level: %s: %s\n", fname, strerror(errno));
nuclear@5 47 return false;
nuclear@5 48 }
nuclear@5 49
nuclear@5 50 char buf[512];
nuclear@5 51 fgets(buf, sizeof buf, fp);
nuclear@5 52 if(sscanf(buf, "SIZE %dx%d", &xsz, &ysz) != 2) {
nuclear@5 53 fprintf(stderr, "invalid or corrupt level file: %s\n", fname);
nuclear@5 54 fclose(fp);
nuclear@5 55 return false;
nuclear@5 56 }
nuclear@5 57 printf("level size: %dx%d\n", xsz, ysz);
nuclear@1 58
nuclear@1 59 cells = new GridCell*[xsz * ysz];
nuclear@1 60 memset(cells, 0, xsz * ysz * sizeof *cells);
nuclear@1 61
nuclear@5 62 int y = 0;
nuclear@5 63 GridCell **grid_row = cells;
nuclear@5 64
nuclear@5 65 while(fgets(buf, sizeof buf, fp)) {
nuclear@5 66 for(int i=0; i<xsz; i++) {
nuclear@5 67 if(!buf[i] || buf[i] == '\r' || buf[i] == '\n') {
nuclear@5 68 grid_row += xsz - i;
nuclear@5 69 break;
nuclear@5 70 }
nuclear@5 71
nuclear@5 72 if(isalpha(buf[i]) || buf[i] == ' ') {
nuclear@38 73 GridCell *cell = new GridCell(deftile);
nuclear@38 74 *grid_row = cell;
nuclear@38 75 cell_list.push_back(*grid_row);
nuclear@5 76 }
nuclear@5 77 grid_row++;
nuclear@5 78 }
nuclear@5 79
nuclear@5 80 if(++y >= ysz) {
nuclear@5 81 break;
nuclear@5 82 }
nuclear@5 83 }
nuclear@5 84 fclose(fp);
nuclear@1 85
nuclear@50 86 for(int i=0; i<ysz; i++) {
nuclear@50 87 for(int j=0; j<xsz; j++) {
nuclear@50 88 GridCell *cell = get_cell(j, i);
nuclear@50 89 if(!cell) {
nuclear@50 90 continue;
nuclear@50 91 }
nuclear@50 92
nuclear@50 93 // find the adjacency mask of this cell and store it
nuclear@50 94 unsigned int adjmask = get_cell_dirmask(j, i);
nuclear@50 95 cell->set_adj_mask(adjmask);
nuclear@50 96
nuclear@50 97 // add any audio sources in this grid-cell to the level static audio manager
nuclear@50 98 std::list<Tile::AudioSourceDesc> asrc = cell->get_audio_sources();
nuclear@50 99 for(auto sdesc : asrc) {
nuclear@50 100 if(sdesc.dirmask & adjmask) {
nuclear@50 101 AudioSource *s = new AudioSource;
nuclear@50 102 s->set_sample(sdesc.sample);
nuclear@50 103 s->set_position(sdesc.pos + get_cell_pos(i, y));
nuclear@50 104 austatic.add_source(s);
nuclear@50 105 }
nuclear@50 106 }
nuclear@50 107 }
nuclear@50 108 }
nuclear@50 109
nuclear@1 110 return true;
nuclear@1 111 }
nuclear@1 112
nuclear@1 113 bool Level::save(const char *fname) const
nuclear@1 114 {
nuclear@1 115 return false;
nuclear@1 116 }
nuclear@1 117
nuclear@50 118 GridCell *Level::get_cell(int x, int y)
nuclear@50 119 {
nuclear@50 120 if(x < 0 || x >= xsz || y < 0 || y >= ysz) {
nuclear@50 121 return 0;
nuclear@50 122 }
nuclear@50 123 return cells[y * xsz + x];
nuclear@50 124 }
nuclear@50 125
nuclear@1 126 const GridCell *Level::get_cell(int x, int y) const
nuclear@1 127 {
nuclear@1 128 if(x < 0 || x >= xsz || y < 0 || y >= ysz) {
nuclear@1 129 return 0;
nuclear@1 130 }
nuclear@1 131 return cells[y * xsz + x];
nuclear@1 132 }
nuclear@1 133
nuclear@1 134 Vector3 Level::get_cell_pos(int x, int y) const
nuclear@1 135 {
nuclear@46 136 float posx = (float)x * cell_size;
nuclear@46 137 float posy = (float)y * cell_size;
nuclear@46 138 posx -= cell_size * (float)xsz / 2.0f;
nuclear@46 139 posy -= cell_size * (float)ysz / 2.0f;
nuclear@1 140 return Vector3(posx, 0, posy);
nuclear@1 141 }
nuclear@1 142
nuclear@48 143 void Level::get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const
nuclear@48 144 {
nuclear@48 145 float posx = pos.x + cell_size * (float)xsz / 2.0f;
nuclear@48 146 float posy = pos.z + cell_size * (float)ysz / 2.0f;
nuclear@48 147 *xptr = (int)round(posx / cell_size);
nuclear@48 148 *yptr = (int)round(posy / cell_size);
nuclear@48 149 }
nuclear@48 150
nuclear@23 151 unsigned int Level::get_cell_dirmask(int x, int y) const
nuclear@23 152 {
nuclear@23 153 unsigned int dmask = TILE_ALL;
nuclear@23 154 if(y > 0 && get_cell(x, y - 1)) {
nuclear@23 155 dmask &= ~TILE_NORTH;
nuclear@23 156 }
nuclear@23 157 if(y < ysz - 1 && get_cell(x, y + 1)) {
nuclear@23 158 dmask &= ~TILE_SOUTH;
nuclear@23 159 }
nuclear@23 160 if(x > 0 && get_cell(x - 1, y)) {
nuclear@23 161 dmask &= ~TILE_WEST;
nuclear@23 162 }
nuclear@23 163 if(x < xsz - 1 && get_cell(x + 1, y)) {
nuclear@23 164 dmask &= ~TILE_EAST;
nuclear@23 165 }
nuclear@23 166 return dmask;
nuclear@23 167 }
nuclear@23 168
nuclear@49 169 void Level::set_player_position(const Vector3 &ppos)
nuclear@49 170 {
nuclear@49 171 player_pos = ppos;
nuclear@49 172 }
nuclear@49 173
nuclear@38 174 void Level::update(unsigned long msec, float dt)
nuclear@38 175 {
nuclear@38 176 for(auto cell : cell_list) {
nuclear@38 177 cell->update(msec, dt);
nuclear@38 178 }
nuclear@49 179
nuclear@49 180 // activate the closest audio sources
nuclear@49 181 if(cfg.sound) {
nuclear@49 182 austatic.active_range(player_pos, 2.0);
nuclear@49 183 }
nuclear@38 184 }
nuclear@38 185
nuclear@1 186 void Level::draw() const
nuclear@1 187 {
nuclear@1 188 glMatrixMode(GL_MODELVIEW);
nuclear@1 189
nuclear@1 190 for(int i=0; i<ysz; i++) {
nuclear@1 191 for(int j=0; j<xsz; j++) {
nuclear@1 192 const GridCell *cell = get_cell(j, i);
nuclear@1 193 if(cell) {
nuclear@1 194 Vector3 pos = get_cell_pos(j, i);
nuclear@1 195 glPushMatrix();
nuclear@1 196 glTranslatef(pos.x, pos.y, pos.z);
nuclear@1 197 glScalef(cell_size, cell_size, cell_size);
nuclear@5 198
nuclear@23 199 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@5 200
nuclear@5 201 cell->draw(dmask);
nuclear@1 202 glPopMatrix();
nuclear@1 203 }
nuclear@1 204 }
nuclear@1 205 }
nuclear@1 206 }
nuclear@1 207
nuclear@23 208 void Level::draw_lights() const
nuclear@23 209 {
nuclear@23 210 glMatrixMode(GL_MODELVIEW);
nuclear@23 211
nuclear@23 212 for(int i=0; i<ysz; i++) {
nuclear@23 213 for(int j=0; j<xsz; j++) {
nuclear@23 214 const GridCell *cell = get_cell(j, i);
nuclear@23 215 if(cell) {
nuclear@23 216 Vector3 pos = get_cell_pos(j, i);
nuclear@23 217
nuclear@23 218 glPushMatrix();
nuclear@23 219 glTranslatef(pos.x, pos.y, pos.z);
nuclear@23 220 glScalef(cell_size, cell_size, cell_size);
nuclear@23 221
nuclear@23 222 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@23 223 cell->draw_lights(dmask);
nuclear@23 224
nuclear@23 225 glPopMatrix();
nuclear@23 226 }
nuclear@23 227 }
nuclear@23 228 }
nuclear@23 229 }
nuclear@23 230
nuclear@46 231 void Level::draw_post() const
nuclear@46 232 {
nuclear@46 233 glMatrixMode(GL_MODELVIEW);
nuclear@46 234
nuclear@46 235 for(int i=0; i<ysz; i++) {
nuclear@46 236 for(int j=0; j<xsz; j++) {
nuclear@46 237 const GridCell *cell = get_cell(j, i);
nuclear@46 238 if(cell) {
nuclear@46 239 Vector3 pos = get_cell_pos(j, i);
nuclear@46 240 glPushMatrix();
nuclear@46 241 glTranslatef(pos.x, pos.y, pos.z);
nuclear@46 242 glScalef(cell_size, cell_size, cell_size);
nuclear@46 243
nuclear@46 244 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@46 245
nuclear@46 246 cell->draw_post(dmask);
nuclear@46 247 glPopMatrix();
nuclear@46 248 }
nuclear@46 249 }
nuclear@46 250 }
nuclear@46 251 }
nuclear@46 252
nuclear@1 253 void Level::draw_grid() const
nuclear@1 254 {
nuclear@1 255 float xlen = xsz * cell_size;
nuclear@1 256 float ylen = ysz * cell_size;
nuclear@1 257
nuclear@1 258 glPushAttrib(GL_ENABLE_BIT);
nuclear@1 259 glDisable(GL_LIGHTING);
nuclear@1 260
nuclear@1 261 glBegin(GL_LINES);
nuclear@1 262 glColor3f(0.4, 0.4, 0.4);
nuclear@1 263
nuclear@1 264 float y = -ylen / 2.0 - cell_size / 2.0;
nuclear@1 265 for(int i=0; i<ysz; i++) {
nuclear@1 266 glVertex3f(-xlen / 2.0, 0, y);
nuclear@1 267 glVertex3f(xlen / 2.0, 0, y);
nuclear@1 268 y += cell_size;
nuclear@1 269 }
nuclear@1 270
nuclear@1 271 float x = -xlen / 2.0 - cell_size / 2.0;
nuclear@1 272 for(int i=0; i<xsz; i++) {
nuclear@1 273 glVertex3f(x, 0, -ylen / 2.0);
nuclear@1 274 glVertex3f(x, 0, ylen / 2.0);
nuclear@1 275 x += cell_size;
nuclear@1 276 }
nuclear@1 277 glEnd();
nuclear@1 278
nuclear@1 279 glPopAttrib();
nuclear@1 280 }
nuclear@1 281
nuclear@5 282
nuclear@48 283 AudioSample *Level::get_sample(int x, int y, int which) const
nuclear@48 284 {
nuclear@48 285 const GridCell *cell = get_cell(x, y);
nuclear@48 286 if(!cell) {
nuclear@48 287 return 0;
nuclear@48 288 }
nuclear@48 289 return cell->get_sample(which);
nuclear@48 290 }
nuclear@48 291
nuclear@48 292
nuclear@38 293 GridCell::GridCell(Tile *tile)
nuclear@5 294 {
nuclear@5 295 if(tile) {
nuclear@45 296 add_tile(tile);
nuclear@5 297 }
nuclear@50 298
nuclear@50 299 adjmask = TILE_ALL;
nuclear@50 300 }
nuclear@50 301
nuclear@50 302 void GridCell::set_adj_mask(unsigned int mask)
nuclear@50 303 {
nuclear@50 304 adjmask = mask;
nuclear@50 305 }
nuclear@50 306
nuclear@50 307 unsigned int GridCell::get_adj_mask() const
nuclear@50 308 {
nuclear@50 309 return adjmask;
nuclear@5 310 }
nuclear@5 311
nuclear@38 312 void GridCell::add_tile(Tile *tile)
nuclear@1 313 {
nuclear@45 314 if(!tile) {
nuclear@45 315 return;
nuclear@45 316 }
nuclear@45 317
nuclear@1 318 tiles.push_back(tile);
nuclear@45 319
nuclear@45 320 /* instanciate any particle systems */
nuclear@45 321 int num_psattr = tile->get_unique_psys_count();
nuclear@45 322
nuclear@45 323 for(int i=0; i<num_psattr; i++) {
nuclear@49 324 const struct psys_attributes *psattr = tile->get_unique_psys(i);
nuclear@45 325 struct psys_emitter *emitter = psys_create();
nuclear@49 326 emitter->attr = *psattr;
nuclear@45 327 psys.push_back(emitter);
nuclear@45 328 }
nuclear@1 329 }
nuclear@1 330
nuclear@38 331 void GridCell::update(unsigned long msec, float dt)
nuclear@38 332 {
nuclear@45 333 for(auto ps : psys) {
nuclear@45 334 psys_update(ps, (float)msec / 1000.0f);
nuclear@45 335 }
nuclear@38 336 }
nuclear@38 337
nuclear@5 338 void GridCell::draw(unsigned int draw_mask) const
nuclear@1 339 {
nuclear@23 340 for(auto tile : tiles) {
nuclear@23 341 tile->draw(draw_mask);
nuclear@1 342 }
nuclear@1 343 }
nuclear@23 344
nuclear@23 345 void GridCell::draw_lights(unsigned int draw_mask) const
nuclear@23 346 {
nuclear@23 347 for(auto tile : tiles) {
nuclear@23 348 tile->draw_lights(draw_mask);
nuclear@23 349 }
nuclear@23 350 }
nuclear@45 351
nuclear@45 352 void GridCell::draw_post(unsigned int draw_mask) const
nuclear@45 353 {
nuclear@45 354 for(auto tile : tiles) {
nuclear@45 355 tile->draw_post(draw_mask);
nuclear@45 356 }
nuclear@45 357 for(auto ps : psys) {
nuclear@45 358 psys_draw(ps);
nuclear@45 359 }
nuclear@45 360 }
nuclear@48 361
nuclear@48 362 AudioSample *GridCell::get_sample(int which) const
nuclear@48 363 {
nuclear@48 364 for(auto tile : tiles) {
nuclear@48 365 AudioSample *s = tile->get_sample(which);
nuclear@48 366 if(s) {
nuclear@48 367 return s;
nuclear@48 368 }
nuclear@48 369 }
nuclear@48 370 return 0;
nuclear@48 371 }
nuclear@49 372
nuclear@49 373 std::list<Tile::AudioSourceDesc> GridCell::get_audio_sources() const
nuclear@49 374 {
nuclear@49 375 std::list<Tile::AudioSourceDesc> srclist;
nuclear@49 376
nuclear@49 377 for(auto tile : tiles) {
nuclear@49 378 int num_src = tile->get_audio_source_count();
nuclear@49 379 for(int i=0; i<num_src; i++) {
nuclear@49 380 srclist.push_back(tile->get_audio_source(i));
nuclear@49 381 }
nuclear@49 382 }
nuclear@49 383 return srclist;
nuclear@49 384 }