dungeon_crawler

annotate prototype/src/level.cc @ 48:aa9e28670ae2

added sound playback, more to do
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 17 Sep 2012 08:40:59 +0300
parents f3030df27110
children 303743485aba
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@1 8
nuclear@1 9 Level::Level()
nuclear@1 10 {
nuclear@1 11 cell_size = 1.0;
nuclear@1 12
nuclear@1 13 cells = 0;
nuclear@1 14 xsz = ysz = 0;
nuclear@1 15 }
nuclear@1 16
nuclear@1 17 Level::~Level()
nuclear@1 18 {
nuclear@1 19 delete [] cells;
nuclear@38 20
nuclear@38 21 for(auto cell : cell_list) {
nuclear@38 22 delete cell;
nuclear@38 23 }
nuclear@1 24 }
nuclear@1 25
nuclear@1 26 bool Level::load(const char *fname)
nuclear@1 27 {
nuclear@5 28 if(!fname) {
nuclear@5 29 return false;
nuclear@5 30 }
nuclear@5 31
nuclear@5 32 TileSet *tileset = get_active_tileset();
nuclear@5 33 if(!tileset) {
nuclear@5 34 fprintf(stderr, "level loading failed: no active tileset\n");
nuclear@5 35 return false;
nuclear@5 36 }
nuclear@5 37 Tile *deftile = tileset->get_tile("default");
nuclear@5 38 if(!deftile) {
nuclear@5 39 fprintf(stderr, "level loading failed: active tileset has no default tile\n");
nuclear@5 40 return false;
nuclear@5 41 }
nuclear@5 42
nuclear@5 43 FILE *fp = fopen(fname, "r");
nuclear@5 44 if(!fp) {
nuclear@5 45 fprintf(stderr, "failed to open level: %s: %s\n", fname, strerror(errno));
nuclear@5 46 return false;
nuclear@5 47 }
nuclear@5 48
nuclear@5 49 char buf[512];
nuclear@5 50 fgets(buf, sizeof buf, fp);
nuclear@5 51 if(sscanf(buf, "SIZE %dx%d", &xsz, &ysz) != 2) {
nuclear@5 52 fprintf(stderr, "invalid or corrupt level file: %s\n", fname);
nuclear@5 53 fclose(fp);
nuclear@5 54 return false;
nuclear@5 55 }
nuclear@5 56 printf("level size: %dx%d\n", xsz, ysz);
nuclear@1 57
nuclear@1 58 cells = new GridCell*[xsz * ysz];
nuclear@1 59 memset(cells, 0, xsz * ysz * sizeof *cells);
nuclear@1 60
nuclear@5 61 int y = 0;
nuclear@5 62 GridCell **grid_row = cells;
nuclear@5 63
nuclear@5 64 while(fgets(buf, sizeof buf, fp)) {
nuclear@5 65 for(int i=0; i<xsz; i++) {
nuclear@5 66 if(!buf[i] || buf[i] == '\r' || buf[i] == '\n') {
nuclear@5 67 grid_row += xsz - i;
nuclear@5 68 break;
nuclear@5 69 }
nuclear@5 70
nuclear@5 71 if(isalpha(buf[i]) || buf[i] == ' ') {
nuclear@38 72 GridCell *cell = new GridCell(deftile);
nuclear@38 73 *grid_row = cell;
nuclear@38 74 cell_list.push_back(*grid_row);
nuclear@5 75 }
nuclear@5 76 grid_row++;
nuclear@5 77 }
nuclear@5 78
nuclear@5 79 if(++y >= ysz) {
nuclear@5 80 break;
nuclear@5 81 }
nuclear@5 82 }
nuclear@5 83 fclose(fp);
nuclear@1 84
nuclear@1 85 return true;
nuclear@1 86 }
nuclear@1 87
nuclear@1 88 bool Level::save(const char *fname) const
nuclear@1 89 {
nuclear@1 90 return false;
nuclear@1 91 }
nuclear@1 92
nuclear@1 93 const GridCell *Level::get_cell(int x, int y) const
nuclear@1 94 {
nuclear@1 95 if(x < 0 || x >= xsz || y < 0 || y >= ysz) {
nuclear@1 96 return 0;
nuclear@1 97 }
nuclear@1 98 return cells[y * xsz + x];
nuclear@1 99 }
nuclear@1 100
nuclear@1 101 Vector3 Level::get_cell_pos(int x, int y) const
nuclear@1 102 {
nuclear@46 103 float posx = (float)x * cell_size;
nuclear@46 104 float posy = (float)y * cell_size;
nuclear@46 105 posx -= cell_size * (float)xsz / 2.0f;
nuclear@46 106 posy -= cell_size * (float)ysz / 2.0f;
nuclear@1 107 return Vector3(posx, 0, posy);
nuclear@1 108 }
nuclear@1 109
nuclear@48 110 void Level::get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const
nuclear@48 111 {
nuclear@48 112 float posx = pos.x + cell_size * (float)xsz / 2.0f;
nuclear@48 113 float posy = pos.z + cell_size * (float)ysz / 2.0f;
nuclear@48 114 *xptr = (int)round(posx / cell_size);
nuclear@48 115 *yptr = (int)round(posy / cell_size);
nuclear@48 116 }
nuclear@48 117
nuclear@23 118 unsigned int Level::get_cell_dirmask(int x, int y) const
nuclear@23 119 {
nuclear@23 120 unsigned int dmask = TILE_ALL;
nuclear@23 121 if(y > 0 && get_cell(x, y - 1)) {
nuclear@23 122 dmask &= ~TILE_NORTH;
nuclear@23 123 }
nuclear@23 124 if(y < ysz - 1 && get_cell(x, y + 1)) {
nuclear@23 125 dmask &= ~TILE_SOUTH;
nuclear@23 126 }
nuclear@23 127 if(x > 0 && get_cell(x - 1, y)) {
nuclear@23 128 dmask &= ~TILE_WEST;
nuclear@23 129 }
nuclear@23 130 if(x < xsz - 1 && get_cell(x + 1, y)) {
nuclear@23 131 dmask &= ~TILE_EAST;
nuclear@23 132 }
nuclear@23 133 return dmask;
nuclear@23 134 }
nuclear@23 135
nuclear@38 136 void Level::update(unsigned long msec, float dt)
nuclear@38 137 {
nuclear@38 138 for(auto cell : cell_list) {
nuclear@38 139 cell->update(msec, dt);
nuclear@38 140 }
nuclear@38 141 }
nuclear@38 142
nuclear@1 143 void Level::draw() const
nuclear@1 144 {
nuclear@1 145 glMatrixMode(GL_MODELVIEW);
nuclear@1 146
nuclear@1 147 for(int i=0; i<ysz; i++) {
nuclear@1 148 for(int j=0; j<xsz; j++) {
nuclear@1 149 const GridCell *cell = get_cell(j, i);
nuclear@1 150 if(cell) {
nuclear@1 151 Vector3 pos = get_cell_pos(j, i);
nuclear@1 152 glPushMatrix();
nuclear@1 153 glTranslatef(pos.x, pos.y, pos.z);
nuclear@1 154 glScalef(cell_size, cell_size, cell_size);
nuclear@5 155
nuclear@23 156 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@5 157
nuclear@5 158 cell->draw(dmask);
nuclear@1 159 glPopMatrix();
nuclear@1 160 }
nuclear@1 161 }
nuclear@1 162 }
nuclear@1 163 }
nuclear@1 164
nuclear@23 165 void Level::draw_lights() const
nuclear@23 166 {
nuclear@23 167 glMatrixMode(GL_MODELVIEW);
nuclear@23 168
nuclear@23 169 for(int i=0; i<ysz; i++) {
nuclear@23 170 for(int j=0; j<xsz; j++) {
nuclear@23 171 const GridCell *cell = get_cell(j, i);
nuclear@23 172 if(cell) {
nuclear@23 173 Vector3 pos = get_cell_pos(j, i);
nuclear@23 174
nuclear@23 175 glPushMatrix();
nuclear@23 176 glTranslatef(pos.x, pos.y, pos.z);
nuclear@23 177 glScalef(cell_size, cell_size, cell_size);
nuclear@23 178
nuclear@23 179 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@23 180 cell->draw_lights(dmask);
nuclear@23 181
nuclear@23 182 glPopMatrix();
nuclear@23 183 }
nuclear@23 184 }
nuclear@23 185 }
nuclear@23 186 }
nuclear@23 187
nuclear@46 188 void Level::draw_post() const
nuclear@46 189 {
nuclear@46 190 glMatrixMode(GL_MODELVIEW);
nuclear@46 191
nuclear@46 192 for(int i=0; i<ysz; i++) {
nuclear@46 193 for(int j=0; j<xsz; j++) {
nuclear@46 194 const GridCell *cell = get_cell(j, i);
nuclear@46 195 if(cell) {
nuclear@46 196 Vector3 pos = get_cell_pos(j, i);
nuclear@46 197 glPushMatrix();
nuclear@46 198 glTranslatef(pos.x, pos.y, pos.z);
nuclear@46 199 glScalef(cell_size, cell_size, cell_size);
nuclear@46 200
nuclear@46 201 unsigned int dmask = get_cell_dirmask(j, i);
nuclear@46 202
nuclear@46 203 cell->draw_post(dmask);
nuclear@46 204 glPopMatrix();
nuclear@46 205 }
nuclear@46 206 }
nuclear@46 207 }
nuclear@46 208 }
nuclear@46 209
nuclear@1 210 void Level::draw_grid() const
nuclear@1 211 {
nuclear@1 212 float xlen = xsz * cell_size;
nuclear@1 213 float ylen = ysz * cell_size;
nuclear@1 214
nuclear@1 215 glPushAttrib(GL_ENABLE_BIT);
nuclear@1 216 glDisable(GL_LIGHTING);
nuclear@1 217
nuclear@1 218 glBegin(GL_LINES);
nuclear@1 219 glColor3f(0.4, 0.4, 0.4);
nuclear@1 220
nuclear@1 221 float y = -ylen / 2.0 - cell_size / 2.0;
nuclear@1 222 for(int i=0; i<ysz; i++) {
nuclear@1 223 glVertex3f(-xlen / 2.0, 0, y);
nuclear@1 224 glVertex3f(xlen / 2.0, 0, y);
nuclear@1 225 y += cell_size;
nuclear@1 226 }
nuclear@1 227
nuclear@1 228 float x = -xlen / 2.0 - cell_size / 2.0;
nuclear@1 229 for(int i=0; i<xsz; i++) {
nuclear@1 230 glVertex3f(x, 0, -ylen / 2.0);
nuclear@1 231 glVertex3f(x, 0, ylen / 2.0);
nuclear@1 232 x += cell_size;
nuclear@1 233 }
nuclear@1 234 glEnd();
nuclear@1 235
nuclear@1 236 glPopAttrib();
nuclear@1 237 }
nuclear@1 238
nuclear@5 239
nuclear@48 240 AudioSample *Level::get_sample(int x, int y, int which) const
nuclear@48 241 {
nuclear@48 242 const GridCell *cell = get_cell(x, y);
nuclear@48 243 if(!cell) {
nuclear@48 244 return 0;
nuclear@48 245 }
nuclear@48 246 return cell->get_sample(which);
nuclear@48 247 }
nuclear@48 248
nuclear@48 249
nuclear@38 250 GridCell::GridCell(Tile *tile)
nuclear@5 251 {
nuclear@5 252 if(tile) {
nuclear@45 253 add_tile(tile);
nuclear@5 254 }
nuclear@5 255 }
nuclear@5 256
nuclear@38 257 void GridCell::add_tile(Tile *tile)
nuclear@1 258 {
nuclear@45 259 if(!tile) {
nuclear@45 260 return;
nuclear@45 261 }
nuclear@45 262
nuclear@1 263 tiles.push_back(tile);
nuclear@45 264
nuclear@45 265 /* instanciate any particle systems */
nuclear@46 266 const struct psys_attributes * const *psattr = tile->get_unique_psys();
nuclear@45 267 int num_psattr = tile->get_unique_psys_count();
nuclear@45 268
nuclear@45 269 for(int i=0; i<num_psattr; i++) {
nuclear@45 270 struct psys_emitter *emitter = psys_create();
nuclear@45 271 emitter->attr = *psattr[i];
nuclear@45 272 psys.push_back(emitter);
nuclear@45 273 }
nuclear@1 274 }
nuclear@1 275
nuclear@38 276 void GridCell::update(unsigned long msec, float dt)
nuclear@38 277 {
nuclear@45 278 for(auto ps : psys) {
nuclear@45 279 psys_update(ps, (float)msec / 1000.0f);
nuclear@45 280 }
nuclear@38 281 }
nuclear@38 282
nuclear@5 283 void GridCell::draw(unsigned int draw_mask) const
nuclear@1 284 {
nuclear@23 285 for(auto tile : tiles) {
nuclear@23 286 tile->draw(draw_mask);
nuclear@1 287 }
nuclear@1 288 }
nuclear@23 289
nuclear@23 290 void GridCell::draw_lights(unsigned int draw_mask) const
nuclear@23 291 {
nuclear@23 292 for(auto tile : tiles) {
nuclear@23 293 tile->draw_lights(draw_mask);
nuclear@23 294 }
nuclear@23 295 }
nuclear@45 296
nuclear@45 297 void GridCell::draw_post(unsigned int draw_mask) const
nuclear@45 298 {
nuclear@45 299 for(auto tile : tiles) {
nuclear@45 300 tile->draw_post(draw_mask);
nuclear@45 301 }
nuclear@45 302 for(auto ps : psys) {
nuclear@45 303 psys_draw(ps);
nuclear@45 304 }
nuclear@45 305 }
nuclear@48 306
nuclear@48 307 AudioSample *GridCell::get_sample(int which) const
nuclear@48 308 {
nuclear@48 309 for(auto tile : tiles) {
nuclear@48 310 AudioSample *s = tile->get_sample(which);
nuclear@48 311 if(s) {
nuclear@48 312 return s;
nuclear@48 313 }
nuclear@48 314 }
nuclear@48 315 return 0;
nuclear@48 316 }