dungeon_crawler

annotate prototype/src/level.cc @ 49:303743485aba

pretty much implemented the positional torch sound sources
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 18 Sep 2012 00:34:29 +0300
parents aa9e28670ae2
children c40efa9cf844
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@49 76
nuclear@49 77 // add any audio sources in this grid-cell to the level static audio manager
nuclear@49 78 std::list<Tile::AudioSourceDesc> asrc = cell->get_audio_sources();
nuclear@49 79 for(auto sdesc : asrc) {
nuclear@49 80 AudioSource *s = new AudioSource;
nuclear@49 81 s->set_sample(sdesc.sample);
nuclear@49 82 s->set_position(sdesc.pos + get_cell_pos(i, y));
nuclear@49 83 austatic.add_source(s);
nuclear@49 84 }
nuclear@5 85 }
nuclear@5 86 grid_row++;
nuclear@5 87 }
nuclear@5 88
nuclear@5 89 if(++y >= ysz) {
nuclear@5 90 break;
nuclear@5 91 }
nuclear@5 92 }
nuclear@5 93 fclose(fp);
nuclear@1 94
nuclear@1 95 return true;
nuclear@1 96 }
nuclear@1 97
nuclear@1 98 bool Level::save(const char *fname) const
nuclear@1 99 {
nuclear@1 100 return false;
nuclear@1 101 }
nuclear@1 102
nuclear@1 103 const GridCell *Level::get_cell(int x, int y) const
nuclear@1 104 {
nuclear@1 105 if(x < 0 || x >= xsz || y < 0 || y >= ysz) {
nuclear@1 106 return 0;
nuclear@1 107 }
nuclear@1 108 return cells[y * xsz + x];
nuclear@1 109 }
nuclear@1 110
nuclear@1 111 Vector3 Level::get_cell_pos(int x, int y) const
nuclear@1 112 {
nuclear@46 113 float posx = (float)x * cell_size;
nuclear@46 114 float posy = (float)y * cell_size;
nuclear@46 115 posx -= cell_size * (float)xsz / 2.0f;
nuclear@46 116 posy -= cell_size * (float)ysz / 2.0f;
nuclear@1 117 return Vector3(posx, 0, posy);
nuclear@1 118 }
nuclear@1 119
nuclear@48 120 void Level::get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const
nuclear@48 121 {
nuclear@48 122 float posx = pos.x + cell_size * (float)xsz / 2.0f;
nuclear@48 123 float posy = pos.z + cell_size * (float)ysz / 2.0f;
nuclear@48 124 *xptr = (int)round(posx / cell_size);
nuclear@48 125 *yptr = (int)round(posy / cell_size);
nuclear@48 126 }
nuclear@48 127
nuclear@23 128 unsigned int Level::get_cell_dirmask(int x, int y) const
nuclear@23 129 {
nuclear@23 130 unsigned int dmask = TILE_ALL;
nuclear@23 131 if(y > 0 && get_cell(x, y - 1)) {
nuclear@23 132 dmask &= ~TILE_NORTH;
nuclear@23 133 }
nuclear@23 134 if(y < ysz - 1 && get_cell(x, y + 1)) {
nuclear@23 135 dmask &= ~TILE_SOUTH;
nuclear@23 136 }
nuclear@23 137 if(x > 0 && get_cell(x - 1, y)) {
nuclear@23 138 dmask &= ~TILE_WEST;
nuclear@23 139 }
nuclear@23 140 if(x < xsz - 1 && get_cell(x + 1, y)) {
nuclear@23 141 dmask &= ~TILE_EAST;
nuclear@23 142 }
nuclear@23 143 return dmask;
nuclear@23 144 }
nuclear@23 145
nuclear@49 146 void Level::set_player_position(const Vector3 &ppos)
nuclear@49 147 {
nuclear@49 148 player_pos = ppos;
nuclear@49 149 }
nuclear@49 150
nuclear@38 151 void Level::update(unsigned long msec, float dt)
nuclear@38 152 {
nuclear@38 153 for(auto cell : cell_list) {
nuclear@38 154 cell->update(msec, dt);
nuclear@38 155 }
nuclear@49 156
nuclear@49 157 // activate the closest audio sources
nuclear@49 158 if(cfg.sound) {
nuclear@49 159 austatic.active_range(player_pos, 2.0);
nuclear@49 160 }
nuclear@38 161 }
nuclear@38 162
nuclear@1 163 void Level::draw() const
nuclear@1 164 {
nuclear@1 165 glMatrixMode(GL_MODELVIEW);
nuclear@1 166
nuclear@1 167 for(int i=0; i<ysz; i++) {
nuclear@1 168 for(int j=0; j<xsz; j++) {
nuclear@1 169 const GridCell *cell = get_cell(j, i);
nuclear@1 170 if(cell) {
nuclear@1 171 Vector3 pos = get_cell_pos(j, i);
nuclear@1 172 glPushMatrix();
nuclear@1 173 glTranslatef(pos.x, pos.y, pos.z);
nuclear@1 174 glScalef(cell_size, cell_size, cell_size);
nuclear@5 175
nuclear@23 176 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@5 177
nuclear@5 178 cell->draw(dmask);
nuclear@1 179 glPopMatrix();
nuclear@1 180 }
nuclear@1 181 }
nuclear@1 182 }
nuclear@1 183 }
nuclear@1 184
nuclear@23 185 void Level::draw_lights() const
nuclear@23 186 {
nuclear@23 187 glMatrixMode(GL_MODELVIEW);
nuclear@23 188
nuclear@23 189 for(int i=0; i<ysz; i++) {
nuclear@23 190 for(int j=0; j<xsz; j++) {
nuclear@23 191 const GridCell *cell = get_cell(j, i);
nuclear@23 192 if(cell) {
nuclear@23 193 Vector3 pos = get_cell_pos(j, i);
nuclear@23 194
nuclear@23 195 glPushMatrix();
nuclear@23 196 glTranslatef(pos.x, pos.y, pos.z);
nuclear@23 197 glScalef(cell_size, cell_size, cell_size);
nuclear@23 198
nuclear@23 199 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@23 200 cell->draw_lights(dmask);
nuclear@23 201
nuclear@23 202 glPopMatrix();
nuclear@23 203 }
nuclear@23 204 }
nuclear@23 205 }
nuclear@23 206 }
nuclear@23 207
nuclear@46 208 void Level::draw_post() const
nuclear@46 209 {
nuclear@46 210 glMatrixMode(GL_MODELVIEW);
nuclear@46 211
nuclear@46 212 for(int i=0; i<ysz; i++) {
nuclear@46 213 for(int j=0; j<xsz; j++) {
nuclear@46 214 const GridCell *cell = get_cell(j, i);
nuclear@46 215 if(cell) {
nuclear@46 216 Vector3 pos = get_cell_pos(j, i);
nuclear@46 217 glPushMatrix();
nuclear@46 218 glTranslatef(pos.x, pos.y, pos.z);
nuclear@46 219 glScalef(cell_size, cell_size, cell_size);
nuclear@46 220
nuclear@46 221 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@46 222
nuclear@46 223 cell->draw_post(dmask);
nuclear@46 224 glPopMatrix();
nuclear@46 225 }
nuclear@46 226 }
nuclear@46 227 }
nuclear@46 228 }
nuclear@46 229
nuclear@1 230 void Level::draw_grid() const
nuclear@1 231 {
nuclear@1 232 float xlen = xsz * cell_size;
nuclear@1 233 float ylen = ysz * cell_size;
nuclear@1 234
nuclear@1 235 glPushAttrib(GL_ENABLE_BIT);
nuclear@1 236 glDisable(GL_LIGHTING);
nuclear@1 237
nuclear@1 238 glBegin(GL_LINES);
nuclear@1 239 glColor3f(0.4, 0.4, 0.4);
nuclear@1 240
nuclear@1 241 float y = -ylen / 2.0 - cell_size / 2.0;
nuclear@1 242 for(int i=0; i<ysz; i++) {
nuclear@1 243 glVertex3f(-xlen / 2.0, 0, y);
nuclear@1 244 glVertex3f(xlen / 2.0, 0, y);
nuclear@1 245 y += cell_size;
nuclear@1 246 }
nuclear@1 247
nuclear@1 248 float x = -xlen / 2.0 - cell_size / 2.0;
nuclear@1 249 for(int i=0; i<xsz; i++) {
nuclear@1 250 glVertex3f(x, 0, -ylen / 2.0);
nuclear@1 251 glVertex3f(x, 0, ylen / 2.0);
nuclear@1 252 x += cell_size;
nuclear@1 253 }
nuclear@1 254 glEnd();
nuclear@1 255
nuclear@1 256 glPopAttrib();
nuclear@1 257 }
nuclear@1 258
nuclear@5 259
nuclear@48 260 AudioSample *Level::get_sample(int x, int y, int which) const
nuclear@48 261 {
nuclear@48 262 const GridCell *cell = get_cell(x, y);
nuclear@48 263 if(!cell) {
nuclear@48 264 return 0;
nuclear@48 265 }
nuclear@48 266 return cell->get_sample(which);
nuclear@48 267 }
nuclear@48 268
nuclear@48 269
nuclear@38 270 GridCell::GridCell(Tile *tile)
nuclear@5 271 {
nuclear@5 272 if(tile) {
nuclear@45 273 add_tile(tile);
nuclear@5 274 }
nuclear@5 275 }
nuclear@5 276
nuclear@38 277 void GridCell::add_tile(Tile *tile)
nuclear@1 278 {
nuclear@45 279 if(!tile) {
nuclear@45 280 return;
nuclear@45 281 }
nuclear@45 282
nuclear@1 283 tiles.push_back(tile);
nuclear@45 284
nuclear@45 285 /* instanciate any particle systems */
nuclear@45 286 int num_psattr = tile->get_unique_psys_count();
nuclear@45 287
nuclear@45 288 for(int i=0; i<num_psattr; i++) {
nuclear@49 289 const struct psys_attributes *psattr = tile->get_unique_psys(i);
nuclear@45 290 struct psys_emitter *emitter = psys_create();
nuclear@49 291 emitter->attr = *psattr;
nuclear@45 292 psys.push_back(emitter);
nuclear@45 293 }
nuclear@1 294 }
nuclear@1 295
nuclear@38 296 void GridCell::update(unsigned long msec, float dt)
nuclear@38 297 {
nuclear@45 298 for(auto ps : psys) {
nuclear@45 299 psys_update(ps, (float)msec / 1000.0f);
nuclear@45 300 }
nuclear@38 301 }
nuclear@38 302
nuclear@5 303 void GridCell::draw(unsigned int draw_mask) const
nuclear@1 304 {
nuclear@23 305 for(auto tile : tiles) {
nuclear@23 306 tile->draw(draw_mask);
nuclear@1 307 }
nuclear@1 308 }
nuclear@23 309
nuclear@23 310 void GridCell::draw_lights(unsigned int draw_mask) const
nuclear@23 311 {
nuclear@23 312 for(auto tile : tiles) {
nuclear@23 313 tile->draw_lights(draw_mask);
nuclear@23 314 }
nuclear@23 315 }
nuclear@45 316
nuclear@45 317 void GridCell::draw_post(unsigned int draw_mask) const
nuclear@45 318 {
nuclear@45 319 for(auto tile : tiles) {
nuclear@45 320 tile->draw_post(draw_mask);
nuclear@45 321 }
nuclear@45 322 for(auto ps : psys) {
nuclear@45 323 psys_draw(ps);
nuclear@45 324 }
nuclear@45 325 }
nuclear@48 326
nuclear@48 327 AudioSample *GridCell::get_sample(int which) const
nuclear@48 328 {
nuclear@48 329 for(auto tile : tiles) {
nuclear@48 330 AudioSample *s = tile->get_sample(which);
nuclear@48 331 if(s) {
nuclear@48 332 return s;
nuclear@48 333 }
nuclear@48 334 }
nuclear@48 335 return 0;
nuclear@48 336 }
nuclear@49 337
nuclear@49 338 std::list<Tile::AudioSourceDesc> GridCell::get_audio_sources() const
nuclear@49 339 {
nuclear@49 340 std::list<Tile::AudioSourceDesc> srclist;
nuclear@49 341
nuclear@49 342 for(auto tile : tiles) {
nuclear@49 343 int num_src = tile->get_audio_source_count();
nuclear@49 344 for(int i=0; i<num_src; i++) {
nuclear@49 345 srclist.push_back(tile->get_audio_source(i));
nuclear@49 346 }
nuclear@49 347 }
nuclear@49 348 return srclist;
nuclear@49 349 }