nuclear@1: #include nuclear@1: #include nuclear@5: #include nuclear@1: #include "opengl.h" nuclear@1: #include "level.h" nuclear@1: #include "tile.h" nuclear@5: #include "tileset.h" nuclear@49: #include "cfg.h" nuclear@1: nuclear@1: Level::Level() nuclear@1: { nuclear@1: cell_size = 1.0; nuclear@1: nuclear@1: cells = 0; nuclear@1: xsz = ysz = 0; nuclear@1: } nuclear@1: nuclear@1: Level::~Level() nuclear@1: { nuclear@1: delete [] cells; nuclear@38: nuclear@38: for(auto cell : cell_list) { nuclear@38: delete cell; nuclear@38: } nuclear@1: } nuclear@1: nuclear@1: bool Level::load(const char *fname) nuclear@1: { nuclear@5: if(!fname) { nuclear@5: return false; nuclear@5: } nuclear@5: nuclear@5: TileSet *tileset = get_active_tileset(); nuclear@5: if(!tileset) { nuclear@5: fprintf(stderr, "level loading failed: no active tileset\n"); nuclear@5: return false; nuclear@5: } nuclear@5: Tile *deftile = tileset->get_tile("default"); nuclear@5: if(!deftile) { nuclear@5: fprintf(stderr, "level loading failed: active tileset has no default tile\n"); nuclear@5: return false; nuclear@5: } nuclear@5: nuclear@5: FILE *fp = fopen(fname, "r"); nuclear@5: if(!fp) { nuclear@5: fprintf(stderr, "failed to open level: %s: %s\n", fname, strerror(errno)); nuclear@5: return false; nuclear@5: } nuclear@5: nuclear@5: char buf[512]; nuclear@5: fgets(buf, sizeof buf, fp); nuclear@5: if(sscanf(buf, "SIZE %dx%d", &xsz, &ysz) != 2) { nuclear@5: fprintf(stderr, "invalid or corrupt level file: %s\n", fname); nuclear@5: fclose(fp); nuclear@5: return false; nuclear@5: } nuclear@5: printf("level size: %dx%d\n", xsz, ysz); nuclear@1: nuclear@1: cells = new GridCell*[xsz * ysz]; nuclear@1: memset(cells, 0, xsz * ysz * sizeof *cells); nuclear@1: nuclear@5: int y = 0; nuclear@5: GridCell **grid_row = cells; nuclear@5: nuclear@5: while(fgets(buf, sizeof buf, fp)) { nuclear@5: for(int i=0; iget_tile("light"))) { nuclear@58: fprintf(stderr, "failed to add light tile\n"); nuclear@58: } nuclear@58: break; nuclear@58: nuclear@58: default: nuclear@58: tile = 0; nuclear@58: break; nuclear@58: } nuclear@58: nuclear@58: if(tile) { nuclear@58: cell->add_tile(tile); nuclear@58: } nuclear@5: } nuclear@5: grid_row++; nuclear@5: } nuclear@5: nuclear@5: if(++y >= ysz) { nuclear@5: break; nuclear@5: } nuclear@5: } nuclear@5: fclose(fp); nuclear@1: nuclear@50: for(int i=0; iset_adj_mask(adjmask); nuclear@50: nuclear@50: // add any audio sources in this grid-cell to the level static audio manager nuclear@50: std::list asrc = cell->get_audio_sources(); nuclear@50: for(auto sdesc : asrc) { nuclear@50: if(sdesc.dirmask & adjmask) { nuclear@51: Vector3 pos = sdesc.pos + get_cell_pos(j, i); nuclear@51: nuclear@50: AudioSource *s = new AudioSource; nuclear@50: s->set_sample(sdesc.sample); nuclear@51: s->set_position(pos); nuclear@51: s->set_volume(sdesc.volume); nuclear@51: s->set_reference_dist(sdesc.ref_dist); nuclear@51: //s->set_rolloff(1.0); nuclear@50: austatic.add_source(s); nuclear@50: } nuclear@50: } nuclear@50: } nuclear@50: } nuclear@50: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool Level::save(const char *fname) const nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@50: GridCell *Level::get_cell(int x, int y) nuclear@50: { nuclear@50: if(x < 0 || x >= xsz || y < 0 || y >= ysz) { nuclear@50: return 0; nuclear@50: } nuclear@50: return cells[y * xsz + x]; nuclear@50: } nuclear@50: nuclear@1: const GridCell *Level::get_cell(int x, int y) const nuclear@1: { nuclear@1: if(x < 0 || x >= xsz || y < 0 || y >= ysz) { nuclear@1: return 0; nuclear@1: } nuclear@1: return cells[y * xsz + x]; nuclear@1: } nuclear@1: nuclear@1: Vector3 Level::get_cell_pos(int x, int y) const nuclear@1: { nuclear@46: float posx = (float)x * cell_size; nuclear@46: float posy = (float)y * cell_size; nuclear@46: posx -= cell_size * (float)xsz / 2.0f; nuclear@46: posy -= cell_size * (float)ysz / 2.0f; nuclear@1: return Vector3(posx, 0, posy); nuclear@1: } nuclear@1: nuclear@48: void Level::get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const nuclear@48: { nuclear@48: float posx = pos.x + cell_size * (float)xsz / 2.0f; nuclear@48: float posy = pos.z + cell_size * (float)ysz / 2.0f; nuclear@48: *xptr = (int)round(posx / cell_size); nuclear@48: *yptr = (int)round(posy / cell_size); nuclear@48: } nuclear@48: nuclear@23: unsigned int Level::get_cell_dirmask(int x, int y) const nuclear@23: { nuclear@23: unsigned int dmask = TILE_ALL; nuclear@23: if(y > 0 && get_cell(x, y - 1)) { nuclear@23: dmask &= ~TILE_NORTH; nuclear@23: } nuclear@23: if(y < ysz - 1 && get_cell(x, y + 1)) { nuclear@23: dmask &= ~TILE_SOUTH; nuclear@23: } nuclear@23: if(x > 0 && get_cell(x - 1, y)) { nuclear@23: dmask &= ~TILE_WEST; nuclear@23: } nuclear@23: if(x < xsz - 1 && get_cell(x + 1, y)) { nuclear@23: dmask &= ~TILE_EAST; nuclear@23: } nuclear@23: return dmask; nuclear@23: } nuclear@23: nuclear@49: void Level::set_player_position(const Vector3 &ppos) nuclear@49: { nuclear@49: player_pos = ppos; nuclear@49: } nuclear@49: nuclear@38: void Level::update(unsigned long msec, float dt) nuclear@38: { nuclear@38: for(auto cell : cell_list) { nuclear@38: cell->update(msec, dt); nuclear@38: } nuclear@49: nuclear@49: // activate the closest audio sources nuclear@49: if(cfg.sound) { nuclear@49: austatic.active_range(player_pos, 2.0); nuclear@49: } nuclear@38: } nuclear@38: nuclear@1: void Level::draw() const nuclear@1: { nuclear@1: glMatrixMode(GL_MODELVIEW); nuclear@1: nuclear@1: for(int i=0; idraw(dmask); nuclear@1: glPopMatrix(); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: nuclear@23: void Level::draw_lights() const nuclear@23: { nuclear@23: glMatrixMode(GL_MODELVIEW); nuclear@23: nuclear@23: for(int i=0; idraw_lights(dmask); nuclear@23: nuclear@23: glPopMatrix(); nuclear@23: } nuclear@23: } nuclear@23: } nuclear@23: } nuclear@23: nuclear@46: void Level::draw_post() const nuclear@46: { nuclear@46: glMatrixMode(GL_MODELVIEW); nuclear@46: nuclear@46: for(int i=0; idraw_post(dmask); nuclear@46: glPopMatrix(); nuclear@46: } nuclear@46: } nuclear@46: } nuclear@46: } nuclear@46: nuclear@1: void Level::draw_grid() const nuclear@1: { nuclear@1: float xlen = xsz * cell_size; nuclear@1: float ylen = ysz * cell_size; nuclear@1: nuclear@1: glPushAttrib(GL_ENABLE_BIT); nuclear@1: glDisable(GL_LIGHTING); nuclear@1: nuclear@1: glBegin(GL_LINES); nuclear@1: glColor3f(0.4, 0.4, 0.4); nuclear@1: nuclear@1: float y = -ylen / 2.0 - cell_size / 2.0; nuclear@1: for(int i=0; iget_sample(which); nuclear@48: } nuclear@48: nuclear@48: nuclear@38: GridCell::GridCell(Tile *tile) nuclear@5: { nuclear@5: if(tile) { nuclear@45: add_tile(tile); nuclear@5: } nuclear@50: nuclear@50: adjmask = TILE_ALL; nuclear@50: } nuclear@50: nuclear@50: void GridCell::set_adj_mask(unsigned int mask) nuclear@50: { nuclear@50: adjmask = mask; nuclear@50: } nuclear@50: nuclear@50: unsigned int GridCell::get_adj_mask() const nuclear@50: { nuclear@50: return adjmask; nuclear@5: } nuclear@5: nuclear@38: void GridCell::add_tile(Tile *tile) nuclear@1: { nuclear@45: if(!tile) { nuclear@45: return; nuclear@45: } nuclear@45: nuclear@1: tiles.push_back(tile); nuclear@45: nuclear@45: /* instanciate any particle systems */ nuclear@45: int num_psattr = tile->get_unique_psys_count(); nuclear@45: nuclear@45: for(int i=0; iget_unique_psys(i); nuclear@45: struct psys_emitter *emitter = psys_create(); nuclear@49: emitter->attr = *psattr; nuclear@45: psys.push_back(emitter); nuclear@45: } nuclear@1: } nuclear@1: nuclear@38: void GridCell::update(unsigned long msec, float dt) nuclear@38: { nuclear@45: for(auto ps : psys) { nuclear@45: psys_update(ps, (float)msec / 1000.0f); nuclear@45: } nuclear@38: } nuclear@38: nuclear@5: void GridCell::draw(unsigned int draw_mask) const nuclear@1: { nuclear@23: for(auto tile : tiles) { nuclear@23: tile->draw(draw_mask); nuclear@1: } nuclear@1: } nuclear@23: nuclear@23: void GridCell::draw_lights(unsigned int draw_mask) const nuclear@23: { nuclear@23: for(auto tile : tiles) { nuclear@23: tile->draw_lights(draw_mask); nuclear@23: } nuclear@23: } nuclear@45: nuclear@45: void GridCell::draw_post(unsigned int draw_mask) const nuclear@45: { nuclear@45: for(auto tile : tiles) { nuclear@45: tile->draw_post(draw_mask); nuclear@45: } nuclear@45: for(auto ps : psys) { nuclear@45: psys_draw(ps); nuclear@45: } nuclear@45: } nuclear@48: nuclear@48: AudioSample *GridCell::get_sample(int which) const nuclear@48: { nuclear@48: for(auto tile : tiles) { nuclear@48: AudioSample *s = tile->get_sample(which); nuclear@48: if(s) { nuclear@48: return s; nuclear@48: } nuclear@48: } nuclear@48: return 0; nuclear@48: } nuclear@49: nuclear@49: std::list GridCell::get_audio_sources() const nuclear@49: { nuclear@49: std::list srclist; nuclear@49: nuclear@49: for(auto tile : tiles) { nuclear@49: int num_src = tile->get_audio_source_count(); nuclear@49: for(int i=0; iget_audio_source(i)); nuclear@49: } nuclear@49: } nuclear@49: return srclist; nuclear@49: }